我在 CUDA 中编写了一个小程序,计算 C 数组中有多少个 3 并打印出来。
#include <stdio.h>
#include <assert.h>
#include <cuda.h>
#include <cstdlib>
__global__ void incrementArrayOnDevice(int *a, int N, int *count)
{
int id = blockIdx.x * blockDim.x + threadIdx.x;
//__shared__ int s_a[512]; // one for each thread
//s_a[threadIdx.x] = a[id];
if( id < N )
{
//if( s_a[threadIdx.x] == 3 )
if( a[id] == 3 )
{
atomicAdd(count, 1);
}
}
}
int main(void)
{
int *a_h; // host memory
int *a_d; // device memory
int N = 16777216;
// allocate array on host
a_h = (int*)malloc(sizeof(int) * N);
for(int i = 0; i < N; ++i)
a_h[i] = (i % 3 == 0 ? 3 : 1);
// allocate arrays on device
cudaMalloc(&a_d, sizeof(int) * N);
// copy data from host to device
cudaMemcpy(a_d, a_h, sizeof(int) * N, cudaMemcpyHostToDevice);
// do calculation on device
int blockSize = 512;
int nBlocks = N / blockSize + (N % blockSize == 0 ? 0 : 1);
printf("number of blocks: %d\n", nBlocks);
int count;
int *devCount;
cudaMalloc(&devCount, sizeof(int));
cudaMemset(devCount, 0, sizeof(int));
incrementArrayOnDevice<<<nBlocks, blockSize>>> (a_d, N, devCount);
// retrieve result from device
cudaMemcpy(&count, devCount, sizeof(int), cudaMemcpyDeviceToHost);
printf("%d\n", count);
free(a_h);
cudaFree(a_d);
cudaFree(devCount);
}
我得到的结果是:real 0m3.025s user 0m2.989s sys 0m0.029s
当我在具有 4 个线程的 CPU 上运行它时,我得到: real 0m0.101s user 0m0.100s sys 0m0.024s
请注意,GPU 是旧的——我不知道确切的型号,因为我没有 root 访问权限,但它运行的 OpenGL 版本是 1.2,使用 MESA 驱动程序。
难道我做错了什么?我该怎么做才能让它运行得更快?
注意:我尝试为每个块使用存储桶(因此每个块的 atomicAdd()s 会减少),但我得到了完全相同的性能。我还尝试将分配给该块的 512 个整数复制到共享内存块(您可以在评论中看到它)并且时间再次相同。