我有一些看起来像这样的代码:
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;
}
这样它就不需要内存访问了吗?出于可读性的原因,我不想手动执行此操作。我需要它作为一个数组,因为有时候我会循环它。
答案 0 :(得分:2)
首先,我不假装成为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;
}
我只是使用__global__
函数而不是__device__
函数,就像你的情况一样,我正在使用CUDA 5.5为sm=2.1
架构编译发布模式。反汇编的代码是
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; R2 = bias address of constant memory
IMAD.U32.U32.HI.X R5, R0, R5, c[0x0][0x24];
LDC R2, c[0x2][R2]; Load in R2 from the constant memory
LD.E R0, [R4];
IADD R2, R0, R2;
ST.E [R4], R2;
EXIT ;
注意来自常量内存(LDC
)的负载。
如果我将__global__
功能指令更改为
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
指令是从R2
指令存储在MOV32I
指令中的偏差地址加载0x4
偏移量。
因此,我认为我可以得出结论,编译器驱动程序通常不会按照您希望的方式优化代码。