0. 前言
在一个 CUDA 课程的考试中由于这个地方的理解问题导致没有成功 pass,应该如何设置 BlockNum 呢?
1. 参数
- compute capability, CC
这个也就是计算架构,对应于具体的 NVIDIA 显卡型号,可以在编译时作为 option 输入
- ThreadsPerBlock
这个参数是最常见的,也就是 blockDim
, 自己设置的是1024, 计算架构会决定 block 内线程数的上限
- RegistersPerThread
一直没有设置过这个参数,ptxas info 会给给出具体的使用数据
1.1 问题
接下来问题出现了,到底应该怎么设置 gridDim 呢?也就是 BlockNums. 在测试代码中数据量 N=10000000
, 自己的理解是我一个 block 用1024个 threads,使用 256 个block,这样的话总共有 256*1024 个 threads 可以并行工作,那么我用 for 循环加上步长 stride = blockDim.x * gridDim.x
来实现 N
个数据的计算,也就是
#define N 10000000
#define THREADS_PER_BLOCK 1024
#define BLOCK_NUMS 256
//#define BLOCK_NUMS ((N + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK)
__global__ void gpu_histogram(int *input, int count, int *output)
{
int index = blockIdx.x * blockDim.x + threadIdx.x;
int stride = blockDim.x * gridDim.x;
for(int i = index;i<count;i+=stride){
int target = input[index] / 50;
assert(target >= 0 && target < BUCKETS_COUNT);
atomicAdd(&output[target],1);
}
__syncthreads();
}
int main(){
...
gpu_histogram<<<BLOCK_NUMS, THREADS_PER_BLOCK>>>(...);
...
}
但是这样是没法通过的,把 #define BLOCK_NUMS 256
修改为 #define BLOCK_NUMS ((N + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK)
才能得到正确结果
1.2 思考
我不要去关注 gridDim
这个参数的设置,设置好 ThreadsPerBlock 之后通过计算直接得到 BlockNums 这个数,不需要去考虑硬件最多支持多少 block 并行。
我们在程序中设定了需要跑多少个 block,并不意味着计算机会同时运行完这些 block,有多少 block 在并行是由计算机硬件决定的。设置好数量和处理逻辑之后交给计算机去执行就OK。所以推荐都通过 ((N + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK)
这种方式去计算
至于为什么设置为 256 结果会出错,目前还没有理解