CUDA中的内联常量数组访问

时间:2013-11-25 05:14:30

标签: 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;
}

这样它就不需要内存访问了吗?出于可读性的原因,我不想手动执行此操作。我需要它作为一个数组,因为有时候我会循环它。

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偏移量。

因此,我认为我可以得出结论,编译器驱动程序通常不会按照您希望的方式优化代码。