内核中定义的Float4变量应存储在寄存器中!我做了一个简单的测试。在第一个内核中,我使用寄存器来优化内存流量,第二个内核直接从全局内存中读取。
__global__ void kernel(float4 *arg1, float4 *arg2, float4 *arg3)
{
int x = blockIdx.x * blockDim.x + threadIdx.x;
float4 temp1 = arg2[x];
float4 temp2 = arg3[x];
//some computations using temp1 and temp2
arg2[x] = temp1;
arg3[x] = temp2;
arg1[x] = make_float4(temp1.x, temp1.y, temp1.z, temp1.w);
}
__global__ void kernel(float4 *arg1, float4 *arg2, float4 *arg3)
{
int x = blockIdx.x * blockDim.x + threadIdx.x;
//some computations using a direct access to global memory
//for example arg2[x].x
arg1[x] = make_float4(arg2[x].x, arg2[x].y, arg2[x].z, arg2[x].w);
}
第一个内核的速度提高了9-10%。差别不大。使用寄存器时可以带来更多好处吗?
答案 0 :(得分:2)
首先,你不能说仅仅基于C代码的寄存器是什么,不会是什么。这肯定不是两个代码之间性能差异的来源。事实上,两个内核都使用寄存器来处理float4变量,它们编译的代码几乎相同。
第一个内核:
ld.param.u64 %rd3, [__cudaparm__Z7kernel0P6float4S0_S0__arg2];
add.u64 %rd4, %rd3, %rd2;
ld.global.v4.f32 {%f1,%f2,%f3,%f4}, [%rd4+0];
.loc 16 21 0
ld.param.u64 %rd5, [__cudaparm__Z7kernel0P6float4S0_S0__arg3];
add.u64 %rd6, %rd5, %rd2;
ld.global.v4.f32 {%f5,%f6,%f7,%f8}, [%rd6+0];
st.global.v4.f32 [%rd4+0], {%f1,%f2,%f3,%f4};
st.global.v4.f32 [%rd6+0], {%f5,%f6,%f7,%f8};
.loc 16 24 0
ld.param.u64 %rd7, [__cudaparm__Z7kernel0P6float4S0_S0__arg1];
add.u64 %rd8, %rd7, %rd2;
st.global.v4.f32 [%rd8+0], {%f1,%f2,%f3,%f4};
第二个内核:
ld.param.u64 %rd3, [__cudaparm__Z7kernel1P6float4S0_S0__arg2];
add.u64 %rd4, %rd3, %rd2;
ld.global.v4.f32 {%f1,%f2,%f3,%f4}, [%rd4+0];
ld.param.u64 %rd5, [__cudaparm__Z7kernel1P6float4S0_S0__arg1];
add.u64 %rd6, %rd5, %rd2;
st.global.v4.f32 [%rd6+0], {%f1,%f2,%f3,%f4};
如果它们之间确实存在性能差异,那么第一个内核可能比第二个内核具有更多的指令级并行机会。但这只是一个疯狂的猜测,不知道更多关于如何完成两者的基准测试。