在我的论文中,我运行了一个简单的代码,用于在 Xeon Phi 协处理器上研究 Lennard Jones 系统,并尝试对其进行矢量化并研究执行时间的变化。
我特别使用的机器有 61 个内核,具有 32 kB 的 L1 缓存和 512 kB 的 L2 缓存,向量寄存器可以存储 512 位。
我使用和不使用单元列表方法实现了代码,并使用了不同数量的粒子,特别是从 512 到 16384,每次都加倍。
位置和力被存储在三个不同的向量中(rx,ry,rz 和 fx,fy,fz)。
在没有单元格列表的情况下,我有很好的结果,但在另一种情况下,我有一些奇怪的结果。
细胞列表和粒子数量之间的依赖关系应该与实施的细胞列表方法成线性关系,实际上我得到了一条直线,绘制了粒子数量上的时间,但是 N=8192 和 N=16384 的时间执行力要高得多。
我尝试对这些值附近的 N 值进行一些计算,但缩放比例对于其他数字是正确的,只有这两个数字存在问题。
为了清楚起见,我报告了一些价值:
N Time
512 6.14995
1024 11.1381
2048 23.1964
4096 51.9393
6144 78.1251
8192 389.724
10240 144.173
12288 167.772
14336 209.669
16384 822.131
我认为这是一个技术问题,但我真的不知道为什么会发生这种情况。
我还观察到使用矢量化的变化非常低,没有细胞列表我观察到的变化是 4 倍,或多或少,但使用细胞列表它只有 1.5 倍左右。
问题:
有人知道问题可能是什么吗?为什么这些特定值很奇怪,为什么矢量化增益如此之低?
我的教授告诉我,可能会发生某些值在执行时显示奇怪的结果,有人观察到这样的事情吗?
非常感谢。
下面我报告了评估力的主循环,简而言之,执行的主要部分是使用单元列表实现的。
for(vcy=0; vcy<ncell; vcy++){
for(vcx=0; vcx<ncell; vcx++){
previouspartc=0;
// Central cell index
c=vcx*ncell+vcy;
// Define previouspart
for(p=1; p<=c; p++) previouspartc=previouspartc+npart[p-1];
// Loop over central cell's particles
for(i=0; i<npart[c]-1; i++){
for(j=i+1; j<npart[c]; j++){
ftempx=0.; ftempy=0.;
dx =rx1[previouspartc+i]-rx1[previouspartc+j];
dy =ry1[previouspartc+i]-ry1[previouspartc+j];
dx = (dx + 0.5*dy)*L;
dy = dy*halfsq3*L;
r2 = dx*dx + dy*dy;
if(r2<r2cut) {
rr2 = 1./r2;
rr6 = rr2*rr2*rr2;
enk+=(c12*rr6 -c6)*rr6 -ecut;
vir=(cf12*rr6-cf6)*rr6*rr2;
ftempx=vir*dx;
ftempy=vir*dy;
}
fx1[previouspartc+i]+=ftempx;
fy1[previouspartc+i]+=ftempy;
fx1[previouspartc+j]-=ftempx;
fy1[previouspartc+j]-=ftempy;
}
}
// Create the two indexes vcx1, vcy1 of the neighbour cells (the one on the right and the three under)
vcx1[0]=vcx+1; vcy1[0]=vcy;
for(k=1; k<4; k++){
vcx1[k]=vcx-1+(k-1);
vcy1[k]=vcy-1;
}
// Loop over near cells
for(k=0; k<4; k++){
previouspartc1=0;
// PBC
shiftx=0.; shifty=0.;
if(vcx1[k] <0){ shiftx= -1; vcx1[k]=ncell-1;}
else if(vcx1[k] >=ncell){ shiftx= 1; vcx1[k]=0;}
if(vcy1[k] <0){ shifty= -1; vcy1[k]=ncell-1;}
else if(vcy1[k] >=ncell){ shifty= 1; vcy1[k]=0;}
// Scalar cell index of neighbour cell
c1=vcx1[k]*ncell+vcy1[k];
// Define previouspart
for(p=1; p<=c1; p++) previouspartc1=previouspartc1+npart[p-1];
for(i=0; i<npart[c]; i++){
for(j=0; j<npart[c1]; j++){
ftempx=0.; ftempy=0.;
dx =rx1[previouspartc+i]-(rx1[previouspartc1+j]+shiftx);
dy =ry1[previouspartc+i]-(ry1[previouspartc1+j]+shifty);
dx = (dx + 0.5*dy)*L;
dy = dy*halfsq3*L;
r2 = dx*dx + dy*dy;
if(r2<r2cut) {
rr2 = 1./r2;
rr6 = rr2*rr2*rr2;
enk+=(c12*rr6 -c6)*rr6 -ecut;
vir=(cf12*rr6-cf6)*rr6*rr2;
ftempx=vir*dx;
ftempy=vir*dy;
}
fx1[previouspartc+i]+=ftempx;
fy1[previouspartc+i]+=ftempy;
fx1[previouspartc1+j]-=ftempx;
fy1[previouspartc1+j]-=ftempy;
}
}
}
}
}