かなりうまく動作するコードがいくつかありますが、もっとうまく動作させたいと思います。私が抱えている主な問題は、ネストされたforループが必要なことです。外側のものは反復用であり(これは連続して発生する必要があります)、内側のものは検討中の各点粒子用です。外側のものについてできることはあまりないことは知っていますが、次のようなものを最適化する方法があるかどうか疑問に思っています。
void collide(particle particles[], box boxes[],
double boxShiftX, double boxShiftY) {/*{{{*/
int i;
double nX;
double nY;
int boxnum;
for(i=0;i<PART_COUNT;i++) {
boxnum = ((((int)(particles[i].sX+boxShiftX))/BOX_SIZE)%BWIDTH+
BWIDTH*((((int)(particles[i].sY+boxShiftY))/BOX_SIZE)%BHEIGHT));
//copied and pasted the macro which is why it's kinda odd looking
particles[i].vX -= boxes[boxnum].mX;
particles[i].vY -= boxes[boxnum].mY;
if(boxes[boxnum].rotDir == 1) {
nX = particles[i].vX*Wxx+particles[i].vY*Wxy;
nY = particles[i].vX*Wyx+particles[i].vY*Wyy;
} else { //to make it randomly pick a rot. direction
nX = particles[i].vX*Wxx-particles[i].vY*Wxy;
nY = -particles[i].vX*Wyx+particles[i].vY*Wyy;
}
particles[i].vX = nX + boxes[boxnum].mX;
particles[i].vY = nY + boxes[boxnum].mY;
}
}/*}}}*/
SIMDについてはあまりわかりませんが、SIMDを調べました。データを適切に抽出してパックするために必要な処理が、明らかに半分の命令を実行するだけの価値があるかどうかは完全にはわかりません。一度に2つのダブルを使用できます。
shmとpthread_barrierを使用して複数のスレッドに分割しようとしましたが(上記のコードが1つであるさまざまなステージを同期するため)、速度が低下しました。
私の現在のコードはかなり速く進みます。これは、10Mのパーティクル*反復ごとに1秒のオーダーであり、gprofからわかるように、私の時間の30%はその関数だけに費やされています(5000回の呼び出し、PART_COUNT = 8192パーティクルは1.8秒かかりました)。小さくて一定の時間のことは心配していません。512Kの粒子*50Kの反復*1000回の実験が前回1週間以上かかっただけです。
私の質問は、これらの長いベクトルを単にループするよりも効率的な方法があるかどうかだと思います。あるべきだと思いますが、見つかりません。