2016-06-11 9 views
1

私はGPUプログラミング、特にCUDA/C++を初めて使用しています。 atomicAddを使用して配列のすべてのメンバーを1ずつ増やすという単純なコードを書いています。1つのスレッドだけがcudaカーネルを実行します

しかし結果は、配列の最初の要素が増えただけで、残りは同じままです。私のコードは以下の通りです。

ご協力いただきありがとうございます。

#include "cuda_runtime.h" 
#include "device_launch_parameters.h" 
#include <stdio.h> 
#include <iostream> 
#include <fstream> 
using namespace std; 
__global__ void Histcount(int *a) 
{ 
    int i = blockIdx.x*blockDim.x + threadIdx.x; 
    { 
     atomicAdd(&a[i], 1); 
    } 
} 

int main() 
{ 
    int * hostarray = new int[20]; 
    int * devarray; 
    cudaError_t error; 
    error=cudaMalloc(&devarray, sizeof(int) * 20); 
    for (int i = 0; i < 20; i++) 
    { 
     hostarray[i] = i ; 
    } 
    cudaMemcpy((int *)devarray, (int *)hostarray, sizeof(int) * 20, cudaMemcpyHostToDevice); 
    dim3 gs = (1, 1); 
    dim3 bs = (20, 1, 1); 
    Histcount <<<gs, bs >>> (devarray); 
    cudaMemcpy((int *)hostarray, (int *)devarray, sizeof(int) * 20, cudaMemcpyDeviceToHost); 
    for (int i = 0; i < 20; i++) 
    { 
     cout << hostarray[i]<<endl; 

    } 
} 

答えて

3

これはdim3変数を指定するための有効な方法ではありません。

dim3 gs = (1, 1); 
dim3 bs = (20, 1, 1); 

実際には、コンパイラはそれらのライン上の警告を投げることがあり、もしそうなら、あなたはそれらを無視してはいけません。

dim3 gs = dim3(1, 1); 
dim3 bs = dim3(20, 1, 1); 

のか:

あなたはいずれかを実行する必要があり

dim3 gs(1, 1); 
dim3 bs(20, 1, 1); 

実装の問題は、コンパイラがであなたの実際の意図を知らないということです。例:

(20, 1, 1) 

あなた自身がそれを持っているので、コンパイラ(実際に警告を発することがあります)evaluates that expression1に設定し、変数dim3にスカラーとして割り当てます。つまり、ブロックサイズが1、グリッドサイズが1(目的ではない)になり、コード全体が1スレッドしか実行されませんでした。

+2

(20,1,1)が1と評価される理由については、CまたはC++リファレンスで「comma operator」を参照してください。コンマ演算子は、右端の式の値を返します。この場合、1になります。 – njuffa

+0

[左の式も評価されます](https://en.wikipedia.org/wiki/Comma_o​​perator)、その結果は破棄されます。どうやら、左側の式が一定の値であれば、コンパイラは警告を発することがあります。それを評価することは効果がないので、(my)コンパイラは「式は効果がありません」という警告を出します。これを副作用のある表現で置き換えると、 '(j ++、j ++、1)'の場合、警告は消えます(最終結果はまだ意図しないスカラー1ですが)。 –

+1

警告は、C/C++言語標準では義務付けられていないので、常に「may」カテゴリにあると思います。 – njuffa

関連する問題