公式ガイドのshared memory exampleを参照してthis questionに続いて、私はちょうど私が熱方程式の行列 - 不正なアドレスエラー
を作ったこの悪い描かれた画像のようである熱方程式の行列を構築しようとしていますここで
は、最小限の例では、コードは大きなN(32より大きい)を合わせて配置されている
#define N 32
#define BLOCK_SIZE 16
#define NUM_BLOCKS ((N + BLOCK_SIZE - 1)/ BLOCK_SIZE)
__global__ void heat_matrix(int* A)
{
const unsigned int tid = threadIdx.x + blockIdx.x * blockDim.x;
__shared__ int temp_sm_A[N*N];
int* temp_A = &temp_sm_A[0]; memset(temp_A, 0, N*N*sizeof(int));
if (tid < N) //(*)
{
#pragma unroll
for (unsigned int m = 0; m < NUM_BLOCKS; ++m)
{
#pragma unroll
for (unsigned int e = 0; e < BLOCK_SIZE ; ++e)
{
if ((tid == 0 && e == 0) || (tid == (N-1) && e == (BLOCK_SIZE-1)))
{
temp_A[tid + (e + BLOCK_SIZE * m) * N] = -2;
temp_A[tid + (e + BLOCK_SIZE * m) * N + (tid==0 ? 1 : -1)] = 1;
}
if (tid == e)
{
temp_A[tid + (e + BLOCK_SIZE * m) * N - 1] = 1;
//printf("temp_A[%d] = 1;\n", (tid + (e + BLOCK_SIZE * m) * N -1));
temp_A[tid + (e + BLOCK_SIZE * m) * N] = -2;
//printf("temp_A[%d] = -2;\n", (tid + (e + BLOCK_SIZE * m) * N));
temp_A[tid + (e + BLOCK_SIZE * m) * N + 1] = 1;
//printf("temp_A[%d] = 1;\n", (tid + (e + BLOCK_SIZE * m) * N +1));
}
}
}
__syncthreads(); //(**)
memcpy(A, temp_A, N*N*sizeof(int));
}
}
int main(){
int* h_A = (int*)malloc(N*N*sizeof(int)); memset(h_A, 0, N*N*sizeof(int));
int* d_A;
checkCudaErrors(cudaMalloc((void**)&d_A, N*N*sizeof(int)));
checkCudaErrors(cudaMemcpy(d_A, h_A, N*N*sizeof(int), cudaMemcpyHostToDevice));
dim3 dim_grid((N/2 + BLOCK_SIZE -1)/ BLOCK_SIZE);
dim3 dim_block(BLOCK_SIZE);
heat_matrix <<< dim_grid, dim_block >>> (d_A);
checkCudaErrors(cudaMemcpy(h_A, d_A, N*N*sizeof(int), cudaMemcpyDeviceToHost));
...
}
、私がこれまで行ってきたものです。私はブロック分割を利用しました。 nvcc
利回り
CUDA error at matrix.cu:102 code=77(cudaErrorIllegalAddress) "cudaMemcpy(h_A, d_A, N*N*sizeof(int), cudaMemcpyDeviceToHost)"
そしてcuda-memcheck
を実行するとき、私はコードで間違っていたところ、私が見ることができない唯一のエラー(実際にそこに別のがあるが、それはcudasuccess=checkCudaErrors(cudaDeviceReset()); ...
から来ている)
========= CUDA-MEMCHECK
========= Invalid __shared__ write of size 4
========= at 0x00000cd0 in heat_matrix(int*)
========= by thread (0,0,0) in block (0,0,0)
========= Address 0xfffffffc is out of bounds
...
を提供します。最初のブロックのスレッド0
はどのように不正なアクセスを引き起こすことができますか?それに対処する特定のif
ケースもあり、エラーが発生したコード行は報告されていません。
また、私のコードには、if
のすべてを処理するよりも効率的な方法がありますか?確かに存在しますが、ケースを2番目のfor
に分割するより良い並行表現は見つかりませんでした。
私にとっては、(*)
は不要です。代わりに(**)
が必要です。他のGPU関数呼び出しに従いたいと思っています。私は正しい?
よろしいですか?最初に 'memcpy'と' memset'を取り除きます。次に、マトリックスの "中"と境界内で作業する間にスレッドを分割すべきですか(例えば 'if(tid == 0) 'など)?ワープについてはOKですが、プロンプトの出力を覗くのに適した値でした。 – Eugenio
境界線を明示的に考慮する必要はありません。対角線上にあるか、隣接する要素にあるのか、他の場所にいるのかを確認してください。 – tera
あなたの編集はとても役に立ちました。それは契約だった、thx – Eugenio