全局内存与CUDA中的动态全局内存分配

时间:2013-10-30 01:17:01

标签: c++ cuda

我有一个需要使用全局内存的CUDA(v5.5)应用程序。理想情况下,我更喜欢使用常量内存,但我已经耗尽了常量内存,并且必须将溢出放在全局内存中。我还有一些需要偶尔编写的变量(在GPU上进行一些减少操作之后),我将它放在全局内存中。

为了阅读,我将以一种简单的方式访问全局内存。我的内核在for循环中调用,并且在内核的每次调用中,每个线程将访问完全相同的全局内存地址而没有偏移。对于写入,在每次内核调用之后,在GPU上执行缩减,并且我必须在循环的下一次迭代之前将结果写入全局内存。但是,在我的应用程序中,读取数据远远超过写入全局内存。

我的问题是,使用动态分配的全局内存,使用全局(变量)范围中声明的全局内存是否有任何优势?我需要的全局内存量将根据应用程序而改变,因此动态分配将因此而优选。我知道我的全局内存使用的上限然而我更关心性能,所以我也可以使用一个大的固定分配静态地声明内存,我肯定不会溢出。考虑到性能,是否有理由偏好一种形式的全局内存分配而不是另一种?它们是否存在于GPU上的相同物理位置,是否以相同的方式缓存,或者两种形式的读取成本是否相同?

2 个答案:

答案 0 :(得分:10)

Global memory可以分配statically(使用__device__),dynamically(使用设备mallocnew)并通过{{ 3}}(例如使用cudaMalloc)。

所有上述方法在物理上分配相同类型的存储器,即从板载(但不是芯片上)DRAM子系统中划出的存储器。无论分配方式如何,此内存都具有相同的访问,合并和缓存规则(因此具有相同的一般性能注意事项)。

由于动态分配需要一些非零时间,因此通过在程序开始时使用静态(即__device__)方法或通过一次分配,可以提高代码的性能。运行时API(即cudaMalloc等)这可以避免花时间在代码的性能敏感区域内动态分配内存。

另请注意,我概述的3种方法虽然具有与设备代码类似的类似C / C ++的访问方法,但它们与主机具有不同的访问方法。使用cudaMemcpyToSymbolcudaMemcpyFromSymbol等运行时API函数访问静态分配的内存,通过普通cudaMalloc / cudaMemcpy类型函数访问运行时API分配的内存,并动态分配全局内存(设备newmalloc)无法直接从主机访问。

答案 1 :(得分:1)

首先,您需要考虑合并内存访问。你没有提到你正在使用的GPU。在最新的GPU中,采煤存储器读取将提供与恒定存储器相同的性能。因此,请尽可能以煤炭方式读取和写入您的记忆。

另一个你可以使用纹理内存(如果数据大小适合它)。这种纹理内存有一些缓存机制。以前用于全局内存读取未合并的情况。但最新的GPU在纹理和全局内存方面具有几乎相同的性能。

我不认为全局声明的内存比动态分配的全局内存提供更多性能,因为合并问题仍然存在。在CUDA全局内存的情况下,在全局(可变)范围内声明的全局内存也是不可能的。可以全局声明的变量(在程序中)是常量内存变量和纹理,我们不需要将它作为参数传递给内核。

有关内存优化的信息,请参阅cuda c最佳做法指南http://docs.nvidia.com/cuda/cuda-c-best-practices-guide/#memory-optimizations

中的内存优化部分