我在GPU上实现了字符串匹配算法。与算法的顺序版本相比,并行版本的搜索时间大大减少,但是通过使用不同数量的块和线程,我得到不同的结果。 如何确定块和碎片的数量以获得最佳结果?
答案 0 :(得分:1)
我认为这个问题很难(如果不是不可能的话)回答,因为它确实取决于算法及其运作方式。由于我无法看到你的实现,我可以给你一些线索:
不要使用全局记忆&检查如何最大限度地使用共享内存。通常可以很好地了解线程如何访问内存以及如何检索数据等。
了解经线的运作方式。有时,如果线程和数据之间有1对1的映射,则warp中的线程可能会等待其他线程完成。因此,您可以将线程映射到多个数据,而不是这种1对1映射,以便它们保持忙碌状态。
由于块由32个线程中的组线程组成,因此如果块中的线程数是32的倍数,则最好是这样,因此不会得到包含3个线程等的warp。 / p>
避免在经线中发散路径。
我希望它有所帮助。
答案 1 :(得分:1)
@Chris点也非常重要,但更多地依赖于算法本身。
检查Cuda手册中有关内存查找的线程对齐方式。共享内存数组的大小也应为16的倍数。
使用合并的全局内存读取。但是通过算法设计,通常就是这种情况,使用共享内存有帮助。
不要在全局内存中使用原子操作,或者根本不使用原子操作。它们很慢。一些使用原子操作的算法可以使用不同的技术重写。
如果没有显示代码,没有人可以告诉你什么是最好的或为什么性能发生变化。
内核每个块的线程数是最重要的值。
计算该值的重要值是:
您的算法应该可以在所有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个常驻线程
书中也提到了这一点:
大规模并行处理器编程:实践方法(GPU计算系列的应用)
良好的编程建议:
示例:一个与矩阵无关的行向量归一化我的内核。
/*
* ////////////////////////
* // 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
*/