このカーネル関数で共有メモリを利用しようとしていますが、期待したほどパフォーマンスが良くありません。この関数は、私のアプリケーションでは何度も (約 1000 回以上) 呼び出されるため、共有メモリを活用してメモリ レイテンシを回避することを考えていました。しかし、共有メモリを使用しているため、アプリケーションが非常に遅くなったため、明らかに何かが間違っています。
これはカーネルです:
__global__ void AndBitwiseOperation(int* _memory_device, int b1_size, int* b1_memory, int* b2_memory){
int j = 0;
// index GPU - Transaction-wise
unsigned int i = blockIdx.x * blockDim.x + threadIdx.x;
unsigned int tid = threadIdx.x;
// shared variable
extern __shared__ int shared_memory_data[];
extern __shared__ int shared_b1_data[];
extern __shared__ int shared_b2_data[];
// copy from global memory into shared memory and sync threads
shared_b1_data[tid] = b1_memory[tid];
shared_b2_data[tid] = b2_memory[tid];
__syncthreads();
// AND each int bitwise
for(j = 0; j < b1_size; j++)
shared_memory_data[tid] = (shared_b1_data[tid] & shared_b2_data[tid]);
// write result for this block to global memory
_memory_device[i] = shared_memory_data[i];
}
b1 と b2 のサイズは、実行時にしか知ることができない顧客の数に依存するため、共有変数はexternとして宣言されます (ただし、どちらも常に同じサイズです)。
これは私がカーネルを呼び出す方法です:
void Bitmap::And(const Bitmap &b1, const Bitmap &b2)
{
int* _memory_device;
int* b1_memory;
int* b2_memory;
int b1_size = b1.getIntSize();
// allocate memory on GPU
(cudaMalloc((void **)&b1_memory, _memSizeInt * SIZE_UINT));
(cudaMalloc((void **)&b2_memory, _memSizeInt * SIZE_UINT));
(cudaMalloc((void **)&_memory_device, _memSizeInt * SIZE_UINT));
// copy values on GPU
(cudaMemcpy(b1_memory, b1._memory, _memSizeInt * SIZE_UINT, cudaMemcpyHostToDevice ));
(cudaMemcpy(b2_memory, b2._memory, _memSizeInt * SIZE_UINT, cudaMemcpyHostToDevice ));
(cudaMemcpy(_memory_device, _memory, _memSizeInt * SIZE_UINT, cudaMemcpyHostToDevice ));
dim3 dimBlock(1, 1);
dim3 dimGrid(1, 1);
AndBitwiseOperation<<<dimGrid, dimBlock>>>(_memory_device, b1_size, b1_memory, b2_memory);
// return values
(cudaMemcpy(_memory, _memory_device, _memSizeInt * SIZE_UINT, cudaMemcpyDeviceToHost ));
// Free Memory
(cudaFree(b1_memory));
(cudaFree(b2_memory));
(cudaFree(_memory_device));
}
b1 と b2 は、各要素が 4 ビットのビットマップです。要素の数は、顧客の数によって異なります。また、カーネルのパラメーターに問題があります。ブロックまたはスレッドを追加すると、AndBitwiseOperation() が正しい結果を返さないためです。ブロックごとに 1 つのブロックと 1 つのスレッドだけを使用すると、結果は正しくなりますが、カーネルは並列ではありません。
あらゆるアドバイスを歓迎します:)
ありがとう