我正在编写一个代码,计算所有粒子之间的距离,并计算它们之间的力。代码如下:
void calcCoulombicRepForces(double xc[], double yc[], double zc[], double fx[], double fy[], double fz[], int Np, double q1q2){
double x1,y1,z1,xhat,yhat,zhat,dist,distcube;
for (int i = 0; i < Np; i++){
double sumX = 0.0; double sumY = 0.0; double sumZ = 0.0;
x1 = xc[i];
y1 = yc[i];
z1 = zc[i];
for (int j = 0; j < Np; j++){
xhat = xc[j]-x1;
yhat = yc[j]-y1;
zhat = zc[j]-z1;
dist = sqrt(xhat*xhat + yhat*yhat + zhat*zhat);
distcube = dist*dist*dist;
sumX += xhat/distcube;
sumY += yhat/distcube;
sumZ += zhat/distcube;
}
fx[i] = -q1q2*sumX;
fy[i] = -q1q2*sumY;
fz[i] = -q1q2*sumZ;
}
}
xc、yc和zc是坐标。fx、fy和fz是力。这里每个数组的大小为Np ~ 58000个元素。
代码工作正常,但该函数所花费的99%的时间都花在写入/更新数组内部的值上,即这三行
fx[i] = -q1q2*sumX;
fy[i] = -q1q2*sumY;
fz[i] = -q1q2*sumZ;
我在某个地方读到它可能是因为它试图从更高级别的缓存或RAM访问数组fx,fy和fz。如果是这样,有没有一种方法可以优化这三行,使数组写入/更新变得更快?如果没有,我在这里做错了什么?如果我错过了一些我应该包括的东西,请让我知道。
2条答案
按热度按时间7fyelxc51#
你的基准测试方法只会产生无意义的结果。
如果你去掉了这三个赋值,那么函数就没有任何副作用了,它也不会返回任何东西,所以编译器会优化掉整个函数体。
这就是为什么显然所有的时间都花在了三个赋值上。
rkue9o1l2#
你计算距离(和其他值)的次数太多了。你应该只为每对点计算一次。这段代码应该会对你有所帮助。它应该会在
~2x
时间内运行得更快,因为你的函数处理的是n * (n -1)
对,而我的函数将处理(n * (n -1) /2)
对(所有唯一的对只进动一次)。此外,正如有人在评论中提到的,制作一个结构体来保存这些xyz和每个点的剩余值,然后用这些结构体的数组来加速代码。