cuda - CUDA 常量内存的生命周期是多少?

标签 cuda gpu-constant-memory

我无法理解 CUDA 常量内存的限制。

  1. 为什么我们不能在运行时分配__constant__ 内存?为什么我需要在具有接近全局范围的固定大小变量中进行编译?

  2. 什么时候实际加载或卸载常量内存?我知道 cudaMemcpytoSymbol 用于加载特定数组,但每个内核是否使用自己的常量内存分配?相关的,绑定(bind)和取消绑定(bind)是否有类似于绑定(bind)纹理的旧成本的成本(也就是,使用纹理会增加每次内核调用的成本)?

  3. 常量内存位于芯片的什么位置?

CUDA Architecture

我主要对与 Pascal 和 Volta 相关的答案感兴趣。

最佳答案

以相反的顺序回答这六个问题可能是最简单的:

Where does constant memory reside on the chip?

事实并非如此。常量内存存储在片外静态保留的物理内存中,并通过每个 SM 缓存访问。当编译器可以识别变量存储在逻辑常量内存空间时,它将发出特定的 PTX 指令,允许通过常量缓存访问该静态内存。另请注意,在所有当前支持的架构上都有特定的保留常量内存库用于存储内核参数。

Is there a cost to binding, and unbinding similar to the old cost of binding textures (aka, using textures added a cost to every kernel invocation)?

没有。但是也没有“绑定(bind)”或“解除绑定(bind)”,因为保留是静态执行的。唯一的运行时成本是主机到设备的内存传输以及作为上下文建立的一部分将符号加载到上下文中的成本。

I understand that cudaMemcpytoSymbol is used to load the particular array, but does each kernel use its own allocation of constant memory?

没有。整个 GPU 只有一个“分配”(尽管如上所述,内核参数有特定的常量内存组,所以在某种意义上你可以说每个内核都有一个常量内存组件)。

When is constant memory actually loaded, or unloaded?

这取决于您所说的“加载”和“卸载”的含义。加载实际上是一个两阶段过程——首先检索符号并将其加载到上下文中(如果您使用运行时 API,这是自动完成的),其次任何用户运行时操作通过 cudaMemcpytoSymbol 更改常量内存的内容

Why do I need to compile in a fixed size variable with near-global scope?

如前所述,常量内存基本上是 PTX 内存层次结构中的逻辑地址空间,它反射(reflect)在 GPU DRAM 映射的有限大小保留区域中,并且需要编译器发出特定指令以通过专用 on 统一访问芯片缓存或缓存。鉴于其静态的、编译器分析驱动的性质,它在语言中的实现也将主要是静态的是有道理的。

Why can't we allocate __constant__ memory at runtime?

主要是因为 NVIDIA 选择不公开它。但考虑到上面列出的所有限制,我认为这不是一个非常糟糕的选择。其中一些很可能是历史性的,因为常量内存从一开始就是 CUDA 设计的一部分。 CUDA 设计中几乎所有的原始特性和功能都映射到硬件特性,硬件特性的存在是为了硬件的首要目的,即 GPU 旨在支持的图形 API。因此,您所问的某些问题很可能与 OpenGL 或 Direct 3D 的历史特征或限制有关,但我对其中任何一个都不够熟悉,无法确定。

关于cuda - CUDA 常量内存的生命周期是多少?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45626354/

相关文章:

cuda常量内存引用

cuda - 本地、全局、常量和共享内存

c++ - 为什么时序会随着输入数据中零的数量而急剧变化?

c++ - CUDA 中的并行批处理小矩阵不适用于 for 循环

cmake - 我如何 "tell"CMake 3.9+ 我想使用 NVIDIA 的 OpenCL 库?

cuda - 分配常量内存

CUDA 代码中的常量内存使用

c++ - CUDA C++ 中的变量分配 - 无法分配设备变量

c++ - 从 CUDA 设备函数/内核中并行化一个方法