2013-04-20 123 views
9

在CUDA中使用常量的最佳方式是哪种?在CUDA中使用常量

一种方式是在不断的内存来定义常量,如:

// CUDA global constants 
__constant__ int M; 

int main(void) 
{ 
    ... 
    cudaMemcpyToSymbol("M", &M, sizeof(M)); 
    ... 
} 

的备选方法是使用C预处理:

#define M = ... 

我认为定义与C预处理器常数速度要快得多。那么在CUDA设备上使用恒定内存的好处是什么?被在编译时已知

+1

编译时已知的常量应该使用预处理器宏(即'#define')来定义。在其他情况下,'__constant__' [变量](http://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#constant)可能是CUDA程序员用来优化访问代码的一个选项不改变的计算变量。请注意,使用''M''来引用一个符号在cuda 5中不再有效。 – 2013-04-20 12:43:28

+0

知道这两种可能性之间的运行时间差异是多么有趣。我是currenlty在一些cfd代码上工作,我想将参数作为选项传递给程序,因此有必要使用第一种方法。另一方面,如果我使用预处理器宏,这是不可能的。 – jrsm 2013-04-20 14:13:50

+0

既然你的第二个例子不生成任何类型的机器代码,这不是一个明智的问题。您需要提出实际的运行时使用情况,以便对此问题有任何意义。对于将单个标量立即值初始加载到变量或寄存器中,第二种方法将始终更快。 – 2013-04-20 14:14:27

回答

9
  1. 常数应该使用 预处理宏(例如#define)或经由全球/文件范围内的C/C++ const变量来定义。
  2. __constant__ memory的使用对于那些使用某些在内核持续时间内不发生变化并且存在某些访问模式(例如,所有线程同时访问相同值)的程序的应用程序可能是有益的。这并不比满足上述第1项要求的常数更好或更快。
  3. 如果通过程序进行选择的数量在数量上相对较少,而这些选择会影响内核执行额外的编译时优化一个可能的方法是使用templated code/kernels
+2

由于多种原因,使用C/C++样式常量,预处理器宏或C++模板可能比使用__constant__内存更快:1.编译器可以应用其他优化,以及2.常量可以作为直接内嵌在指令中。常量高速缓存访​​问可能会错过常量高速缓存,增加额外的延迟 – 2014-06-10 06:07:17

+0

由于每次调用每个线程中的构造函数,不会定义非重要类型的'#definitiond常量? – 2016-09-12 08:15:37

4

常规的C/C++风格常量:在CUDA C(本身是C99的修改)中,常量是绝对编译时间实体。考虑到GPU处理的性质,考虑到在NVCC中发生的优化量非常大,这并不奇怪。

#define:宏一如既往非常不雅但在捏中有用。

__constant__变量说明符是,但是一个全新的动物,在我看来是一个用词不当的东西。我会放下什么Nvidia已经在下面的空白处here

__constant__限定符可选择与 __device__一起使用,声明的变量:

  • 寓于常量内存空间,
  • 具有应用程序的生命周期,
  • 可以从网格内的所有线程和主机通过运行时库访问(cudaGetSymbolAddress()/ cudaGetSymbolSize()/ cudaMemcpyToSymbol()/ cudaMemcpyFromSymbol())。

Nvidia的文档指定__constant__可在寄存器水平速度(接近零延迟)只要是由一个经纱的所有线程被访问的相同的恒定。

它们在CUDA代码的全局范围内声明。但是,基于个人(当前正在进行的)经验,在分离编译时必须小心使用该说明符,例如分离CUDA代码(.cu和.c)。cuh文件)从你的C/C++代码中加入封装函数到C风格的头文件中。

与传统的“常量”指定变量不同,它们是在运行时从分配设备内存并最终启动内核的主机代码初始化的。我再说一遍,我目前正在使用的代码演示这些可以在内核执行前使用cudaMemcpyToSymbol()在运行时上设置。

鉴于保证访问的L1缓存级别的速度,至少可以说很方便。