2013-12-10 26 views
5

例えば、私はこれらの次のポインタに割り当てる:この後CUDAでは、デバイスポインタの配列をデバイスメモリにコピーする方法は?

float *data_1, *data_2, *data_3, *data_4; 

//Use malloc to allocate memory and fill out some data to these pointers 
...... 
//Filling complete 

float *data_d1,*data_d2,*data_d3,*data_d4; 

cudaMalloc((void **)&data_d1,size1); 
cudaMalloc((void **)&data_d2,size2); 
cudaMalloc((void **)&data_d3,size3); 
cudaMalloc((void **)&data_d4,size4); 

cudaMemcpy(data_d1,data_1,size1,cudaMemcpyHostToDevice); 
cudaMemcpy(data_d2,data_2,size2,cudaMemcpyHostToDevice); 
cudaMemcpy(data_d3,data_3,size3,cudaMemcpyHostToDevice); 
cudaMemcpy(data_d4,data_4,size4,cudaMemcpyHostToDevice); 

を、私はすでにホストポインタがそうであるように、正確なデータを含む4つのデバイスのポインタを取得する必要があります。今、私は次のようにポインタの1つの配列にこれらのポインタを保存したいのですが、

float *ptrs[4]; 

ptrs[0] = data_d1; 
ptrs[1] = data_d2; 
ptrs[2] = data_d3; 
ptrs[3] = data_d4; 

今私はCUDAカーネルへのポインタのこの配列を転送したいと思います。しかし、私はptrs [4]が実際にホストメモリ上にあるので、私はデバイス上に新しいポインタを割り当てる必要があることを知っています。だから私は、これをしなかった

float **ptrs_d; 
size_t size = 4 * sizeof(float*); 
cudaMalloc((void ***)&ptrs_d,size); 
cudaMemcpy(ptrs_d,ptrs,size,cudaMemcpyHostToDevice); 

そしてカーネル起動:kernel_testで

kernel_test<<<dimGrid,dimBlock>>>(ptrs_d, ...); 
//Declaration should be 
//__global__ void kernel_test(float **ptrs_d, ...); 

を、次の構文で負荷データ:

if (threadIdx.x < length_of_data_1d) 
{ 
    float element0 = (ptrs[0])[threadIdx.x]; 
} 

コンパイルは大丈夫ですが、デバッグ時アクセス違反のエラーが発生します。

私のコードには多分エラーがあります。しかし、私はちょうどこの方法でデバイスポインタを渡すことができない理由と、CUDAでデバイスポインタの配列をカーネル機能に渡すことが許可されている場合、それにアクセスする適切な方法は何かを知りたいだけです。

この問題を解決するにはどうすればよいですか?どんな提案も感謝しています。前もって感謝します。

+2

あなたの方法には明らかな問題はありません。私はあなたが示したものの周りにシンプルなコードを作成し、それは私のために正しく動作するようです、それは[ここ](http://pastebin.com/n1S63xLb)です。あなたのアクセス違反は、あなたのデータの長さとここに示していないいくつかのコードに基づいた範囲外の配列かもしれません。デバイスポインタの配列をコピーするための基本的な方法とは関係ないかもしれません。一連のスニペットではなく、問題を再現する完全なコードを提供することをお勧めします。問題はあなたがここに示していないものです。 –

+0

お寄せいただきありがとうございます。私は数回デバッグを試み、最後にこのメソッドが実際に適用可能であることを学びました。実際の問題は、あなたが示唆しているように、範囲外の問題である可能性が最も高いと思われ、今私は把握しようとしています。あなたの敏感な助けにもう一度感謝します。 –

+1

デバッガで確実に実行すると、何がうまくいかないのかを知ることができます。 'cuda-memcheck'であなたのコードを実行することで、問題を明らかにすることもできます。 –

答えて

2

CUDAがstandartと同様に想定しているように、1つの可能性はvoidポインタを割り当てることです。カーネルに渡すときは、float**にキャストすることができます。 私はそのようにしました:

void* ptrs_d = 0; 
cudaMalloc(&ptrs_d, 4*sizeof(float*)); 
cudaMemcpy(ptrs_d, ptrs, 4*sizeof(float*), cudaMemcpyHostToDevice); 
kernel_test<<<dimGrid, dimBlock>>>((float**)ptrs_d); 
+1

この問題にはどのような問題がありますか? –

+0

@robertポインタの配列をcudaカーネルに渡すことは可能です。 – hubs

+1

何が求められているのかを達成するために、フロートからボイドにキャストしてフロートに戻す必要はありません。コメントリンクに記載したコードはそのことを示しています。 –

関連する問題