-1

私はcudaで流体力学の問題に取り組んでおり、このような問題を発見しました

長さ600のdebug_arrayと長さ100の配列value_arrayなどの配列があり、次のようにしたい場合

for(int i=0;i<6;i++)
{
   debug_array[6*(bx*block_size+tx)+i] = value_array[bx*block_size+tx];
}

この例では、block_size は 100 要素の配列に基づいています。たとえば、4 ブロック block_size 25 です。

value_array にたとえば 10;20;30;..... が含まれている場合、debug_array には 10;10;10;10;10;10;20;20;20;20;20;20 のような 6 つの同様の値のグループがあると予想されます。 ;30......
問題は、values 配列からすべての値を取得していないことです。なぜこれが機能しないのか、または適切な回避策があります。

float val = value_array[bx*block_size+tx]; を定義するとうまくいきます。for ループの外側に置き、これをループ内に保持します debug_array[bx*block_size+tx+i] = val;

しかし、カーネルにはループ内に 5​​ ~ 10 個のデバイス関数があり、読みにくくなるため、これは避けたいと思います。

アドバイスをいただければ幸いです。

マーカス

4

2 に答える 2

2

インデックスの計算にエラーがあるようです:

debug_array の最初の 6 つの要素がデータで埋められると仮定bx = 0しましょう 。tx = 0

次のスレッド: tx = 1: 要素 1 から 7 にデータが入力されます (既存のデータを上書きします)。スレッドが並行して動作するため、どのスレッドが最初にスケジュールされるか、したがってどの値が debug_array に書き込まれるかは決定されません。

あなたは書いたはずです:

 debug_array[6*(bx*block_size+tx)+i] = value_array[bx*block_size+tx];
于 2012-08-20T15:39:13.383 に答える
0

value_array 式をループから一時変数に移動するようにコードを変更すると、コードが機能するようになり、それが唯一のコード変更である場合、これはコンパイラのバグのようなにおいがします。

nvcc コンパイラ オプションを変更して最適化を減らすか無効にして、ループ内の value_array 式が動作を変更するかどうかを確認してください。また、最新の CUDA ツールを使用していることを確認してください。

最適化コンパイラは、手動の回避策とまったく同じように、ループ インデックス変数に依存しない式をループから移動しようとすることがよくあります。これは「インバリアント コード モーション」と呼ばれ、ループの各反復で実行されるコードの量を減らすことで、ループを高速化します。ループから不変コードを手動で抽出してもうまくいくが、コンパイラーにそれを自分で理解させてもうまくいかない場合、それはコンパイラーに疑問を投げかけます。

于 2012-08-20T16:55:45.620 に答える