0

メイン プログラムに大きな char 配列があり、それをチャンクでデバイス メモリにコピーします。プログラムで約 500,000 のスレッドを実行し、各スレッドは 2000 文字にアクセスします。したがって、コードを使用して一度に 500,000 * 2000 = 1GB バイトを転送します

err = cudaMemcpy (dev_database, adjusted_database[k], JOBS * 2000 * sizeof(char), cudaMemcpyHostToDevice);
if(err != cudaSuccess) { printf("CUDA error: %s\n", cudaGetErrorString(err)); exit(EXIT_FAILURE); }

私のカーネルでは、3 つの共有配列も定義しています

//__shared__ char dev_query[200];
__shared__ float dev_scores[200*5];
__shared__ int dev_index[26];

そしてそれらを初期化します

if(threadIdx.x == 0) { 
  //for(i = 0; i < 200; i++){ dev_query[i] = dev_query_constant[i]; }
  for(i = 0; i < 200 * 5; i++){ dev_scores[i] = dev_scores_constant[i]; }
  for(i = 0; i < 26; i++){ dev_index[i] = dev_index_constant[i]; }
}
__syncthreads(); 

コメントされた 2 行でプログラムを実行すると、カーネルが奇妙な値を返し、char 配列の 2 番目のチャンクをコピーするとエラーが発生します。

CUDA エラー: 不明な起動エラー

上記のコードの行のコメントを外すと、すべて正常に動作します。1GB ではなく 100MB など、配列の小さなチャンクをコピーすると、上記と同じエラーが発生する 6 番目のチャンクに到達するまで正常に動作します。

これは非常に奇妙な動作であり、なぜこれが起こっているのかを理解したいと思います。これを引き起こしているバグはどこかにありますか?小さなチャンク (100MB など) を転送し、他のチャンクを無視すると、プログラムは正常に動作するため、特定するのは困難です。共有変数に関連する行のコメントを外したり、共有変数を定数に変更したりしても、問題なく動作します。どんな助けでも大歓迎です。ありがとう!

編集: これが私のカーネルです。要約すると、2 つの文字列の類似性スコアを、0 からそれらの長さまでのすべての i の i 番目の文字を比較することによって計算しています。以下のコードは、 の直後の行のコメントを解除しない限り、上記のエラーを生成します if(threadIdx.x == 0) {。または、以下の共有配列を定数配列に置き換えると、正常に動作します。

__global__ void assign7(int jobs_todo, char* database, float* results, int flag) {
unsigned int id = threadIdx.x + blockIdx.x * blockDim.x;

if(id < jobs_todo) {
__shared__ char dev_query[200];
__shared__ float dev_pos_specific_scores[200*5];
__shared__ int dev_subst_index[26];

int j_, i, p, stop, k; //stop2;
float score=0, max=0;
char ch; //ch1, ch2;

if(threadIdx.x == 0) {
//for(i = 0; i < 51; i++){ dev_query[i] = dev_query_constant[i]; }
  for(i = 0; i < 5 * 200; i++){ dev_pos_specific_scores[i] = dev_pos_specific_scores_constant[i]; }
  for(i = 0; i < 26; i++){ dev_subst_index[i] = dev_subst_index_constant[i]; }
}
__syncthreads(); 

for(i = 1; i <= 2000 - 51; i += 1){
  p = jobs_todo*(i-1);
  score = 0;
  stop = 51/1; stop = stop*1;
  for(j_ = 1; j_ <= stop; j_ += 1){
    k = (j_-1)*5;
    ch = database[p + id];
    score += dev_pos_specific_scores[k + dev_subst_index[ch - 'A']];
    if(score < 0) score = 0;
    if(score > max) max = score;                                      
    p += jobs_todo;
  }
}
results[id] = max;
}
}
4

2 に答える 2

2

以下の部分はk、初期化せずに使用します。

ch = database[p + id];
score += dev_scores[k + dev_index[ch - 'A']];

これは関係ありませんが、この部分:

if(threadIdx.x == 0) { 
  //for(i = 0; i < 200; i++){ dev_query[i] = dev_query_constant[i]; }
  for(i = 0; i < 200 * 5; i++){ dev_scores[i] = dev_scores_constant[i]; }
  for(i = 0; i < 26; i++){ dev_index[i] = dev_index_constant[i]; }
}

次のように変更できます。

if(threadIdx.x < 200) {
  // dev_query[i] = dev_query_constant[i];
}

if(threadIdx.x < 200 * 5) { // or iterate whole block 5 times..
  dev_scores[i] = dev_scores_constant[i];
}
...
于 2012-02-27T22:06:42.453 に答える
0

dev_index[ch-'A']-1 を返す原因となった文字がデータに含まれていました。これにより、k = 0 のときにインデックスがdev_scores-1 になりました。これが、コードのメモリ エラーの原因であると考えています。私はすべてにコメントし、徐々にコメントを外した部分をコメントしました。今はうまくいきます。@talonmies、@harrism、@perreal のコメントに感謝します。

于 2012-03-01T14:05:31.103 に答える