我的程序运行速度比我想要的慢。
我做了一些分析,我发现这个部分占用了绝大部分的处理时间
DO K = 0, K_MAX
WRITE(EIGENVALUES_IO, *) K * 0.001 * PI, (W_UP(J), J=1, ATOM_COUNT)
DCMPLXW_UP(:) = DCMPLX(W_UP(:))
DO E = 1, ENERGY_STEPS
ENERGY = MIN_ENERGY + ENERGY_STEP * REAL(E, DP)
ZV = DCMPLX(ENERGY, DELTA)
ON_SITE_SINGLE = DCMPLX(0.0_DP)
DO Q = 1, ATOM_COUNT
DO J = 1, ATOM_COUNT
ON_SITE_SINGLE(J) = ON_SITE_SINGLE(J) + (MATRIX_UP(J, Q) * MATRIX_UP_CONJG(J, Q)) / (ZV - DCMPLXW_UP(Q))
END DO
END DO
DOS_DOWN(E) = DOS_DOWN(E) - WEIGHTS(K) * SUM(IMAG(ON_SITE_SINGLE))
END DO
END DO
该行
ON_SITE_SINGLE(J) = ON_SITE_SINGLE(J) + (MATRIX_UP(J, Q) * MATRIX_UP_CONJG(J, Q)) / (ZV - DCMPLXW_UP(Q))
是那个正在造成伤害的人。
我在这方面相当新手,有什么方法可以加快速度吗? AFAIK,同样的原则适用于C,所以你们的任何帮助也都会很好。
数组都是COMPLEX
K_MAX是1000
ENERGY_STEPS是1000
ATOM_COUNT很低(<50)
答案 0 :(得分:5)
我的所有节目都比我想要的慢。在所有(好的,不是全部,但很多)我的科学程序中都有一个深度循环嵌套,其中最内层的语句占用了大部分的计算时间。通常我希望我的计算的90%以上被这些陈述所占用。你内心的声明正在执行2.5x10 ^ 9次,所以你应该期望它占用总时间的很大一部分。
记住这一点我建议你:
a)采用@Alexandre的建议来使用BLAS而不是自制的矩阵向量乘法。
b)忽略@Yuval关于将操作提升到循环之外的建议 - 如果你将优化调高,一个好的Fortran编译器会为你做这个(警告:这是一个自我实现的预言,就像编译器没有这不是一个好的。如今,我希望从好的Fortran中获得很多其他的优化,参见(d)。 (我不希望编译器优化内存访问,我希望从BLAS中获得。)c)形成一个现实的期望,即你应该从你的程序中获得多少性能。如果您获得的持续FLOP率超过CPU额定性能的10%,那么您的表现非常好,应该花时间做其他事情而不是优化。
d)仔细阅读您的编译器文档。确保您了解优化标志实际执行的操作。确保为正在使用的CPU生成代码,而不是为某些旧版本生成代码。如果可用,请切换快速矢量操作。所有这一切。
e)开始并行化。 OpenMP是一个很好的起点,正如@Nicolas所说,学习曲线起初非常温和。
哦,您似乎遵循的建议0是衡量代码的性能并衡量您所做的任何更改的影响。
答案 1 :(得分:1)
你分开的因素,即
(ZV - DCMPLXW_UP(Q))
不依赖于J,仅依赖于Q. 因此,我会将此计算移至Q循环。 更好的是,计算:
1/(ZV - DCMPLXW_UP(Q))
在外部循环中,并乘以它而不是在循环内部分割 (AFAIR,乘法比分裂快)。 另外,检查矩阵数据结构是否与循环相对应(循环尽可能地遍历内存的连续部分)。 通常,如果您可以改进算法,这将是最大的运行时间改进。
Programming Pearls对类似的优化有很好的描述。
答案 2 :(得分:1)
如果常规代码优化让您陷入困境,您可以尝试OpenMP,这是为C和Fortran进行并行编程的API。在循环之前,您在代码中插入了一些指令,“预编译器”样式,并且它将在不同进程之间分割大量循环。
您可能需要尝试几条说明。例如:
#pragma omp parallel for
/* Loop here */
这是一个非常完整的API,您可以根据许多参数,共享变量和不同的并行拆分技术拆分所有内容。您还可以指定希望OpenMP创建的进程数,核心数等。
通过一些调整,您最终会找到一种提高计算速度的解决方案。
答案 3 :(得分:1)
请将BLAS用于'vactor plus matrix-vector multiplies'。你基本上是在
行中这样做的ON_SITE_SINGLE(J) = ON_SITE_SINGLE(J) + (MATRIX_UP(J, Q) * MATRIX_UP_CONJG(J, Q)) / (ZV - DCMPLXW_UP(Q))
通过精心调整的BLAS库,您可以获得显着的改进。