我需要读取/解析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 );)绕过页面缓存(由于您将流式传输文件并且从不重新读取文件的任何部分,因此页面缓存对您不利)
  • 使用单个生产者线程读取大块数据(例如64k至1MB +)
    放入N个页面对齐的缓冲区之一。
  • 读取缓冲区时,将其传递给工作线程,然后读取以填充下一个缓冲区
  • 当所有工作程序都使用了缓冲区的一部分时,请传递
    缓冲回到读取线程。

  • 您需要尝试使用适当的read()大小,辅助线程数和传递的缓冲区数。更大的read()会更有效,但是更大的缓冲区大小会使内存需求更大,并使从工作线程取回该缓冲区的延迟变得更加不可预测。您希望尽可能少地复制数据,因此希望工作线程直接在从文件读取的缓冲区上工作。

    09-16 08:42