我正在处理非常大的内存映射文件(200+ GB),这些文件无法完全加载到内存中,并且是随机访问的。映射文件存储在固态驱动器阵列上,但我仍然发现,除非先前已完成相同的搜索,并且已使用的页面已被读入内存,否则一次访问所需的部分非常慢。
添加多个线程同时读取mmap中的变量可以显着提高速度,而且我无法达到测试改进的上限,但是拥有超过1000个线程会导致openmp抛出资源不可用的错误。 / p>
我也尝试过madvise来告诉内核需要的特定部分(MADV_WILLNEED),但是内核似乎没有足够快地对建议起作用。
我正在寻找一种方法来在实际使用之前立即同时预取所需的部分数据。读取变量(或包含它的映射文件的内存页大小的部分)的资源最少的方法是什么,将其强制进入内存而不会阻塞读取。
如果无法避免阻塞,那么运行更大数量的非常轻量级的线程来进行读取的方法也会有效。
答案 0 :(得分:2)
您好像回答了自己的问题。除了线程之外,您唯一的解决方案是遍历许多访问,您可以为每个访问执行madvise
。然后经过一些x madvise
s(比如10,000)后,你会回来并访问内存。但应注意,O / S确实 NOT 保证I / O将按照调用madvise的顺序完成。因此,O / S可以处理第一个madvise,然后跳到madvises的末尾,或者地址最低的那个,基本上无论它喜欢什么。根本没有办法将I / O大大加速到您想要的程度。
示例:
for(i=0; i < accesses + 10000; ++i)
{
madvise(access[i].addr, access[i].length, MADV_WILLNEED);
if(i >= 10000)
{
// Access location access[i-10000].addr
}
}
但是,您应该问自己,如果您正在使用随机访问,那么该文件的内存映射是否真的是您想要做的。似乎异步I / O会更有意义。