管理CUDA的入住率

时间:2016-10-17 11:08:41

标签: c++ performance cuda gpu nvidia

早上好。

我开始学习cuda编程,我正在考虑表现。我在CUDA网站上读到,在其他方面表现良好,我们应该考虑以下四个方面:

http://docs.nvidia.com/gameworks/content/developertools/desktop/analysis/report/cudaexperiments/kernellevel/achievedoccupancy.htm

- 每个SM(系统多处理器)  每SM的块数   - 每个SM注册   - 每个SM的共享内存

所以我正在讨论第一件事情,根据GPU,我根据每个SM的最大warp和每个SM的块来定义内核的尺寸。我的任务是执行十亿的总和来衡量哪种方法更好。

我所做的是一个for循环,我在每次迭代时启动一个最大化占用率的内核。例如,对于NVidia 1080 GPU,我读到了:

int max_blocks = 32; //maximum number of active blocks per SM   int max_threads_per_Block = 64; //maximum number of active threads per SM   int max_threads = 2048;

每个SM总共提供2048个线程,并保证最大占用率。这个GPU可以有64个活动warp,每个warrt有32个线程。在这个GPU中,一个活动块有2个warp,这意味着每个块一次可以有64个活动线程。有了这个,我按如下方式启动内核:

dim3 threadsPerBlock(max_threads_per_Block);   dim3 numBlocks(max_blocks); VecAdd<<<numBlocks, threadsPerBlock>>>(d_A, d_B, d_C,max_threads);

我惊讶地注意到,如果我直接启动此内核,如:

int N = total_ops; //in this case one thousand millions   dim3 threadsPerBlock(256);    dim3 numBlocks(2*N / threadsPerBlock.x); VecAdd<<<numBlocks, threadsPerBlock>>>(d_A, d_B, d_C,);

性能更好(消耗时间)。我在相同的执行中启动相同的实验5次以避免异常值。我的问题是:有没有办法管理占用率以获得比编译器和运行时API更好的结果?我知道我尝试做的优化已经以某种方式由GPU管理。我理解,如果有一份文件解释我们应该如何启动软件(上面的链接)以获得良好的性能,那么它应该是一种控制它的方法。

谢谢

1 个答案:

答案 0 :(得分:2)

在你的第一个例子中,

int max_blocks = 32;            //maximum number of active blocks per SM
int max_threads_per_Block = 64; //maximum number of active threads per SM
int max_threads = 2048;

dim3 threadsPerBlock(max_threads_per_Block);
dim3 numBlocks(max_blocks);
VecAdd<<<numBlocks, threadsPerBlock>>>(d_A, d_B, d_C,max_threads);

您需要根据需要为每个块启动尽可能多的块和线程,以完全加载一个 SM。但是,您的GTX 1080有 20 SM,因此您的入住率仅为1/20 = 5%。

在第二个例子中,

int N = total_ops;              //in this case one thousand millions
dim3 threadsPerBlock(256);
dim3 numBlocks(2*N / threadsPerBlock.x);
VecAdd<<<numBlocks, threadsPerBlock>>>(d_A, d_B, d_C,);

您正在启动大量的块,这允许GPU根据需要并行执行多达100%的占用率(资源允许,在简单的向量添加的情况下这不应该是一个问题)。因此表现更好。

虽然您可以在第一个示例中将块数乘以20以获得与第二个示例相同的性能,但第二个示例中的模式是首选,因为它不涉及所使用的GPU的特定配置。因此代码将完全加载任何大范围的GPU。

另一方面,作为存储器绑定算法的向量加法并不特别适合于证明占用的效果。但是,您仍然看到差异,因为完全加载内存子系统需要一定的最小内存事务数量(由内存带宽乘以内存访问的延迟确定),并且5%的占用率示例低于此最小值