【发布时间】:2015-11-17 20:18:26
【问题描述】:
我正在尝试优化 C 中的代码,特别是占用总执行时间近 99.99% 的关键循环。这是那个循环:
#pragma omp parallel shared(NTOT,i) num_threads(4)
{
# pragma omp for private(dx,dy,d,j,V,E,F,G) reduction(+:dU) nowait
for(j = 1; j <= NTOT; j++){
if(j == i) continue;
dx = (X[j][0]-X[i][0])*a;
dy = (X[j][1]-X[i][1])*a;
d = sqrt(dx*dx+dy*dy);
V = (D/(d*d*d))*(dS[0]*spin[2*j-2]+dS[1]*spin[2*j-1]);
E = dS[0]*dx+dS[1]*dy;
F = spin[2*j-2]*dx+spin[2*j-1]*dy;
G = -3*(D/(d*d*d*d*d))*E*F;
dU += (V+G);
}
}
所有变量都是本地的。 NTOT=3600 的循环需要 0.7 秒,这是一个很长的时间,尤其是当我必须在整个程序中执行 500,000 次时,导致在此循环中花费了 97 小时。我的问题是这个循环中是否还有其他需要优化的地方?
我的电脑的处理器是 Intel core i5,带有 4 个 CPU(4X1600Mhz) 和 3072K L3 缓存。
【问题讨论】:
-
正如发布的那样,您的代码有一个不平衡的
{。你有if(j == i) continue;。你的意思是if(j == i) {?请编辑您的帖子,因为无法判断您是否希望在j == i或j != i上执行循环主体 -
我希望 i=j 不执行循环体,因为在这种情况下 d 将等于 0,并且我将有浮点异常。也出于身体原因。
-
一种可以优化的方法,提供dx和dy总是整数是建立一个sqrt数组表,只要dx和dy不是很大的数字,它会占用一点内存,但会提供很大的速度。
-
是的,它可能是。但它们将是巨大的标签[NTOT][NTOT],无法在缓存中处理
-
你能发布更多你的代码吗? (例如所有变量的定义和使用)。我想这是用
for (i = 1; i <= NTOT; ++i)包裹的?你可以通过a预缩放X以创建Xa数组吗?如果您发布了足够多的代码,我可以下载它,并且我有一个自定义基准套件,可以对您的每一行代码进行详细分析。无论openmp如何,我已经可以看到一些可能的优化。另外,一些测试数据或生成它的方法怎么样。 sqrt 看起来像一个热点,但您可能会受到内存限制(例如,获取 X 和自旋数组需要更多时间)。测量就知道了。
标签: c optimization