MPI 并行化有助于多次读取大量数据
MPI parallelization help for reading a large amount of data multiple times
有人要求我并行化现有的 c 程序以减少其运行时间。
我只有一些(非常有限的)使用基本 MPI 的经验(而且我所有的编程知识都是自学的,所以有点参差不齐)。我目前正在尝试找出最佳的并行化方法。
目前,在主循环的每次迭代期间(M = 迭代次数),程序按顺序访问一组输入文件(N = 文件数)——每个文件的长度都不同。读取所有输入文件后,程序对数据进行排序并更新一组输出文件。 N和M一开始都是已知的,N总是大于M。实际上,N太大无法将所有输入数据读入内存,所以每次读取文件时,只有与主循环相关的信息保留迭代。
我相信我可以使每个主循环迭代独立,但每次迭代仍需要访问所有 N 个文件。使用 OpenMPI(技术上 OpenRTE 1.6.2 运行 on Rocks-即 RedHat Linux)并行化该程序的最佳方法是什么?
我的第一个想法是简单地跨多个线程拆分输入文件的读入——每个线程处理一个文件子集,然后在最后对输入进行排序。
我的第二个想法是跨线程拆分主 M 循环,这样可以更好地利用 MPI。但是这种方法是否需要在每个线程中复制所有输入文件(以避免读取冲突)?如果是这样,我担心复制文件可能会抵消并行化主循环所获得的任何时间。此外,除了为每种方法构建测试程序之外,是否有更简单的方法来确定哪种方法更快?
编辑:文件系统是NFS。
阅读评论后,我回去 运行 对代码进行了一些测试。该程序将 93% 的运行时间用于读取数据。从上面所说的看来,单独的并行化似乎并不是最好的解决方案。在这一点上,似乎有必要真正研究程序的计算并尽量减少读入要求。
非常感谢您的回复。
根据评论回复,文件系统是 NFS,您的意思是您正在通过网络读取文件?如果并行化大约 N 个文件,这可能会出现很大问题。如果 N 太大,您可能会超过一次打开文件指针的最大数量,这通常在 /etc/security/limits.conf 中定义。
我知道 shell 类型是 csh 还是 tcsh,然后如果您在提示符下键入 limit
,它将显示所有这些值。抱歉,我忘记了在 bash shell 中显示的命令。
然后,您还会冒 NFS 过载以及 LAN 或 WAN 带宽问题的风险。如果您的网络速度为 100 mbps,那么每秒最多只有 12 兆字节的数据。如果您不检查它,您怎么知道它不是一个真正以千字节/秒为单位的值?
如果程序 运行 时间的最大原因是读入数据,您可能对此无能为力。除了 NFS 问题,我建议考虑如何命令硬盘驱动器(无论它位于何处)读取每个 chunk/file 数据。我认为通常最好只有一个文件指针尽可能按顺序从磁盘驱动器读取数据,这将由您决定如何缓冲要在程序中使用的数据。如果您有足够的 RAM,则需要进行计算和计算。如果不是,那将是您需要增加的,否则您将被迫依赖磁盘i/o,这是一个杀手。
与 NFS 并行 I/O 是一项愚蠢的任务。 MPI 实现会尽力而为,但 NFS——除了串行之外——还提供了可怕的一致性语义。客户端写入在某个不确定的时间显示给其他进程。您可以关闭每个操作的缓存和 fcntl-lock,但您仍然无法获得预期的一致性。
MPI 实现提供 NFS 支持,因为 NFS 无处不在,但您可以部署 PVFS / OrangeFS 之类的东西,如果分析确定 I/O 实际上是您的重要瓶颈。
有人要求我并行化现有的 c 程序以减少其运行时间。 我只有一些(非常有限的)使用基本 MPI 的经验(而且我所有的编程知识都是自学的,所以有点参差不齐)。我目前正在尝试找出最佳的并行化方法。
目前,在主循环的每次迭代期间(M = 迭代次数),程序按顺序访问一组输入文件(N = 文件数)——每个文件的长度都不同。读取所有输入文件后,程序对数据进行排序并更新一组输出文件。 N和M一开始都是已知的,N总是大于M。实际上,N太大无法将所有输入数据读入内存,所以每次读取文件时,只有与主循环相关的信息保留迭代。
我相信我可以使每个主循环迭代独立,但每次迭代仍需要访问所有 N 个文件。使用 OpenMPI(技术上 OpenRTE 1.6.2 运行 on Rocks-即 RedHat Linux)并行化该程序的最佳方法是什么?
我的第一个想法是简单地跨多个线程拆分输入文件的读入——每个线程处理一个文件子集,然后在最后对输入进行排序。
我的第二个想法是跨线程拆分主 M 循环,这样可以更好地利用 MPI。但是这种方法是否需要在每个线程中复制所有输入文件(以避免读取冲突)?如果是这样,我担心复制文件可能会抵消并行化主循环所获得的任何时间。此外,除了为每种方法构建测试程序之外,是否有更简单的方法来确定哪种方法更快?
编辑:文件系统是NFS。
阅读评论后,我回去 运行 对代码进行了一些测试。该程序将 93% 的运行时间用于读取数据。从上面所说的看来,单独的并行化似乎并不是最好的解决方案。在这一点上,似乎有必要真正研究程序的计算并尽量减少读入要求。
非常感谢您的回复。
根据评论回复,文件系统是 NFS,您的意思是您正在通过网络读取文件?如果并行化大约 N 个文件,这可能会出现很大问题。如果 N 太大,您可能会超过一次打开文件指针的最大数量,这通常在 /etc/security/limits.conf 中定义。
我知道 shell 类型是 csh 还是 tcsh,然后如果您在提示符下键入 limit
,它将显示所有这些值。抱歉,我忘记了在 bash shell 中显示的命令。
然后,您还会冒 NFS 过载以及 LAN 或 WAN 带宽问题的风险。如果您的网络速度为 100 mbps,那么每秒最多只有 12 兆字节的数据。如果您不检查它,您怎么知道它不是一个真正以千字节/秒为单位的值?
如果程序 运行 时间的最大原因是读入数据,您可能对此无能为力。除了 NFS 问题,我建议考虑如何命令硬盘驱动器(无论它位于何处)读取每个 chunk/file 数据。我认为通常最好只有一个文件指针尽可能按顺序从磁盘驱动器读取数据,这将由您决定如何缓冲要在程序中使用的数据。如果您有足够的 RAM,则需要进行计算和计算。如果不是,那将是您需要增加的,否则您将被迫依赖磁盘i/o,这是一个杀手。
与 NFS 并行 I/O 是一项愚蠢的任务。 MPI 实现会尽力而为,但 NFS——除了串行之外——还提供了可怕的一致性语义。客户端写入在某个不确定的时间显示给其他进程。您可以关闭每个操作的缓存和 fcntl-lock,但您仍然无法获得预期的一致性。
MPI 实现提供 NFS 支持,因为 NFS 无处不在,但您可以部署 PVFS / OrangeFS 之类的东西,如果分析确定 I/O 实际上是您的重要瓶颈。