GPGPU : CUDA C 用の Mutex, Stack の実装について
CUDA に対応した GPU から使える Mutex や Stack の実装のコードが面白かったので, コードを以下に載せます.
以下の Mutex のコードは CUDA の Compute capability 1.2 の GPU で動作します.
struct Mutex { int* value; void InitializeFromHost( void ) { int state = 0; HANDLE_ERROR( cudaMalloc( (void**)& value, sizeof( int ) ) ); HANDLE_ERROR( cudaMemcpy( value, &state, sizeof( int ), cudaMemcpyHostToDevice ) ); } void FinalizeFromHost( void ) { cudaFree( value ); } __device__ void Lock( void ) { while ( atomicCAS( value, 0, 1 ) != 0 ); } __device__ void Unlock( void ) { atomicExch( value, 1 ); } }
以下のスタックのコードは CUDA の Compute capability 2.0 の GPU で動作します.
// 各スレッドごとに使用可能なスタックです. // Stack in local memory. Managed independently for each thread. template<class T, int N> class local_stack { private: T buf[N]; int tos; public: __device__ local_stack() : tos(-1) { } __device__ T const & top() const { return buf[tos]; } __device__ T & top() { return buf[tos]; } __device__ void push(T const & v) { buf[++tos] = v; } __device__ T pop() { return buf[tos--]; } __device__ bool full() { return tos == (N - 1); } __device__ bool empty() { return tos == -1; } }; // こちらは複数のスレッドで利用でき, // グローバルなメモリ上に置かれるものです. // Stacks in global memory. // Same function as local_stack, but accessible from the host. // Interleaved between threads by blocks of THREADS elements. // Independent stack for each thread, // no sharing of data between threads. template<class T, int N, int THREADS> class global_stack { private: T * buf; int free_index; public: // buf should point to an allocated global buffer of // size N * THREADS * sizeof(T) __device__ global_stack(T * buf, int thread_id) : buf(buf), free_index(thread_id) { } __device__ void push(T const & v) { buf[free_index] = v; free_index += THREADS; } __device__ T pop() { free_index -= THREADS; return buf[free_index]; } __device__ bool full() { return free_index >= N * THREADS; } __device__ bool empty() { return free_index < THREADS; } __device__ int size() { return free_index / THREADS; } };