我必须计算一个巨大的nxn矩阵(n>100000),并以某种方式将其存储在内存中以供进一步使用。一个元素的计算是相当昂贵的(只有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来解决这个问题,我已经计算了矩阵的一些部分,给内核一个提示,它可以编写这些部分,而不必停止程序,但没有任何帮助。
有办法解决这个问题吗?
最佳答案
您还可以使用madvise(2)系统调用来通知内核一些不太有用的页面(可能使用MADV_SEQUENTIAL
或MADV_DONTNEED
…)。也许posix_fadvise(2)系统调用可能对文件段有帮助。最终readahead(2)(在另一个线程中,因为它正在阻塞)可能也会有帮助。
文件可能位于一个快速的文件系统中,可能是一个tmpfs
文件系统…
或许在快速磁盘(ssd)上交换也很有用。swapon(2)系统调用(和swapon
命令)。
关于c++ - 使用mmap时性能下降,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19358421/