CUDAプログラミングモデルとその機能を理解しようとしています。演習として、関数呼び出しを使用して次のループ構造を効率的なCUDAカーネルに変換しようとしています。
//function call
bool gmul(int rowsize,int *Ai,int *Bj,int colsize)
{
for(int i = 0;i < rowsize;i++)
{
for(int j = 0;j < colsize;j++)
{
if(Ai[i] == Bj[j])
{
return true;
}
}
}
return false;
}
//Some for loop in main function is as follows
for(i = 0;i < q ;i++)
{
cbeg = Bjc[i];
cend = Bjc[i+1];
for(j = 0;j < m;j++)
{
beg = Aptr[j];
end = Aptr[j+1];
if(gmul(end - beg,Acol + beg,Bir + cbeg,cend - cbeg))
{
temp++;
}
}
Cjc1[i+1] = temp ;
}
そして、関数呼び出しのある私のカーネルは次のとおりです。
__device__ bool mult(int colsize,int rowsize,int *Aj,int *Bi,int *val)
{
for(int j = 0; j < rowsize;j++)
{
for(int k = 0;k < colsize;k++)
{
if(Aj[j] == Bi[k])
{
return true;
}
}
}
return false;
}
__global__ void kernel(int *Aptr,int *Aj,int *Bptr,int *Bi,int rows,int cols,int *count,int *Cjc)
{
int tid = threadIdx.x + blockIdx.x * blockDim.x;
int i;
if(tid < cols)
{
int beg = Bptr[tid];
int end = Bptr[tid+1];
for(i = 0;i < rows;i++)
{
int cbeg = Aptr[i];
int cend = Aptr[i+1];
if(mult(end - beg,cend - cbeg,Aj+cbeg,Bi+beg,count))
{
//atomicAdd(count,1);
//Changes made are in next line
atomicAdd(Cjc+tid+1,1);
}
}
//atomicAdd(Cjc+tid+1,*count);
}
}
私が欲しいのは、値__device__ mult
とともに返されるときはいつでもtrue
、私のグローバルカーネル関数はその特定のスレッドのカウンターをインクリメントし、forループ(カーネル関数内)が終了すると、値をCjc
配列に格納し、カウントが他のスレッドに渡されることですインクリメント操作用。しかし、期待値が得られません。このCjc
配列で取得するのは、すべてのスレッドの実行が終了した後の最終カウントだけです。
CC2.0でGTX480を使用しています
なぜこのCUDAカーネルに対して間違った答えや最適化が得られるのかについての提案/ヒントをいただければ幸いです。前もって感謝します。 * *******解決済み**** ** * **** _ _ _
現在、4000以上のサイズに達すると、配列内のすべての要素の値がとして取得されるという問題に直面しています0
。これが私がカーネルを起動する方法です。
int numBlocks,numThreads;
if(q % 32 == 0)
{
numBlocks = q/32;
numThreads = 32;
}
else
{
numBlocks = (q+31)/32;
numThreads = 32;
}
findkernel<<<numBlocks,numThreads>>>(devAptr,devAcol,devBjc,devBir,m,q,d_Cjc);
ブロックまたはグリッドの寸法の制限を超えているのではないかと思っていましたが、CC 2.0の場合、制限を超えない十分なブロックとスレッドを起動するのが適切だと思います。なぜまだすべての答えがとして出ているのだろうか0
。