0

私は CUDA を初めて使用し、現在分子動力学の既存のアプリケーションを最適化しています。それが行うことは、座標を持つ double4 の配列を取り、neighborlist に基づいて力を計算することです。次の行でカーネルを作成しました。

double4 mPos=d_arr_xyz[gid];
while(-1!=(id=d_neib_list[gid*MAX_NEIGHBORS+i])){
Calc(gid,mPos,AA,d_arr_xyz,id);i++;
}

Calc は d_arr_xyz[id] を取り、力を計算します。これにより、Calc の呼び出しごとに double4 の 1 回の読み取り + (int +double4) の 65 回の読み取りが得られます (65 は、各粒子の d_neib_list 内の近傍の平均数 (-1 に等しくない) です)。

それらの読み取りを減らすことは可能ですか? 異なるパーティクルの近隣リスト、つまり d_arr_xyz[gid] と d_arr_xyz[id] は相関しないため、スレッドのブロックに共有メモリを使用して d_arr_xyz をキャッシュすることはできません。

私が見ているのは、何らかの方法でリスト全体 int*MAX_NEIGHBORS を 1 つまたはいくつかの大規模なトランザクションで共有メモリにロードすると、int の 65 の個別の読み取りが削除されることです。

問題は、これらの int の 65 回の読み取りがいくつかの大規模なトランザクションに変換されるようにすることは可能かどうかです。私は、読み取りが128バイトの長さでさえある可能性があるというドキュメントを読みました。アセンブラが 1 つの大きな呼び出しを行うようにするには、正確に何を記述すればよいですか?

アップデート:

返信ありがとうございます。以下のユーザー talonmies からの回答から、隣人行列の次元 x と y を置き換えるコードを変更しました。連続するスレッドが連続する int[gid] をロードするようになりました。これにより、128 バイトの読み取りが発生する可能性があります。プログラムは 8% 速く動作します。

4

1 に答える 1

3

すべてのメモリ トランザクションは、(可能な場合)ワープごとに発行されます。したがって、あなたが求めている128バイトのトランザクションは、ワープ内の32個のスレッドすべてが、単一の「結合」トランザクションで処理できるメモリロード命令を発行するときです。1 つのスレッドが大規模なメモリ トランザクションを発行することはできず、32 スレッドのワープのみが発行でき、コードを実行するアーキテクチャのメモリ結合要件が満たされる場合にのみ発行されます。

あなたのコードが実際に何をしているかについてのあなたの説明には本当に従うことができませんでしたが、第一原理だけから、答えはノーのようです.

于 2013-06-30T11:58:12.457 に答える