【问题标题】:Serial program runs slower with multiple instances or in parallel串行程序在多个实例或并行时运行速度较慢
【发布时间】:2016-11-22 22:47:32
【问题描述】:

我有一个 fortran 代码,用于计算与我所做的工作相关的一些数量。代码本身涉及多个嵌套循环,并且需要很少的磁盘 I/O。每当修改代码时,我都会针对一组几个输入文件运行它(只是为了确保它正常工作)。

长话短说,最近的更新将程序的运行时间增加了大约四倍,而用一个 CPU 串行运行每个输入文件大约需要 45 分钟(等待的时间很长,只是看看有没有坏掉的东西)。因此,我想在系统上的 4 个 CPU 上并行运行每个输入文件。我一直在尝试通过 bash 脚本实现并行性。

我注意到的有趣的事情是,当机器上只有一个程序实例正在运行时,它需要大约三分半钟才能完成一个输入文件。当程序的四个实例正在运行时,通过一个输入文件需要大约 11 分钟半的时间(使我的总运行时间从大约 45 分钟减少到 36 分钟 - 是的,这是一个改进,但不是我所拥有的希望)。

我尝试过使用 gnu parallel、xargs、wait 甚至只是从命令行在后台启动程序的四个实例来实现并行性。无论实例是如何启动的,我都看到同样的速度变慢。因此,我很确定这不是 shell 脚本的产物,而是程序本身发生的事情。

我尝试在关闭调试符号的情况下重建程序,并使用静态链接。这些都没有任何明显的影响。我目前正在使用以下选项构建程序:

$ gfortran -Wall -g -O3 -fbacktrace -ffpe-trap=invalid,zero,overflow,underflow,denormal -fbounds-check -finit-real=nan -finit-integer=nan -o [程序名] {来源}

任何帮助或指导将不胜感激!

【问题讨论】:

  • 您确定您使用的是 GNU Parallel Shell 吗?如果不是,请检查标签的描述并仅使用适用的那些。另外,bash 标签真的相关吗?可能需要一些代码。
  • 是的,我尝试使用 GNU 并行作为解决方案。我也尝试过使用 xargs,等待,然后简单地在后台启动多个实例。
  • 你有四个硬件核心吗?您的程序内存带宽重吗?请提供有关您的硬件和示例程序的更具体信息。
  • 您的程序可能不受 CPU 限制,但受内存带宽限制或可能依赖某些共享资源,即 NFS 可能正在序列化文件访问。你有什么样的 CPU?
  • CPU 是 Intel i5-6500,四核 @ 3.2 GHz。我只是在单个 CPU 上运行,所以 NFS 不应该干扰。内存带宽是有意义的,这可能是瓶颈所在。

标签: bash parallel-processing fortran gfortran gnu-parallel


【解决方案1】:

在现代 CPU 上,您不能期望线性加速。有几个原因:

  • 超线程 GNU/Linux 将超线程视为核心,即使它不是真正的核心。它更像是核心的 30%。

  • 共享缓存如果您的内核共享相同的缓存并且您的程序的单个实例使用完整的共享缓存,那么如果您运行更多实例,您将获得更多的缓存未命中。 p>

  • 内存带宽 与共享缓存类似的情况是共享内存带宽。如果单个线程使用全部内存带宽,那么并行运行更多作业可能会阻塞带宽。这可以通过在 NUMA 上运行来部分解决,其中每个 CPU 都有一些比其他 RAM“更近”的 RAM。

  • Turbo 模式 许多 CPU 可以以比多线程更高的时钟频率运行单线程。这是因为热。

所有这些都会表现出相同的症状:运行单个线程会比多个线程中的每一个都快,但多个线程的总吞吐量会大于单个线程。

虽然我必须承认您的情况听起来很极端:如果使用 4 个内核,我预计至少可以加速 2 个。

如何确定原因

  • 超线程使用taskset 选择要在哪些内核上运行。如果你使用 4 个核心中的 2 个,使用 #1+2 或 #1+3 有什么区别吗?

  • Turbo 模式 使用cpufreq-set 强制降低频率。如果您并行运行 1 个或 2 个作业,现在的速度是否相同?

  • 共享缓存 不确定如何执行此操作,但如果可以以某种方式禁用缓存,那么将 1 个作业与以相同低频运行的 2 个作业进行比较应该给出一个指示.

【讨论】:

  • -fbounds-check 不会使代码运行得更快,而其他一些 -Wall 也会减慢速度。如果没有专门为此设计的少数产品,我不知道缓存未命中是如何工作的。
  • 使用 taskset 并强制四个实例在两个 CPU 上运行会导致时钟时间比四个 CPU 上的四个实例稍长(12.5 分钟对比 11 分钟)。当四个实例在两个 CPU 上运行时,CPU 时间显着缩短(6.25 分钟对比 10.67 分钟)。
  • 你能在 2 个核心上运行 2 个作业吗,但先尝试核心 #1+2,然后再尝试 #1+3。有区别吗?
  • 2 个作业 2 个核心:使用核心 1+2 整个测试输入集在 36 分 14 秒内完成(相比之下,在 4 个核心上运行 4 个作业约 36 分钟,在 1 个核心上运行 1 个作业需要 44 分钟核)。使用核心 1+3,该组在 39 分 6 秒内完成。
猜你喜欢
  • 1970-01-01
  • 2023-02-16
  • 2010-12-08
  • 1970-01-01
  • 1970-01-01
  • 2015-11-21
  • 1970-01-01
  • 2017-05-25
  • 1970-01-01
相关资源
最近更新 更多