2011-01-22 4 views
4

私はいくつかのコードをcudaカーネルに作りたいと思っています。見よ:CUDA:ループカーネルに埋め込まれています

for (r = Y; r < Y + H; r+=2) 
    { 
     ch1RowSum = ch2RowSum = ch3RowSum = 0; 
     for (c = X; c < X + W; c+=2) 
     { 
      chan1Value = //some calc'd value 
          chan3Value = //some calc'd value 
      chan2Value = //some calc'd value 
      ch2RowSum += chan2Value; 
      ch3RowSum += chan3Value; 
      ch1RowSum += chan1Value; 
     } 
     ch1Mean += ch1RowSum/W; 
     ch2Mean += ch2RowSum/W; 
     ch3Mean += ch3RowSum/W; 
    } 

はこれは、一つの手段を計算するRowSumsと1を計算し、そしてどのように私は私のループインデックスはゼロから始まり、Nで終了いけないという事実を処理する必要があり、2つのカーネルに分割すべきか?

+0

1つの質問を選択しようとすると、正解を選択するのが難しくなります。しかし、あなたの2番目の質問については、具体的に答えるのは難しいですが、カーネルを開発するにはもっと遠くになると思います。 – jmilloy

+0

ブロックごとにHブロックとWスレッドのような設定でカーネルを起動する必要があります。次に、カーネル内のblockIdxとthreadIdxの値からrとcを計算します。しかし、あなたがしたいと思う...私はこれを私の答えに入れようとしました... – jmilloy

+0

それは2つの質問のように見えましたが、私は2つの質問としてそれを書こうとした場合、文脈がそこにあるとは思わなかった – Derek

答えて

1

3つの値を計算するカーネルがあるとしましょう。構成内の各スレッドは、各(r、c)ペアの3つの値を計算します。

__global__ value_kernel(Y, H, X, W) 
{ 
    r = blockIdx.x + Y; 
    c = threadIdx.x + W; 

    chan1value = ... 
    chan2value = ... 
    chan3value = ... 
} 

上記のカーネルで合計(完全に並列)を計算することはできません。上記のように+ =を使用することはできません。そして、あなたは、各ブロック(行)に一つだけのスレッドがある場合は...このように、1つのカーネルに

__global__ both_kernel(Y, H, X, W) 
{ 
    r = blockIdx.x + Y; 
    c = threadIdx.x + W; 

    chan1value = ... 
    chan2value = ... 
    chan3value = ... 

    if(threadIdx.x == 0) 
    { 
     ch1RowSum = 0; 
     ch2RowSum = 0; 
     ch3RowSum = 0; 

     for(i=0; i<blockDim.x; i++) 
     { 
      ch1RowSum += chan1value; 
      ch2RowSum += chan2value; 
      ch3RowSum += chan3value; 
     } 

     ch1Mean = ch1RowSum/blockDim.x; 
     ch2Mean = ch2RowSum/blockDim.x; 
     ch3Mean = ch3RowSum/blockDim.x; 
    } 
} 

をそれをすべて合計しないと意味入れることができますが、それは最初の値のカーネルを使用するために、おそらくより良いですし、合計と手段の両方のための第2のカーネル...下のカーネルをさらに並列化することができます。別のカーネルを使用すると、準備が整ったらそれに集中することができます。

__global__ sum_kernel(Y,W) 
{ 
    r = blockIdx.x + Y; 

    ch1RowSum = 0; 
    ch2RowSum = 0; 
    ch3RowSum = 0; 

    for(i=0; i<W; i++) 
    { 
     ch1RowSum += chan1value; 
     ch2RowSum += chan2value; 
     ch3RowSum += chan3value; 
    } 

    ch1Mean = ch1RowSum/W; 
    ch2Mean = ch2RowSum/W; 
    ch3Mean = ch3RowSum/W; 
} 
+0

あなたはsum/meanを並列化できると言っています...あなたが望むものは削減です。 (多くの利用可能な例の1つ:http://supercomputingblog.com/cuda/cuda-tutorial-3-thread-communication/) – jmilloy

+0

ここでRやCの値を実際に使用していないことがわかりました。 blockIdx.x * threadIdx.xのようなものがblockIdx.x + Yより大きい場合、No Opを実行するための何らかのチェックが必要ですか?それは正確にどのように見えるでしょうか? – Derek

+0

コードでrまたはcを使用していませんでした。グリッド位置(r、c)ごとに計算される3つの値があります。 1つのスレッドで1つの値セットを計算したいと思うでしょう。カーネルを起動するときは、ブロックごとにrブロックとcスレッドを起動します。次に、各スレッドでブロックIDとスレッドIDからrとcを計算できます。私は、rとcは値の計算のための入力にアクセスするために使用され、そして/またはそれらは直接使用されると仮定します。 (あなたが必要以上に多くのスレッドやブロックを持つカーネルを起動したら、あなたの境界を確認してください... if(r> = #rows || c> = #cols)return;) – jmilloy