执行复杂的线程索引计算会对性能产生影响



我刚刚问过自己,使用例如threadIdx.x进行复杂的索引计算是否会对性能产生影响。内核一上传到设备,这些变量就变为常量了吗?

我想导航到一个巨大的数组,其中索引取决于threadIdx.x、threadIdx.y和threadId*.z。我需要例如之类的模运算

array[threadIdx.y % 2 + ...]

在索引计算中有一个加法和一个模数。

来自CUDA编程指南:operator+的吞吐量非常高(3.5计算能力的GPU为160)。

CCD_ 2需要数十个具有类似于CCD_ 3的吞吐量的操作。

在您的情况下,您使用的是带有文字常量的operator%,编译器很可能会对其进行优化。此外,您的常数是2的幂,因此编译器将用按位的operator&(与operator+的吞吐量相同)替换它。

对应用程序进行概要分析是很重要的,这样可以避免在优化算术运算时浪费时间,而不会获得任何性能。算术运算通常被内存加载和存储操作完全隐藏,在这种情况下,您需要专注于优化内存吞吐量。

我假设

array[threadIdx.y % 2 + ...]

只是一个例子。

一般来说,%操作可能较慢。加快指数计算的一个有用技巧是注意

foo%n==foo&(n-1) if n is a power of 2

因此,对于上面的例子,编译器可能会为您进行优化,但如果您有foo%n,那么上面的技巧值得使用。

如果有人感兴趣,我已经评估了相应的PTX代码。

(1) 复杂的线程ID计算会对性能产生影响。"threadIdx.x"等不是常数。

(2) "threadIdx.y%2"是有效实现的,对应于"threadIdx.y&0x00000001"(Cuda Toolkit 5.5)。

最新更新