web-dev-qa-db-ja.com

CUDAの__shared__メモリはいつ役に立ちますか?

誰かが共有メモリの使い方の非常に簡単な例を教えてくれませんか? Cuda Cプログラミングガイドに含まれている例は、無関係な詳細が散らかっているようです。

たとえば、大きな配列をデバイスのグローバルメモリにコピーし、各要素を2乗したい場合、共有メモリを使用してこれを高速化できますか?それともこの場合は役に立ちませんか?

27
Tudor

あなたが述べた特定のケースでは、共有メモリは次の理由で役に立ちません:各データ要素は一度だけ使用されます。共有メモリが役立つようにするには、適切なアクセスパターンを使用して、共有メモリに転送されたデータを数回使用する必要があります。この理由は単純です。グローバルメモリから読み取るだけで、1回のグローバルメモリ読み取りと0回の共有メモリ読み取りが必要です。最初にそれを共有メモリに読み込むには、1回のグローバルメモリ読み込みと1回の共有メモリ読み込みが必要で、時間がかかります。

以下は簡単な例です。ブロック内の各スレッドは、対応する値の2乗に加えて、その左と右の両方の隣接セルの平均の2乗を計算します。

  __global__ void compute_it(float *data)
  {
     int tid = threadIdx.x;
     __shared__ float myblock[1024];
     float tmp;

     // load the thread's data element into shared memory
     myblock[tid] = data[tid];

     // ensure that all threads have loaded their values into
     // shared memory; otherwise, one thread might be computing
     // on unitialized data.
     __syncthreads();

     // compute the average of this thread's left and right neighbors
     tmp = (myblock[tid > 0 ? tid - 1 : 1023] + myblock[tid < 1023 ? tid + 1 : 0]) * 0.5f;
     // square the previousr result and add my value, squared
     tmp = tmp*tmp + myblock[tid] * myblock[tid];

     // write the result back to global memory
     data[tid] = myblock[tid];
  }

これは、1つのブロックのみを使用して動作するように想定されていることに注意してください。より多くのブロックへの拡張は簡単です。ブロックの次元(1024、1、1)とグリッドの次元(1、1、1)を想定しています。

29
Patrick87

共有メモリを明示的に管理されたキャッシュと考えてください-同じスレッド内または異なるスレッドからデータに複数回アクセスする必要がある場合にのみ役立ちます同じblock。データに1度しかアクセスしない場合、共有メモリは役に立ちません。

10
Paul R