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 ;