2012-02-27 3 views
0

メインプログラムに大文字の配列があり、チャンクでデバイス のメモリにコピーしています。私は自分のプログラムで約500,000のスレッドを実行し、各スレッドは2000個の文字にアクセスします。 だから私500,000 * 2000 = 1ギガバイトは、私のカーネルでコードCUDA:ホストからデバイスにchar配列をコピーした後、 "スタックオーバーフローまたはブレークポイントヒット"と指定されていない起動エラーが発生しました

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配列の第二のチャンクをコピーするとき、私は、エラー

CUDAのエラーを取得:未指定の打ち上げ失敗

を私はすべて上記のコードの行のコメントを解除した場合正常に動作します。私は アレイのチャンクを1GBの代わりに100MBのようにコピーすると、上記と同じエラーが発生する 6番目のチャンクに達するまでうまく動作します。

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

EDIT: ここは私のカーネルです。要約すると、私は、0とその長さの間のすべてのiのi番目の文字を比較することによって2つの文字列の類似度スコアを計算しています。 このコードは、上記のエラー を生成します。if(threadIdx.x == 0) {の直後の行のコメントを解除しない限り、このコードは発生しません。または、もしあなたが の共有配列を定数1で置き換えると、うまくいきます。

__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; 
} 
} 
+0

残りのカーネルは何をしていますか?再帰を使用していますか? – perreal

+0

私は再帰を使用していません。残りのコードはforループです。私はこのコメントの後にここにいくつか投稿します。 – Ross

+0

私の質問に私のカーネルコードがあります。私はchar配列をホストからデバイスメモリにコピーした後、私のメインプログラムからこれを呼び出します。 – Ross

答えて

0

チャーがあったdev_index[ch-'A']が-1を返す原因となったデータのラクタ。この は、k = 0のときに、dev_scoresのインデックスを作成しました。私はそれが私のコードで メモリエラーの原因であったと信じています。私はすべてをコメントし、段階的にコメントを外しました。 これで問題なく動作します。あなたのコメントのために@ talonmies、@harrism、および@perrealに感謝します!

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]; 
} 
... 
+0

私はこれを考えていませんでした。それは賢いです。ありがとう。 – Ross

+0

kは私が今修正したタイプミスです。 kの代わりに(j-1)* 5と書くべきです。 – Ross

関連する問題