是否值得用 CUDA 内核中的 __umul24 函数替换所有乘法?我阅读了不同和相反的意见,但我仍然无法做出标杆来弄清楚
2 回答
仅在具有 fermi 之前架构的设备中,即具有 2.0 之前的 cuda 功能,其中整数运算单元为 24 位。
在功能 >= 2.0 的 Cuda 设备上,架构为 32 位,_umul24 会更慢而不是更快。原因是它必须用 32 位架构模拟 24 位操作。
现在的问题是:为速度增益付出努力是否值得?可能不是。
只是想表达与 Ashwin/fabrizioM 稍有不同的观点......
如果您只是想自学 CUDA,那么他们的答案可能或多或少可以接受。但是,如果您实际上是在尝试将生产级应用程序部署到商业或研究环境中,那么这种态度通常是不可接受的,除非您绝对确定您的最终用户(或者您,如果您是最终用户)用户)是费米或更高版本。
更有可能的是,许多将在旧机器上运行 CUDA 的用户将受益于使用 Compute Level 适当的功能。它并不像 Ashwin/fabrizioM 所说的那么难。
例如,在我正在处理的代码中,我正在使用:
//For prior to Fermi use umul, for Fermi on, use
//native mult.
__device__ inline void MultiplyFermi(unsigned int a, unsigned int b)
{ a*b; }
__device__ inline void MultiplyAddFermi(unsigned int a, unsigned int b,
unsigned int c)
{ a*b+c; }
__device__ inline void MultiplyOld(unsigned int a, unsigned int b)
{ __umul24(a,b); }
__device__ inline void MultiplyAddOld(unsigned int a, unsigned int b,
unsigned int c)
{ __umul24(a,b)+c; }
//Maximum Occupancy =
//16384
void GetComputeCharacteristics(ComputeCapabilityLimits_t MyCapability)
{
cudaDeviceProp DeviceProperties;
cudaGetDeviceProperties(&DeviceProperties, 0 );
MyCapability.ComputeCapability =
double(DeviceProperties.major)+ double(DeviceProperties.minor)*0.1;
}
现在这里有一个缺点。它是什么?
好吧,任何使用乘法的内核,都必须有两个不同版本的内核。
这值得么?
好吧,考虑一下,这是一项微不足道的复制和粘贴工作,而且您正在提高效率,在我看来是的。毕竟,CUDA 在概念上并不是最简单的编程形式(也不是任何并行编程)。如果性能不重要,问问自己:为什么要使用 CUDA?
如果性能很关键,那么懒惰的编码并放弃旧设备或发布不太理想的执行是疏忽大意的,除非您绝对有信心可以放弃对部署的旧支持(允许最佳执行)。
对于大多数人来说,提供遗留支持是有意义的,因为一旦您意识到如何做到这一点并不难。请注意,这意味着您还需要更新代码,以适应未来架构的变化。
通常,您应该注意代码针对的最新版本,编写时间,并且如果他们的计算能力超出了您最新实现的优化范围,可能会向用户打印某种警告。