Cuda 复杂的线程索引计算是否会影响性能?

Cuda 复杂的线程索引计算是否会影响性能?,cuda,Cuda,我刚才问自己,使用例如threadIdx.x的复杂索引计算是否会对性能产生影响。内核上传到设备后,这些变量是否会变为常量 我想导航到一个巨大的数组,其中索引依赖于threadIdx.x、threadIdx.y和threadIdx.z。例如,我需要模运算,比如 array[threadIdx.y % 2 + ...] 我想 array[threadIdx.y % 2 + ...] 这只是一个例子 一般来说,%操作可能很慢。加速指数计算的一个有用技巧是 foo%n==foo&(n-1)

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

我想导航到一个巨大的数组,其中索引依赖于threadIdx.x、threadIdx.y和threadIdx.z。例如,我需要模运算,比如

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

array[threadIdx.y % 2 + ...]
这只是一个例子

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

foo%n==foo&(n-1) if n is a power of 2
因此,对于上面的示例,编译器可能会为您进行此优化,但如果您有
foo%n
,则上述技巧值得使用。

我假设

array[threadIdx.y % 2 + ...]
这只是一个例子

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

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

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

您的索引计算中有一个加法和一个模

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

operator%
需要数十个操作,其吞吐量与
operator+
类似

在您的例子中,您使用的是带有文字常量的
运算符%
,编译器很可能会对其进行优化。此外,常数是两个数(2)的幂,因此编译器将用位
运算符&
(与
运算符+
的吞吐量相同)替换它

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

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

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

operator%
需要数十个操作,其吞吐量与
operator+
类似

在您的例子中,您使用的是带有文字常量的
运算符%
,编译器很可能会对其进行优化。此外,常数是两个数(2)的幂,因此编译器将用位
运算符&
(与
运算符+
的吞吐量相同)替换它

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

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

(1) 复杂的线程ID计算会影响性能。“threadIdx.x”等不是常量


(2) “threadIdx.y%2”的实现效率很高,对应于“threadIdx.y&0x00000001”(Cuda Toolkit 5.5)。

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

(1) 复杂的线程ID计算会影响性能。“threadIdx.x”等不是常量


(2) “threadIdx.y%2”的实现效率很高,对应于“threadIdx.y&0x00000001”(Cuda Toolkit 5.5)。

每次计算都会产生影响,并且有公开信息,说明每次计算和每次读取或写入需要多少个周期。关于内置变量的访问,如
threadIdx
,据我所知,它们可以被视为常量。如果您执行重复的计算,只需将这些计算保存在寄存器中,或者信任您的编译器,并检查您的程序集和内核的gpu ressource使用情况(如果您有足够的寄存器,那么每个sm的并发块不会减少)。我更喜欢编写干净的优化代码,而不是信任你的编译器。每一次计算都会产生影响,并且有公开的信息显示每次计算和每次读写需要多少个周期。关于内置变量的访问,如
threadIdx
,据我所知,它们可以被视为常量。如果您执行重复的计算,只需将这些计算保存在寄存器中,或者信任您的编译器,并检查您的程序集和内核的gpu ressource使用情况(如果您有足够的寄存器,那么每个sm的并发块不会减少)。我更喜欢编写干净的优化代码,而不是信任编译器。