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

What are the lifetimes for CUDA constant memory?

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

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

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

  3. 常量内存驻留在芯片的什么位置?

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

这六个问题倒序回答可能是最简单的:

Where does constant memory reside on the chip?

没有。常量内存存储在片外静态保留的物理内存中,并通过每个 SM 缓存访问。当编译器可以识别变量存储在 logical 常量内存 space 中时,它将发出特定的 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)?

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

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

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

When is constant memory actually loaded, or unloaded?

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

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

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

Why can't we allocate __constant__ memory at runtime?

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