共享内存优化混淆

5
我已经用CUDA编写了一个应用程序,每个块使用1kb的共享内存。
由于每个SM只有16kb的共享内存,总共只能容纳16个块,对吧?虽然一次只能调度8个块,但是如果某个块正在执行内存操作,另一个块将被调度到GPU上,但是所有共享内存都被其他16个已经在那里调度的块使用了。
那么,CUDA是否不会在同一个SM上调度更多的块,除非之前分配的块完全完成?
还是说它会将某些块的共享内存移动到全局内存,并在那里分配其他块?在这种情况下,我们需要担心全局内存访问延迟吗?
1个回答

7
它不是这样工作的。在单个SM上同时运行的块数将始终是以下条件中的最小值:
  1. 8个块
  2. 静态和动态分配的共享内存总和小于16kb或48kb的块数,具体取决于GPU架构和设置。还有共享内存页面大小限制,这意味着每个块的分配量会向上舍入到页面大小的下一个最大倍数。
  3. 每个块寄存器使用量总和小于8192/16384/32678(取决于架构)的块数。还有寄存器文件页面大小,这意味着每个块的分配量会向上舍入到页面大小的下一个最大倍数。
就是这样。没有“分页”共享内存以容纳更多块。NVIDIA为计算占用率而制作了一份电子表格,该工具包随附并可作为单独的下载提供。您可以在其中看到确切的规则。它们也在CUDA编程指南的第4.2节中讨论。

这是否意味着有时最好不使用共享内存?因为会有更多的块并行运行? - scatman
这真的取决于情况。共享内存比寄存器慢得多,而寄存器没有银行冲突,因此如果可能的话,始终最好使用寄存器而不是共享内存。传统上,共享内存的用途是允许块内线程之间重复使用数据,在Fermi之前,它非常有效。在Fermi中,共享内存的情况可能会稍微不那么令人信服。L1和L2缓存意味着您通常可以获得共享内存产生的很大一部分,而无需做任何事情,并且没有银行冲突或序列化效应需要担心。 - talonmies
那么,如果在某一时刻将某些块调度到一个SM上,并且现在所有warp都在等待内存操作完成,那么CUDA会在同一SM上调度其他块(已分配块的共享存储器数据将会发生什么?)还是它会等待已分配块完成它们的操作? - peeyush
硬件将始终安排尽可能多的块运行,直到没有更多资源可用,以便可以安排更多块。 如果SM上的每个活动warp都在等待内存事务或在同步障碍处停顿,则SM将被阻塞。 调度启发式算法的工作原理尚未正式记录,但一致意见似乎是,在Fermi卡之前,不会安排新的块,直到SM上的每个块都完成,但在Fermi上比那更灵活。 - talonmies

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接