Optimization CUDA中的内联常量数组访问
我有一些代码如下所示:Optimization CUDA中的内联常量数组访问,optimization,cuda,Optimization,Cuda,我有一些代码如下所示: enum { FIRST, SECOND, THIRD, FOURTH }; __constant__ int array[] = { 1, 4, 2, 3 }; // ... __device__ func() { foo[threadIdx.x] += array[FIRST]; } 编译器是否有办法自动将其转换为: __device__ func() { foo[threadIdx.x] += 1; } 这样就不需要内存访问了?出于可读性原因,我不想手
enum { FIRST, SECOND, THIRD, FOURTH };
__constant__ int array[] = { 1, 4, 2, 3 };
// ...
__device__ func() {
foo[threadIdx.x] += array[FIRST];
}
编译器是否有办法自动将其转换为:
__device__ func() {
foo[threadIdx.x] += 1;
}
这样就不需要内存访问了?出于可读性原因,我不想手动执行此操作。我需要它作为一个数组,因为有时我会在它上面循环。首先,我不会假装是
nvcc
编译器驱动程序的专家,我只是在间接观察的基础上提供这个答案
特别是,我做了以下测试:
#include<cuda.h>
enum { FIRST, SECOND, THIRD, FOURTH };
__constant__ int test_array[] = { 44, 4, 2, 3 };
__global__ void func(int* foo) {
foo[threadIdx.x] += test_array[FIRST];
}
int main () {
return 0;
}
请注意来自常量内存(LDC
)的负载
如果我将\uuuu global\uuuu
功能指令更改为
foo[threadIdx.x] += test_array[SECOND];
现在反汇编的代码看起来像
MOV R1, c[0x1][0x100];
NOP;
MOV32I R5, 0x4;
S2R R0, SR_TID.X;
IMAD.U32.U32 R4.CC, R0, R5, c[0x0][0x20];
MOV32I R2, 0x0;
IMAD.U32.U32.HI.X R5, R0, R5, c[0x0][0x24];
LDC R2, c[0x2][R2+0x4];
LD.E R0, [R4];
IADD R2, R0, R2;
ST.E [R4], R2;
EXIT ;
请注意,现在LDC
指令正通过带有0x4
偏移量的MOV32I
指令从R2
中存储的偏置地址加载
因此,我认为我可以得出结论,一般来说,编译器驱动程序没有按照您希望的方式优化代码。您可能会认为
\uuuuuu常量\uuuuuuu数组[]
引用类似于const
,但事实上\uuuuu常量\uuuuuuuuuu int数组[]
实际上可以通过cudaMemcpyToSymbol
调用在运行时运行,因此,我认为一般来说,编译器不会像您所建议的那样进行优化。您显示的代码不能保证array[FIRST]
在运行时等于1。const
和\uuuu constant\uuuu
的语义是“只读的”,而不是“不可修改的”。volatile const
对象的标准示例是由中断服务例程更新的时钟滴答计数器,该例程只应由应用程序代码读取,而不应由应用程序代码写入。const
实际上是用户代码“不可修改”的<代码>\uuuu常量\uuuuu由设备代码“不可修改”,但由主机代码“可修改”。然而,我与const的比较并不是特别好。为了在编译时进行优化,与编译器宏相比会更好。我明白了。但是如果我也将“const”添加到数组中,编译器会给我所需的优化吗?不会。将const
添加到数组
定义中不会阻止cudaMemcpyToSymbol
调用覆盖数组
中的值。
MOV R1, c[0x1][0x100];
NOP;
MOV32I R5, 0x4;
S2R R0, SR_TID.X;
IMAD.U32.U32 R4.CC, R0, R5, c[0x0][0x20];
MOV32I R2, 0x0;
IMAD.U32.U32.HI.X R5, R0, R5, c[0x0][0x24];
LDC R2, c[0x2][R2+0x4];
LD.E R0, [R4];
IADD R2, R0, R2;
ST.E [R4], R2;
EXIT ;