私の論文では、Xeon Phi コプロセッサーでレナード・ジョーンズ システムを研究するために使用される単純なコードを実行し、それをベクトル化し、実行時間の変化を研究しようとしました。
特に私が使用したマシンは 61 個のコアを持ち、L1 キャッシュが 32 kB、L2 キャッシュが 512 kB で、ベクトル レジスタは 512 ビットを記憶できます。
cell-list メソッドを使用するコードと使用しないコードを実装し、異なる数の粒子 (特に 512 から 16384 まで) を使用して、毎回 2 倍にしました。
位置と力は、3 つの異なるベクトル (rx、ry、rz および fx、fy、fz) で記憶されます。
cell-list がない場合は良い結果が得られますが、別の場合は奇妙な結果が得られます。
セルリストと粒子数の間の依存関係は、実装されたセルリストメソッドで線形になるはずです。実際、粒子数に対して時間をプロットする直線が得られましたが、N = 8192 と N = 16384 の場合、実行力ははるかに高いです。
これらの値に近い N の値を使用して計算を試みましたが、スケーリングは他の数値に対して正しく、これら 2 つの場合にのみ問題があります。
明確にするために、いくつかの値を報告します。
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
技術的な問題だと思いますが、なぜこれが起こるのか正確にはわかりません。
また、ベクトル化を使用した場合の変動は非常に小さく、cell-list を使用しない場合は 4 倍程度の変動が観測されましたが、cell-list を使用した場合は約 1.5 倍にすぎません。
質問:
問題が何であるかを知っている人はいますか?これらの特定の値が奇妙で、ベクトル化ゲインが非常に低いのはなぜですか?
私の教授は、いくつかの値が実行時に奇妙な結果を示すことが起こる可能性があると私に言いました.誰かがこのようなことを観察しましたか?
どうもありがとうございました。
以下に、cell-list で実装された実行の主要部分である力を評価するメイン ループを報告します。
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;
}
}
}
}
}