web-dev-qa-db-ja.com

CUDAカーネルでは、「ローカルスレッドメモリ」に配列をどのように格納しますか?

私はCUDAで小さなプログラムを開発しようとしていますが、SLOWだったので、いくつかのテストを行って少しググっていました。単一の変数はデフォルトでローカルスレッドメモリ内に保存されますが、配列は通常はそうではないことがわかりました。それが実行に非常に時間がかかる理由だと思います。今、私は疑問に思います:ローカルスレッドメモリは少なくとも16KBである必要があり、私の配列は52文字の長さなので、ローカルメモリに格納する方法はありますか(構文は:)

それは次のようなものではありません:

__global__ my_kernel(int a)
{
  __local__ unsigned char p[50];
}
24
Matteo Monti

必要なのはこれだけです:

__global__ my_kernel(int a)
{
    unsigned char p[50];
    ........
}

必要に応じて、コンパイラーはこれを自動的にスピルしてローカルメモリーをスレッド化します。ただし、ローカルメモリはGPU以外のSDRAMに格納され、グローバルメモリと同じくらい遅いことに注意してください。したがって、これによってパフォーマンスが向上することを期待している場合、失望している可能性があります。

11
talonmies

〜これに遭遇した人のために〜

簡単に言えば、各スレッドの配列を作成するには、デバイスのメモリにそれらを作成します。これを行うには、スレッドごとにsharedメモリを少し切り出すことができます。競合やパフォーマンスの低下を防ぐために、特別な注意を払う必要があります。

以下は、2015年のMaxim Milakovによる nvidiaブログ投稿 の例です。

// Should be multiple of 32
#define THREADBLOCK_SIZE 64 
// Could be any number, but the whole array should fit into shared memory 
#define ARRAY_SIZE 32 

__device__ __forceinline__ int no_bank_conflict_index(int thread_id, int logical_index)
{
    return logical_index * THREADBLOCK_SIZE + thread_id;
}

__global__ void kernel5(float * buf, int * index_buf)
{
    // Declare shared memory array A which will hold virtual 
    // private arrays of size ARRAY_SIZE elements for all 
    // THREADBLOCK_SIZE threads of a threadblock
    __shared__ float A[ARRAY_SIZE * THREADBLOCK_SIZE]; 
    ...
    int index = index_buf[threadIdx.x + blockIdx.x * blockDim.x];

    // Here we assume thread block is 1D so threadIdx.x 
    // enumerates all threads in the thread block
    float val = A[no_bank_conflict_index(threadIdx.x, index)];
    ...
}
1
Sunsetquest