私はCUDAで小さなプログラムを開発しようとしていますが、SLOWだったので、いくつかのテストを行って少しググっていました。単一の変数はデフォルトでローカルスレッドメモリ内に保存されますが、配列は通常はそうではないことがわかりました。それが実行に非常に時間がかかる理由だと思います。今、私は疑問に思います:ローカルスレッドメモリは少なくとも16KBである必要があり、私の配列は52文字の長さなので、ローカルメモリに格納する方法はありますか(構文は:)
それは次のようなものではありません:
__global__ my_kernel(int a)
{
__local__ unsigned char p[50];
}
必要なのはこれだけです:
__global__ my_kernel(int a)
{
unsigned char p[50];
........
}
必要に応じて、コンパイラーはこれを自動的にスピルしてローカルメモリーをスレッド化します。ただし、ローカルメモリはGPU以外のSDRAMに格納され、グローバルメモリと同じくらい遅いことに注意してください。したがって、これによってパフォーマンスが向上することを期待している場合、失望している可能性があります。
〜これに遭遇した人のために〜
簡単に言えば、各スレッドの配列を作成するには、デバイスのメモリにそれらを作成します。これを行うには、スレッドごとに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)];
...
}