我需要读取/解析8192字节固定块中的大型二进制文件(4〜6 GB)。我当前的解决方案涉及使用单一生产者多消费者(SPMC)模式流式传输文件块。
编辑
文件大小= N * 8192字节
我需要做的就是对这8192个字节中的每个字节做某事。该文件仅需自上而下读取一次。
考虑到这应该是一个令人尴尬的并行问题,我想让 X 线程分别以相等的(文件大小/ X )大小范围读取。线程根本不需要相互通信。
我尝试生成 X 线程来打开相同的文件并寻求它们各自的部分进行处理,但是,由于HDD机械寻道,该解决方案似乎存在问题,并且其性能显然比SPMC解决方案差。
如果在SSD上使用此方法会不会有任何区别?
还是仅将内存映射整个文件并使用#pragma omp parallel for
处理块会更直接吗?我想我需要足够的RAM来执行此操作?
你有什么建议?
最佳答案
不要使用mmap()
每Linux Torvalds himself:
请注意,最后一次-仅使用一次数据对于mmap()
是不好的用例。
对于SSD上的文件,因为没有物理寻头 Action :
open()
打开文件一次,以获取一个int
文件描述符。 pread()
读取适当的8kB块。 pread()
在不使用lseek()
的情况下从指定的偏移量读取,并且不影响正在读取的文件的当前偏移量。 您可能需要比CPU内核更多的线程,因为每个线程上都会有大量的IO等待。
对于机械磁盘上的文件:
您要最小化机械磁盘上的磁头搜寻。
一次打开文件,使用具有直接IO的
open()
(假设Linux为open( filename, O_RDONLY | O_DIRECT );
)绕过页面缓存(由于您将流式传输文件并且从不重新读取文件的任何部分,因此页面缓存对您不利)放入N个页面对齐的缓冲区之一。
缓冲回到读取线程。
您需要尝试使用适当的
read()
大小,辅助线程数和传递的缓冲区数。更大的read()
会更有效,但是更大的缓冲区大小会使内存需求更大,并使从工作线程取回该缓冲区的延迟变得更加不可预测。您希望尽可能少地复制数据,因此希望工作线程直接在从文件读取的缓冲区上工作。