1

アップデート!

私の現在のコードは、範囲外のメモリ アクセスをチェックしません。cuda memcheck を実行すると、2 x 2 の行列でもメモリ アクセスが悪いと表示されます。どうにかしてはならないメモリにアクセスしていますが、それが問題です!

範囲外のメモリ アクセスをチェックするには、cuda-memcheck ./(実行可能ファイルをここに挿入) を実行します。

以下に示すのは、行列乗算自体のコードです。

dim3 block(32,32);
dim3 grid( (n+31)/32, (n+31)/32 );
matrixMul<<<grid,block>>>(d_C, d_A, d_B, n, k);

kA と kB は値を含む行列です (わかりやすくするためにすべて 2 にしています)。

m、n、k は正方行列ではすべて同じ数です

kC は、答えを格納する行列です。

#ifndef _MATRIXMUL_KERNEL_H_
#define _MATRIXMUL_KERNEL_H_

#include <stdio.h>

__global__ void matrixMul(float *kC, float *kA, float *kB, int n, int k)
{

    int tx = blockIdx.x * 32 + threadIdx.x;
    int ty = blockIdx.y * 32 + threadIdx.y;
    float value = 0;

    for (int i=0;i<n;i++)
    {
        float elementA=kA[ty*n+i];
        float elementB=kB[i*k+tx];
        value += elementA*elementB;
    }

    kC[ty*n+tx] = value;
}

#endif // #ifndef _MATRIXMUL_KERNEL_H_
4

1 に答える 1

2

スレッドのグリッドを定義する方法に基づいて、次のようにスレッド チェックをカーネル コードに追加する必要があります。

#ifndef _MATRIXMUL_KERNEL_H_
#define _MATRIXMUL_KERNEL_H_

#include <stdio.h>

__global__ void matrixMul(float *kC, float *kA, float *kB, int n, int k)
{

    int tx = blockIdx.x * 32 + threadIdx.x;
    int ty = blockIdx.y * 32 + threadIdx.y;

    if ((ty < n) && (tx < n)) { // add this line
      float value = 0;

      for (int i=0;i<n;i++)
      {
        float elementA=kA[ty*n+i];
        float elementB=kB[i*k+tx];
        value += elementA*elementB;
      }

      kC[ty*n+tx] = value;
    }  //  add this line
}

#endif // #ifndef _MATRIXMUL_KERNEL_H_

そうしないと、有効な配列配列外のスレッドによって結果が破損します。無効なスレッドがないため、32x32 の倍数で動作します。その場合、必要な数のスレッドを正確に起動しています。しかし、それ以外の場合は、余分なスレッドを起動しています。これらの余分なスレッドは、無効なマトリックス位置の計算を許可されている場合、結果が破損します。

于 2013-05-19T03:16:09.833 に答える