0

私は並列プログラミングとスタックオーバーフローに非常に慣れていません。CUDA を使用した行列乗算の実装に取り​​組んでいます。行列表現として列順浮動小数点配列を使用しています。

私が開発したアルゴリズムは少しユニークで、次のようになります。行列 nxm 行列 A と mxk 行列 B を指定して、各ブロックに m スレッドを含む nxk ブロックを起動します。基本的に、結果の行列のすべてのエントリに対してブロックを起動し、各スレッドでそのエントリの 1 つの乗算を計算します。例えば、

1 0 0     0 1 2  
0 1 0  *  3 4 5  
0 0 1     6 7 8

結果のマトリックスの最初のエントリでは、各スレッドを次のように起動します

スレッド 0 コンピューティング 1 * 3 スレッド 1 コンピューティング 0 * 0 スレッド 2 コンピューティング 0 * 1

各スレッドが 0 で初期化されたマトリックスに追加されます。今のところ、正しい答えが得られていません。私はこれを何度も繰り返しています

0 0 2
0 0 5
0 0 8

私のカーネル関数は以下です。これはスレッド同期の問題でしょうか、それとも配列のインデックス付けなどを台無しにしていますか?

    /*@param d_A: Column order matrix 
     *@param d_B: Column order matrix
     *@param d_result: 0-initialized matrix that kernels write to
     *@param dim_A: dimensionality of A (number of rows)
     *@param dim_B: dimensionality of B (number of rows)
     */
    __global__ void dot(float *d_A, float *d_B, float *d_result, int dim_A, int dim_B) {
        int n = blockIdx.x;
        int k = blockIdx.y;
        int m = threadIdx.x;

       float a = d_A[(m * dim_A) + n];
       float b = d_B[(k * dim_B) + m];
       //d_result[(k * dim_A) + n] += (a * b);

       syncthreads();
       float temp = d_result[(k*dim_A) + n];
       syncthreads();
       temp = temp + (a * b);
       syncthreads();
       d_result[(k*dim_A) + n] = temp;
       syncthreads();
    }
4

1 に答える 1

1

この場合、使用の全体的な考え方syncthreads()は間違っています。この API 呼び出しにはブロックスコープがあります。

   1. syncthreads();
   2. float temp = d_result[(k*dim_A) + n];
   3. syncthreads();
   4. temp = temp + (a * b);
   5. syncthreads();
   6. d_result[(k*dim_A) + n] = temp;
   7. syncthreads();

ローカル変数float temp;にはスレッド スコープがあり、この同期バリアを使用しても意味がありません。ポインターd_resultはグローバル メモリ ポインターであり、この同期バリアを使用しても意味がありません。スレッドをグローバルに同期するバリアはまだ利用できないことに注意してください (おそらく利用できることはないでしょう)。

通常、syncthreads()共有メモリを計算に使用する場合は、 の使用が必要です。この場合、共有メモリを使用することをお勧めします。ここでsyncthreads()は、共有メモリを適切に使用する方法の例を見ることができます。ここに、共有メモリを使用した行列乗算の例があります。

于 2013-06-28T09:01:22.473 に答える