CUDA - 块和线程

时间:2012-02-18 15:52:00

标签: parallel-processing cuda

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

2 个答案:

答案 0 :(得分:1)

我认为这个问题很难(如果不是不可能的话)回答,因为它确实取决于算法及其运作方式。由于我无法看到你的实现,我可以给你一些线索:

  1. 不要使用全局记忆&检查如何最大限度地使用共享内存。通常可以很好地了解线程如何访问内存以及如何检索数据等。

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

  3. 由于块由32个线程中的组线程组成,因此如果块中的线程数是32的倍数,则最好是这样,因此不会得到包含3个线程等的warp。 / p>

  4. 避免在经线中发散路径。

  5. 我希望它有所帮助。

答案 1 :(得分:1)

@Chris点也非常重要,但更多地依赖于算法本身。

  1. 检查Cuda手册中有关内存查找的线程对齐方式。共享内存数组的大小也应为16的倍数。

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

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

  4. 如果没有显示代码,没有人可以告诉你什么是最好的或为什么性能发生变化。

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

    计算该值的重要值是:

    • 每个多处理器的最大驻留线程数
    • 每个多处理器的最大驻留块数
    • 每个块的最大线程数
    • 每个多处理器的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个线程< - 33%的GPU将空闲
      

    书中也提到了这一点:

         

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

    良好的编程建议:

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

      /*
       * ////////////////////////
       * // 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
       */