2017-05-28 5 views
-2

:ここ要素ごとのadd()CUDAカーネルでは、なぜblockDim.x * gridDim.xを超えていますか?私は、CUDAプログラミングを学んだし、私はトラブルこの要素ごとの加算カーネルでストライドを理解した

// performs vector addition 
// a, b, c are vectors and added values are stored in a and b, while the results are stored in c. 

#define N 10 

__global__ void add(int* a, int* b, int* c) { 
    int tid = threadIdx.x + blockIdx.x*blockDim.x; 
    while(tid < N) { 
     c[tid] = a[tid] + b[tid]; 
     tid += blockDim.x * gridDim.x; 
    } 
} 

はこれのCPUバージョンです:

void add(int* a, int* b, int* c) { 
    int tid = 0; // start from CPU 0 
    while(tid < N) { 
     c[tid] = a[tid] + b[tid]; 
     tid += 2; // assume there are 2 CPUs 
    } 
} 

私はいくつかのチュートリアルを行って、すべてのそれらはaddカーネルで始まります。

tidのストライドはどこから来ていますか?


EDIT

今、私は一種のストライドの値が何を意味し得ます。 CPUの場合、2つの実行スレッドのうちの1つが終了すると、別のコアでtid + 1が処理されるため、tidに2を追加する必要があります。

しかし、ここでの質問は、CPU2のtidとは異なるCPU1のtidですか?私は彼らが同じ変数ではないと思うし、値はCPUの別々のメモリに格納されていますか?

+0

あなたの編集はすべてCPUに関するものですが、あなたのフラグは 'cuda'と' gpgpu'です...そして、あなたはどこからCPUバージョンを持っていますか? CPU上でコードを並列化する方法を読んだことはありますか?チュートリアルのコードをペーストする場合は、チュートリアルへのリンクを追加してください。あなたは[プログラミングガイドNvidia](http://docs.nvidia.com/cuda/cuda-c-programming-guide/#axzz4iMq8V9Ae)を見てきましたか?非常にコンパクトですが、わかりやすく、より簡単な 'add'カーネルではじまりません。 – Shadow

答えて

1

CUDAプログラミングモデルでは、計算は「スレッド」の「ブロック」によって実行されます。各スレッドは、ブロック内のスレッドIDとブロックIDを持ちます。

  • ブロック0、スレッド0
  • ブロック0、スレッド1
  • :あなたはサイズ3の2個のブロックを使用してカーネルを立ち上げたのであれば、CPUを搭載した、あなたの例のように、あなたは6スレッドを持っていますブロック0、スレッド2
  • ブロック1、スレッド0
  • ブロック1、スレッド1つの
  • ブロック1、スレッド2

tid変数は、ブロックとスレッド内のスレッドIDを組み合わせて、グリッド内の全体的なスレッドIDになります。この例では、これらのスレッドのtidの値は0..5の範囲を正確にカバーすることに注意してください。

ここで、6つのスレッドが配列要素0..5に対して追加操作を実行し、追加の要素に進む必要がある場合、それらのすべてのスレッドが新しい明確なインデックスを取得できるようにインデックスを進めることができます。作業し、要素が明らかにされていないこと。 6のストライド(この例では)はそうします:スレッドは6.11、12..17、18..23などを処理します。したがって、最初のスレッドは0、6、12、18などで動作し、2番目のスレッドは1、7、13、19などで動作します。

次のようにそれが書かれていた場合、おそらくカーネルが明確になります:コードのあなたの「CPUのバージョン」については

__global__ void add(int* a, int* b, int* c) { 
    int overall_thread_id = threadIdx.x + blockIdx.x*blockDim.x; 
    int overall_num_threads = blockDim.x * gridDim.x; 
    int pos = overall_thread_id; 
    while(pos < N) { 
     c[pos] = a[pos] + b[pos]; 
     pos += overall_num_threads; 
    } 
} 

を - それは動作しませんあなたはおそらく上の異なるスレッドを(持っていた場合であってもいるので、さまざまなコア)が実行すると、すべてtidが0になり、同じ方法で進みます。つまり、GPUの「スレッド」とは異なり、それぞれ異なるtidで始まります。tid = index_of_thread_among_Workers()と2つのワーカースレッドを初期化するCPU関数があった場合、最初のスレッドは0,2,4,6などで動作し、2番目のワーカースレッド(インデックス1)は1、3、5、7などで動作します。

関連する問題