【问题标题】:CUDA - Blocks and ThreadsCUDA - 块和线程
【发布时间】:2012-02-18 15:51:59
【问题描述】:

我在 GPU 上实现了一个字符串匹配算法。与算法的顺序版本相比,并行版本的搜索时间已大大减少,但通过使用不同数量的块和线程,我得到不同的结果。 如何确定块数和线程数以获得最佳结果?

【问题讨论】:

  • “使用不同数量的块和线程我得到不同的结果”是什么意思?你是说性能不同,还是说代码不行?

标签: parallel-processing cuda


【解决方案1】:

我认为这个问题即使不是不可能也很难回答,因为它实际上取决于算法及其运行方式。由于我看不到你的实现,我可以给你一些线索:

  1. 不要使用全局内存并检查如何最大限度地使用共享内存。大致了解线程如何访问内存以及如何检索数据等。

  2. 了解您的经线是如何运作的。有时,如果您在线程和数据之间存在 1 对 1 映射,warp 中的线程可能会等待其他线程完成。因此,您可以将线程映射到多个数据,以便它们保持忙碌状态,而不是这种 1 对 1 映射。

  3. 1234563 /p>
  4. 避免曲折中的分歧路径。

我希望它会有所帮助。

【讨论】:

    【解决方案2】:

    @Chris 积分也很重要,但更多地取决于算法本身。

    1. 查看 Cuda 手册,了解有关内存查找的线程对齐。共享内存数组的大小也应该是 16 的倍数。

    2. 使用合并的全局内存读取。但根据算法设计,这通常是这种情况,使用共享内存会有所帮助。

    3. 尽可能不要在全局内存中使用原子操作,或者根本不要使用。他们很慢。一些使用原子操作的算法可以使用不同的技术重写。

    没有显示的代码,没有人可以告诉您什么是最好的或性能变化的原因。

    内核中每个块的线程数是最重要的值。

    计算该值的重要值是:

    • 每个多处理器的最大驻留线程数
    • 每个多处理器的最大驻留块数
    • 每个块的最大线程数
    • 每个多处理器的 32 位寄存器数

    您的算法应该可以在所有 GPU 达到 100% 占用率时进行扩展。为此,我为自己创建了一个辅助类,它自动检测所用 GPU 的最佳线程数,并将其作为 DEFINE 传递给内核。

    /**
     * Number of Threads in a Block
     *
     * Maximum number of resident blocks per multiprocessor : 8
     *
     * ///////////////////
     * Compute capability:
     * ///////////////////
     *
     * Cuda [1.0 - 1.1] =   
     *  Maximum number of resident threads per multiprocessor 768
     *  Optimal Usage: 768 / 8 = 96
     * Cuda [1.2 - 1.3] =
     *  Maximum number of resident threads per multiprocessor 1024
     *  Optimal Usage: 1024 / 8 = 128
     * Cuda [2.x] =
     *  Maximum number of resident threads per multiprocessor 1536
     *  Optimal Usage: 1536 / 8 = 192
     */ 
    public static int BLOCK_SIZE_DEF = 96;
    

    以 Cuda 1.1 为例,每个 SM 拥有 786 个常驻线程

    • 8 个块 * 每个块 96 个线程 = 786 个线程
    • 3 个块 * 每个块 256 个线程 = 786 个线程
    • 1 个块 * 每个块 512 个线程 = 512 个线程

    这在书中也有提及:

    大规模并行处理器编程:实践方法(GPU 计算系列的应用)

    良好的编程建议:

    1. 分析您的内核代码并记下它可以处理的最大线程数或它可以处理多少个“单元”。
    2. 同时输出您的寄存器使用情况并尝试将其降低到相应的目标 CUDA 版本。因为如果您在内核中使用过多的寄存器,则会执行较少的块,从而导致占用率和性能降低。
      示例:使用 Cuda 1.1 并使用每个 SM 768 个驻留线程的最佳数量,您有 8192寄存器使用。这导致每个线程/内核最多有 8192 / 768 = 10 个寄存器。如果您使用 11,GPU 将使用 1 Block 少,从而导致性能下降。

    示例:我的一个与矩阵无关的行向量归一化内核。

    /*
     * ////////////////////////
     * // Compute capability //
     * ////////////////////////
     *
     * Used 12 registers, 540+16 bytes smem, 36 bytes cmem[1]
     * Used 10 registers, 540+16 bytes smem, 36 bytes cmem[1] <-- with -maxregcount 10 Limit for Cuda 1.1
     * I:   Maximum number of Rows = max(x-dim)^max(dimGrid)
     * II:  Maximum number of Columns = unlimited, since they are loaded in a tile loop
     *
     * Cuda [1.0 - 1.3]: 
     * I:   65535^2 = 4.294.836.225
     *
     * Cuda [2.0]:
     * II:  65535^3 = 281.462.092.005.375
     */
    

    【讨论】:

      猜你喜欢
      • 2012-05-13
      • 2015-03-16
      • 2014-05-05
      • 2020-08-29
      • 2021-03-08
      • 2019-05-13
      • 2012-09-05
      • 2013-11-28
      • 1970-01-01
      相关资源
      最近更新 更多