在CUDA中启动的最有效区块数? 我有一个非常大的数组,包含N0元素 每个线程将循环并在m元素上运行 我已经修复了每个块的TBP线程 CUDA约束每个网格的块BPG元素> TBP=32 < /代码> ./P> 我可以触发3个32线程块,每个线程循环一次(m=1),这意味着3 x 32 x 1=96元素可以在其上操作,即损耗6 或者我可以发射2个32块,其中m=2,这意味着2 x 32 x 2=128元素可以被操作,这是损耗38

在CUDA中启动的最有效区块数? 我有一个非常大的数组,包含N0元素 每个线程将循环并在m元素上运行 我已经修复了每个块的TBP线程 CUDA约束每个网格的块BPG元素> TBP=32 < /代码> ./P> 我可以触发3个32线程块,每个线程循环一次(m=1),这意味着3 x 32 x 1=96元素可以在其上操作,即损耗6 或者我可以发射2个32块,其中m=2,这意味着2 x 32 x 2=128元素可以被操作,这是损耗38,cuda,gpgpu,Cuda,Gpgpu,对于大型阵列(100MB+)和大量环路(10000+),这些因素会变得更大,因此损耗会变得非常大,因此如何最大限度地减少损耗?也就是说,我想要一个优化过程(其中N表示实际完成的工作): 我不会担心“浪费”线程——GPU线程是轻量级的 实际上,您可能希望增加块大小,因为这可能会增加GPU的占用率。请注意,SMX(在GeForce 6xx行中)只能执行16个并发块。将块变大将允许您安排更多线程来隐藏内存访问延迟。这实际上是一个相当复杂的问题,我怀疑是否有O(1)解决方案。 但我猜你们可以在CPU上花

对于大型阵列(100MB+)和大量环路(10000+),这些因素会变得更大,因此损耗会变得非常大,因此如何最大限度地减少损耗?也就是说,我想要一个优化过程(其中
N
表示实际完成的工作):


我不会担心“浪费”线程——GPU线程是轻量级的


实际上,您可能希望增加块大小,因为这可能会增加GPU的占用率。请注意,SMX(在GeForce 6xx行中)只能执行16个并发块。将块变大将允许您安排更多线程来隐藏内存访问延迟。

这实际上是一个相当复杂的问题,我怀疑是否有O(1)解决方案。 但我猜你们可以在CPU上花费一些线性时间来计算最小值


根据您在内核中所做的一切,答案可能会像您引用的优化问题那样简单,也可能不会。例如,如果你将有等待时间的问题,等待彼此完成的线程,等等,那么还有更多的问题需要考虑。 这有一些很好的启发。一些一般要点:

选择每个网格的块

  • 每个网格的块数应大于等于多处理器的数量
  • 内核中越多地使用
    \uu syncthreads()
    ,块就越多(这样一个块可以运行,而另一个块可以等待同步)
选择每个块的线程

  • 经纱尺寸的倍数(即通常为32)

  • 通常,最好选择线程数,使每个块的最大线程数(基于硬件)是线程数的倍数。例如,如果最大线程数为768,则每个块使用256个线程往往比使用512个线程要好,因为一个块上可以同时运行多个线程

  • 考虑一下你的线程是否会共享内存,如果是,你希望共享多少内存


如果这只是一个平行贴图,只需将
m
设置为
N/(块大小*最大网格大小)
。否则,在没有完全自动调整的情况下,很难知道分解问题的最佳方法。您可能会对一个类似的问题感兴趣。“您应该最小化每个线程正在做的工作”?这是我见过的最糟糕的一条CUDA优化建议……有趣的是,上次我检查时,并行计算背后的想法是让许多处理器独立地做很少的工作,而不是相反——那就是CPU。当你没有选择的时候,你让他们做很多工作,但是当你有选择的时候,这不是一个好的做法。如果你像现在这样直言不讳,那么给出一些论据。CUDA块调度过程是轻量级的,但不是免费的。此外,GPU中的内存吞吐量和算术吞吐量存在很大差异。在当前的GK104卡上,大约有3000个Glops单精度峰值吞吐量(假设为纯fmad指令流)和大约50 Gfloat/s的峰值内存带宽。这意味着一个给定的线程每读或写一个32位的字就必须至少执行30个fmad,才能进行计算绑定在其生命周期内处理许多并行工作单元的线程和指令级并行性在CUDA设备上实现高吞吐量方面比其他线程要有效得多。所有用于常见事物(如密集线性代数、FFT等)的最高性能代码都朝着这种GPU编程模式发展。@Aloalo:您还应该阅读Vasily Volkov的其他幻灯片,如上一张。