2017-02-05 17 views
0

私はCUDA並列プログラミングチュートリアルの紹介に従っています。有効な回答を得るのが難しいです。Cudaを使用してポインタ配列を追加する。最初の値だけが正しいです

チュートリアル - >http://www.nvidia.com/docs/IO/116711/sc11-cuda-c-basics.pdf

私のコードは、コンパイルされ、ただし、配列の最初の整数が正しく計算されて実行される、チュートリアルに似ている、下記掲載しました。

データ整列の問題があるようですが、なぜか分かりません。また、この方法で配列上で数学演算を行ったことはありませんでした(インデックスなしで追加し、ビット境界を定義するためにブロックサイズに依存しています)。
私はそれがうまくいくことを理解しており、それはチュートリアルで動作しますので、私は何か見落としていると思います。誰かが私を正しい方向に向けることができますか?

#include <iostream> 
#include <cstdlib> 
#include <ctime> 

__global__ void add(int* a, int* b, int* c) { 
    *c = *a + *b; 
} 

int main(){ 
    srand(time(NULL)); 
    int n = 100; 
    int size = n * sizeof(int); 

    int* inputA; 
    int* inputB; 
    int* output; 

    int* d_inputA; 
    int* d_inputB; 
    int* d_output; 

    inputA = (int*)malloc(size); 
    inputB = (int*)malloc(size); 
    output = (int*)malloc(size); 

    cudaMalloc((void**)&d_inputA, size); 
    cudaMalloc((void**)&d_inputB, size); 
    cudaMalloc((void**)&d_output, size); 

    for(int i = 0; i < n; i++) { 
    inputA[i] = rand() % 100 + 1; 
    inputB[i] = rand() % 500 +1; 
    } 

    cudaMemcpy(d_inputA, inputA, size, cudaMemcpyHostToDevice); 
    cudaMemcpy(d_inputB, inputB, size, cudaMemcpyHostToDevice); 

    add<<<n,1>>>(d_inputA, d_inputB, d_output); 

    cudaMemcpy(output, d_output, size, cudaMemcpyDeviceToHost); 

    for(int i = 0; i < n; i++) { 
    std::cout << i << ": " 
    << inputA[i] << " + " << inputB[i] << " = " 
    << output[i] << std::endl; 
    } 
    free(inputA); 
    free(inputB); 
    free(output); 

    cudaFree(d_inputA); 
    cudaFree(d_inputB); 
    cudaFree(d_output); 

    return 0; 
} 

答えて

2

あなたはそれを書いてきたように、カーネル内の各スレッドは、配列の最初の要素だけが正しい値を持っている理由は、それが明らかに作るべき

__global__ void add(int* a, int* b, int* c) { 
    c[0] = a[0] + b[0]; 
} 

と同等のものを実行します。

あなたはこのようにカーネルを変更する場合:

__global__ void add(int* a, int* b, int* c) { 
    int idx = threadIdx.x + blockDim.x * blockIdx.x; 
    c[idx] = a[idx] + b[idx]; 
} 

を一次元グリッド内の各スレッドは、一意のインデックスを計算しているので、あなたは、カーネルは、あなたが期待している何を見つける必要があります。インデックスは組み込みの変数を使用して計算されます。使用している入門資料(たとえばスライド26まで)で読んだ場合のディスカッションがあります。

+0

これは意味があります。私はそれを見たが、それらの変更を忘れてしまった。 – mreff555

0

あなたのカーネルにのみ

はおそらく、あなたが誤って別のスレッドが別のポインタになるだろうと想定している...読み込み、それはあなたが出力に得るものですので、配列の最初の要素への書き込み - 配列の連続する要素に?さて、CUDAの仕組みではありません。すべてのスレッドは、まったく同じパラメータを取得し、スレッド識別子とブロック識別子だけが異なります。

__global__ void add(int* a, int* b, int* c) { 
    int i = threadIdx.x + blockIdx.x * blockDim.x; 
    c[i] = a[i] + b[i]; 
} 

これは一般的な場合に行う必要があります。あなたのケースでは、ブロックとnブロックごとに1つのスレッドを持っているので、あなたが持っている必要があります:

__global__ void add(int* a, int* b, int* c) { 
    int i = blockDim.x; 
    c[i] = a[i] + b[i]; 
} 

を...しかし、ブロックごとに、いくつかのスレッドを持つを避けるにしてみてください - あなたのパフォーマンスは、その悲惨なことになります方法。だからをしないでください上記のコードを使用してください。むしろ、大きなブロックを持つグリッドを作成します。

関連する問題