我有一个fortran代码,我用来计算与我工作相关的一些数量。代码本身涉及多个嵌套循环,并且需要非常少的磁盘I / O.每当修改代码时,我都会针对一组几个输入文件运行它(只是为了确保它正常工作)。
总而言之,最近的更新将程序的运行时间增加了大约四倍,并且使用一个CPU串行运行每个输入文件大约需要45分钟(等待很长时间,只需看是否有任何事情被打破了。因此,我想在系统上的4个cpu中并行运行每个输入文件。我一直试图通过bash脚本实现并行性。
我注意到的有趣的事情是,当只有一个程序实例在机器上运行时,需要大约三分半钟的时间才能通过其中一个输入文件。当程序的四个实例正在运行时,通过一个输入文件需要更多的时间(从11分半钟开始)(将我的总运行时间从大约45分钟缩短到36分钟 - 这是一个改进,是的,但不是我所拥有的希望)。
我尝试使用gnu parallel,xargs,wait来实现并行性,甚至只是从命令行在后台启动程序的四个实例。无论实例如何启动,我都看到同样的减速。因此,我很确定这不是shell脚本的工件,而是程序本身正在发生的事情。
我尝试在关闭调试符号的情况下重建程序,并使用静态链接。这些都没有任何明显的影响。我目前正在使用以下选项构建程序:
$ gfortran -Wall -g -O3 -fbacktrace -ffpe-trap =无效,零,溢出,下溢,非正常-fbounds-check -finit-real = nan -finit-integer = nan -o [program name] {源}
非常感谢任何帮助或指导!
答案 0 :(得分:1)
在现代CPU上,您无法预期线性加速。有几个原因:
超线程 GNU / Linux将超线程视为核心事件,尽管它不是真正的核心。它更像是核心的30%。
共享缓存如果您的内核共享相同的缓存,并且您的程序的单个实例使用完整的共享缓存,那么如果运行更多实例,您将获得更多缓存未命中。
内存带宽与共享缓存类似的情况是共享内存带宽。如果单个线程使用全内存带宽,则并行运行更多作业可能会占用带宽。这可以通过在NUMA上运行来解决,其中每个CPU都有一些比其他RAM“更接近”的RAM。
Turbo模式许多CPU可以以比多线程更高的时钟速率运行单个线程。这是由于热量。
所有这些都会出现相同的症状:运行单个线程将比多个线程中的每个线程都快,但多个线程的总吞吐量将大于单个线程。
虽然我必须承认你的情况听起来很极端:有4个核心,我预计会有至少2的加速。
如何识别原因
超线程使用taskset
选择要运行的核心。如果使用#1 + 2或#1 + 3,如果使用4个核心中的2个是否有任何区别?
Turbo模式使用cpufreq-set
强制降低频率。如果您并行运行1个或2个作业,速度是否相同?
共享缓存不确定如何执行此操作,但如果以某种方式可以禁用缓存,则将1个作业与2个以相同低频运行的作业进行比较应该给出指示