Architecture 体系结构中的NVPTX通用内存空间位置

Architecture 体系结构中的NVPTX通用内存空间位置,architecture,cuda,llvm,llvm-ir,ptx,Architecture,Cuda,Llvm,Llvm Ir,Ptx,在CUDA程序的NVPTX(LLVM IR)中,内存地址空间的标识符从0到5(见下表) 我在同一个LLVM IR程序中看到,内存地址被标识为“通用”或其他类型,如图所示 对于“Generic”(默认情况下,没有标识符): 对于“共享”: 我的问题是,对于通用内存地址空间,数据实际上位于硬件、片外、片内内存或本地寄存器中的什么位置?有人能解释一下通用类型的地址空间最终是如何管理的吗?答案很简单:通用地址空间没有硬件表示 您可以将通用地址空间(AS)视为逻辑AS,在逻辑AS中,其他AS组合在一

在CUDA程序的NVPTX(LLVM IR)中,内存地址空间的标识符从0到5(见下表)

我在同一个LLVM IR程序中看到,内存地址被标识为“通用”或其他类型,如图所示

对于“Generic”(默认情况下,没有标识符):

对于“共享”:


我的问题是,对于通用内存地址空间,数据实际上位于硬件、片外、片内内存或本地寄存器中的什么位置?有人能解释一下通用类型的地址空间最终是如何管理的吗?

答案很简单:通用地址空间没有硬件表示

您可以将通用地址空间(AS)视为逻辑AS,在逻辑AS中,其他AS组合在一起。 例如:下面的内核调用和接受指针的设备函数

__device__ void bar(int* x){
   *x = *x + 1;
}

__global__ void foo(int* x){
   __shared__ int y[1];
   bar(x); 
   bar(y);
}
可以向函数传递任何指针。从语言的角度来看,指针是位于AS 1(全局)还是AS 3(共享)并不重要。 在C++中(和CUDA C/C++),你不必显式指定。例如,在OpenCL<2.0中,您必须显式地为每个指针添加一个修饰符,并且必须提供一个函数
bar
,该函数将特定指针作为指针

LLVM IR中发生的情况是,传递到函数的指针通过
addresspacecast
指令转换到泛型AS。 在PTX
addresspacecast
中,由
cvta
指令表示:

// convert const, global, local, or shared address to generic address
cvta.space.size  p, a;        // source address in register a
cvta.space.size  p, var;      // get generic address of var
cvta.space.size  p, var+imm;  // generic address of var+offset

// convert generic address to const, global, local, or shared address
cvta.to.space.size  p, a;

.space = { .const, .global, .local, .shared };
.size  = { .u32, .u64 };
通用指针映射到全局内存,除非它位于为另一个AS保留的地址区域内。硬件从通用指针中减去AS的起始地址,以确定正确的内存区域

原子学就是一个很好的例子:

atom{.space}.op.type  d, [a], b;
atom{.space}.op.type  d, [a], b, c;

您可以指定地址空间或让硬件选择。如果您希望生成正确的原子指令而不产生指针减法开销,后端负责将指针转换回正确的地址空间。

因此,根据您的回答,您的意思是,如果指针位于LLVM IR中的AS1中,我们无法知道它将进入全局还是共享等内存,对吗?如果指针在AS1中,我们知道它在全局内存中。如果它在AS0中,那么只有硬件可以确定它。将AS0视为从1到5的浓度。