1

巨大な nxn 行列 (n > 100000) を計算し、後で使用するためにメモリに保存する必要があります。1 つの要素の計算は非常にコストがかかるため (数 1000 フロップとメモリ アクセス)、その場で計算することはできません。ただし、一度だけ計算する必要があり、後で変更する必要はありません。また、システムに十分なスワップ領域があるとは限りません。そのため、キャッシュ ファイルを作成し、mmap を使用してメモリにマップすることにしました。

int createCacheFile(std::size_t filesize, std::string const& filename){
    //create empty file
    int fileDescriptor = open(filename.c_str(), O_RDWR | O_CREAT | O_TRUNC, (mode_t)0600);
    //stretch to desired size
    lseek(fileDescriptor, filesize-1, SEEK_SET);
    return fileDescriptor;
}

//...
std::size_t n = 100000;
std::size_t fileSize = n*n*sizeof(float);
int fileDescriptor = createCacheFile(filesize,"matrix.cache");
float* memory = (float*) mmap(0, filesize, PROT_READ | PROT_WRITE, MAP_SHARED, fileDescriptor, 0);

//and now fill it...

パフォーマンスを比較したいと思い、小さな n=10000 を試し、malloc、mmap を MAP_ANONYMOUS および上記の実装と比較しました。この n の場合、行列は RAM に完全に収まります。malloc と MAP_ANONYMOUS は非常に似通った結果をもたらしますが、ファイルによって裏付けられた行列を計算すると、約 10 倍のペナルティが発生します。ファイルに内容を安全に書き込めるように、プログラムはカーネルによって定期的に停止されているようです。プログラムを停止せずにセクションを書き込むことができるというヒントをカーネルに与えるために、既に計算したマトリックスの部分で msync と mprotect を使用してこれを解決しようとしましたが、何も役に立ちませんでした。

これを修正する方法はありますか?

4

1 に答える 1

0

また、 madvise(2) syscall を使用して、あまり役に立たないページについてカーネルに通知することもできます (おそらくMADV_SEQUENTIALまたはMADV_DONTNEED...)。おそらく、posix_fadvise(2) syscall がファイル セグメントに役立つかもしれません。最終的にreadhead(2) (ブロックしているため、別のスレッドで) も役立つ場合があります。

そして、ファイルは高速なファイルシステム、おそらくtmpfs1 つにある可能性があります....

おそらく、高速ディスク (SSD) でのスワップも役立つ場合があります。swapon(2) syscall (およびswaponコマンド)。

于 2013-10-14T12:33:19.350 に答える