处理数百万种排列

Handling millions of permutations

本文关键字:排列 数百万 处理      更新时间:2023-10-16

我试图计算数百万(108)的20x20布尔矩阵的排列。我能很快地算出来。之后,我需要使用标准输出或将其存储到文件中。你认为有可能在4小时内处理这么多的数据吗?

1018操作?让我们看看…你的电脑可能不会比每秒10个9到10个10指令更好。所以,你至少需要109到1010秒来完成1018操作,这是超过31年的时间。这样够快吗?你的电脑在31年的使用过程中还能使用吗?

一个20x20的布尔矩阵是400比特= 50字节* 10^8个排列= 5 * 10^9个字节= 5gb

对于3gb/s的SATA驱动器,您的下限为

5 GB = 40 GBit / 3 GBit/s ~ 13.3 sec

在我5年的旧电脑上,复制一个1.9 GB的文件需要82秒。这包括读写1.9 GB。因此,写10^8 400位值的二进制表示的上限大约是215秒。

编写ASCII表示将使用大约50gb,并花费大约8-10倍的时间,大约2150秒。这将比35分钟多一点。

综上所述,我认为在不到4小时的时间里写这么多数据是可能的。

:

我没有5gb的主内存来保存所有的排列。因此,我多次写入相同的数据。用

调用
./a.out a.bin 100

写入大约4.7 gb的数据,在我的机器上花费114秒。

#include <fstream>
struct matrix {
    unsigned char data[50];
    void write(std::ostream &f) {
        f.write(reinterpret_cast<char*>(data), sizeof(data));
    }
};
static const unsigned long N = 1000000;
matrix permutations[N];
int main(int argc, char **argv)
{
    // prevent sparse file
    for (unsigned long j = 0; j < N; ++j)
        permutations[j].data[j % 50] = 1;
    std::ofstream f(argv[1]);
    f.sync_with_stdio(false);
    unsigned long m = std::stoi(argv[2]);
    for (unsigned long i = 0; i < m; ++i) {
        for (unsigned long j = 0; j < N; ++j)
            permutations[j].write(f);
    }
    return 0;
}

使用ASCII表示将看起来类似

struct matrix {
    unsigned char data[50];
    friend std::ostream &operator<<(std::ostream &f, const matrix &x) {
        static int bits[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
        for (int i = 0; i < 50; ++i) {
            for (int j = 0; j < 8; ++j)
                f << (x.data[i] & bits[j] ? '1' : '0');
        }
        return f;
    }
};

main中的for循环

for (unsigned long i = 0; i < m; ++i) {
    for (unsigned long j = 0; j < N; ++j)
        f << permutations[j] << 'n';
}

写入10^7个排列占用了大约3.8 GiB的磁盘空间,耗时约4:41分钟。写10倍的东西可能需要一个小时或90分钟。在当前硬件上,这应该更快。

将10^8个排列每个打包成50字节(400位),它将提供大约5gb的数据。在普通磁盘上,应该可以将这些数据以每秒100mb的速度存储到磁盘上的文件中,这样5gb数据的总写入时间为50秒。

因此,只要您能够足够快地生成排列,那么在不到指定的4小时内将它们存储到文件中应该不成问题。