2016-11-22 76 views
2

我有一个fortran代码用于计算与我所做的工作相关的一些数量。代码本身涉及几个嵌套循环,并且需要很少的磁盘I/O。每当代码被修改时,我都会针对一组输入文件运行它(只是为了确保它正常工作)。为了长话短说,最近的更新将程序的运行时间增加了四倍,并且使用一个CPU连续运行每个输入文件需要大约45分钟(等待很长时间,只是为了看看是否有什么被打破)。因此,我想在系统上的4个cpus上并行运行每个输入文件。我一直试图通过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 [程式名称] {来源}

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

+0

您确定您使用的是GNU并行Shell吗?如果没有,请检查您的标签的描述,并仅使用适用的标签。另外,bash标签是否真的相关?一些代码可能是必要的。 –

+0

是的,我尝试使用GNU并行作为解决方案。我也尝试过使用xargs,等待,并简单地在后台启动多个实例。 –

+0

你有四个硬件核心吗?你的程序内存带宽很重吗?请提供有关您的硬件和示例程序的更多具体信息。 – IanH

回答

1

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

  • 超线程 GNU/Linux将看到超线程作为核心尽管它已经不是一个真正的核心。它更像是核心的30%。

  • 共享缓存如果你的核心共享相同的缓存和你的程序的单个实例采用全共享缓存,然后如果你运行多个实例,你会得到更多的缓存未命中。

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

  • Turbo模式许多CPU可以以比多线程更高的时钟速率运行单线程。这是由于热量。

所有这些都将表现出相同的症状:运行一个线程会比每多线程的速度较快,但多线程的总吞吐量将超过单线程更大。

虽然我必须承认你的情况听起来很极端:利用4芯我本来期望的至少2

的加速如何查明原因

  • 超线程使用taskset选择要运行的核心。如果使用4个内核中的2个,如果使用#1 + 2或#1 + 3,是否有区别?

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

  • 共享缓存不知道如何做到这一点,但如果它在某种程度上可以禁用缓存,然后1个作业比较2个工作在相同的低频运行应该给的指示。

+0

-fbounds-check不会使代码运行得更快,而其他的一些 - 也会减慢速度。我不知道如果没有为此专门设计的少量产品,其中一个缓存未命中是如何工作的。 – Holmz

+0

使用'taskset'并强制四个实例在两个CPU上运行将导致比四个CPU上的四个实例(12.5分钟与11分钟相比)稍长的时间。当四个实例在两个CPU上运行时,CPU时间显着缩短(6.25分钟,而10.67分钟)。 –

+0

你可以在2个内核上运行2个任务,但可以尝试内核#1 + 2,然后尝试#1 + 3。有区别吗? –

相关问题