从恒定内存中均匀加载128位数据

时间:2012-07-24 01:23:29

标签: types vector cuda structure gpgpu

给定CUDA向量类型int4,如何从常量内存中加载128位数据。

这似乎不起作用:

#include <stdio.h>
#include <cuda.h>

__constant__ int constant_mem[4];
__global__ void kernel(){
    int4 vec;
    vec = constant_mem[0];
}
int main(void){return 0;}

在第七行,我试图将常量存储器中的所有4个整数值加载到128位向量类型中。此操作导致以下编译错误:

vectest.cu(7): error: no operator "=" matches these operands
            operand types are: int4 = int

此外,是否可以直接访问矢量类型而无需投射它,如下所示:

int data = vec[0];

PTX程序集中的切换语句:

    @%p1 bra    BB1_55;

    setp.eq.s32     %p26, %r1, 1;
    @%p26 bra   BB1_54;

    setp.eq.s32     %p27, %r1, 2;
    @%p27 bra   BB1_53;

    setp.ne.s32     %p28, %r1, 3;
    @%p28 bra   BB1_55;

    mov.u32     %r961, %r61;
    bra.uni     BB1_56;

BB1_53:
    mov.u32     %r961, %r60;
    bra.uni     BB1_56;

BB1_54:
    mov.u32     %r961, %r59;
    bra.uni     BB1_56;

BB1_55:
    mov.u32     %r961, %r58;

BB1_56:

1 个答案:

答案 0 :(得分:1)

在第一种情况下,施法可能是最简单的解决方案,所以像这样:

__constant__ int constant_mem[4];
__global__ void kernel(){
    int4 vec = * reinterpret_cast<int4 *>(&constant_mem);
}

(免责声明用浏览器编写,未编译或测试,使用风险自负)

使用C ++ reinterpret_cast运算符将强制编译器发出128位加载指令。

在第二种情况下,听起来你想使用128位内存事务直接寻址存储在128位向量类型数组中的32位字。这需要一些辅助函数,可能类似于:

__inline__ __device__ int fetch4(const int4 val, const int n)
{
     (void) val.x; (void) val.y; (void) val.z; (void) val.w;
     switch(n) {
         case 3:
            return val.w;
         case 2: 
            return val.z;
         case 1:
            return val.y;
         case 0:
         default:
            return val.x;
    }
}

__device__ int index4(const int4 * array, const int n)
{
    int div = n / 4;
    int mod = n - (div * 4);

    int4 val = array[div]; // 128 bit load here

    return fetch4(val, mod);
}

__constant__ int constant_mem[128];
__global__ void kernel(){
    int val = index4(constant_mem, threadIdx.x);
}

(免责声明用浏览器编写,未编译或测试,使用风险自负)

这里我们通过读取整个int4值并解析它们的内容来强制执行128位事务(转换为void是open64编译器的旧版本所必需的咒语,如果它认为成员的话,它很容易优化矢量加载没用了)。有一些IOP的开销来进行索引,但如果生成的事务的负载带宽更高,它们可能是值得的。 switch语句可能是使用条件执行编译的,因此不应该存在分支差异惩罚。请注意,对int4值数组的随机访问可能会浪费大量带宽并导致warp序列化。这样做可能会对性能产生很大的负面影响。