我尝试制作简单的代码,将V1(向量)与V2相加并将值保存在V3中。这是CUDA中的工作方式,但是我不能用PTX编写,有人可以帮忙吗?
__global__ void addKernelPTXv4(float4 *cc, const float4 *aa, const float4 *bb)
{
int i = threadIdx.x;
cc[i].x = aa[i].x + bb[i].x;
cc[i].y = aa[i].y + bb[i].y;
cc[i].z = aa[i].z + bb[i].z;
cc[i].w = aa[i].w + bb[i].w;
}
__global__ void addKernelPTXv4(float4 *cc, const float4 *aa, const float4 *bb)
{
asm(
".reg.f32 a1, a2, a3, a4;"
".reg.f32 b1, b2, b3, b4;"
".reg.f32 c1, c2, c3, c4;"
".reg.r32 r1;"
".reg.s64 rd1, rd2, rd3;"
"mov.r32 r1, %tid.x;"
"mul.s32 r1, r1, 16;"
"add.s64 rd1, %0, r1;"
"add.s64 rd2, %1, r1;"
"add.s64 rd3, %2, r1;"
"ld.global.v4.f32 { a1, a2, a3, a4 }, [rd2];"
"ld.global.v4.f32 { b1, b2, b3, b4 }, [rd3];"
"add.f32 c1, a1, b2;"
"add.f32 c2, a2, b2;"
"add.f32 c3, a3, b3;"
"add.f32 c4, a4, b4;"
"st.global.v4.f32 [rd1], { c1, c2, c3, c4 };"
: "=l"(cc)
: "l"(aa), "l"(bb)
);
}
当我打印Vector CC时,运行PTX代码后,每个地方零。您能告诉我代码的原因和位置吗?
////////////// ADD
在Visual Studio 2015中编译我的ptx / asm代码后,我检查了PTX输出文件:
// .globl _Z14addKernelPTXv4P6float4PKS_S2_
.visible .entry _Z14addKernelPTXv4P6float4PKS_S2_(
.param .u64 _Z14addKernelPTXv4P6float4PKS_S2__param_0,
.param .u64 _Z14addKernelPTXv4P6float4PKS_S2__param_1,
.param .u64 _Z14addKernelPTXv4P6float4PKS_S2__param_2
)
{
.reg .b64 %rd<5>;
ret;
}
是...。空吗?那么问题出在哪里呢?
当我编译CUDA版本时,输出的PTX为:
// .globl _Z14addKernelPTXv4P6float4PKS_S2_
.visible .entry _Z14addKernelPTXv4P6float4PKS_S2_(
.param .u64 _Z14addKernelPTXv4P6float4PKS_S2__param_0,
.param .u64 _Z14addKernelPTXv4P6float4PKS_S2__param_1,
.param .u64 _Z14addKernelPTXv4P6float4PKS_S2__param_2
)
{
.reg .f32 %f<21>;
.reg .b32 %r<2>;
.reg .b64 %rd<11>;
ld.param.u64 %rd1, [_Z14addKernelPTXv4P6float4PKS_S2__param_0];
ld.param.u64 %rd2, [_Z14addKernelPTXv4P6float4PKS_S2__param_1];
ld.param.u64 %rd3, [_Z14addKernelPTXv4P6float4PKS_S2__param_2];
cvta.to.global.u64 %rd4, %rd1;
cvta.to.global.u64 %rd5, %rd3;
cvta.to.global.u64 %rd6, %rd2;
mov.u32 %r1, %tid.x;
mul.wide.s32 %rd7, %r1, 16;
add.s64 %rd8, %rd6, %rd7;
add.s64 %rd9, %rd5, %rd7;
add.s64 %rd10, %rd4, %rd7;
ld.global.v4.f32 {%f1, %f2, %f3, %f4}, [%rd8];
ld.global.v4.f32 {%f5, %f6, %f7, %f8}, [%rd9];
add.f32 %f11, %f4, %f8;
add.f32 %f14, %f3, %f7;
add.f32 %f17, %f2, %f6;
add.f32 %f20, %f1, %f5;
st.global.v4.f32 [%rd10], {%f20, %f17, %f14, %f11};
ret;
}
为什么VS2015清除我的代码?怎么了?
答案 0 :(得分:1)
她是解析代码:
__global__ void addKernelPTXv4(float4 *ccc, const float4 *aaa, const float4 *bbb)
{
asm volatile ("{ \n\t"
".reg.f32 aa<4>, bb<4>, cc<4>; \n\t"
".reg.s32 rr0; \n\t"
".reg.s64 rrd<4>; \n\t"
"mov.s32 rr0, %tid.x; \n\t"
"mul.wide.s32 rrd0, rr0, 16; \n\t"
"add.s64 rrd1, %0, rrd0; \n\t"
"add.s64 rrd2, %1, rrd0; \n\t"
"add.s64 rrd3, %2, rrd0; \n\t"
"ld.global.v4.f32 { aa0, aa1, aa2, aa3 }, [rrd2]; \n\t"
"ld.global.v4.f32 { bb0, bb1, bb2, bb3 }, [rrd3]; \n\t"
"add.f32 cc0, aa0, bb0; \n\t"
"add.f32 cc1, aa1, bb1; \n\t"
"add.f32 cc2, aa2, bb2; \n\t"
"add.f32 cc3, aa3, bb3; \n\t"
"st.global.v4.f32 [rrd1], { cc0, cc1, cc2, cc3 }; \n\t"
"} \n\t"
:
: "l"(ccc), "l"(aaa), "l"(bbb)
: "memory"
);
}
编译后:
// .globl _Z14addKernelPTXv4P6float4PKS_S2_
.visible .entry _Z14addKernelPTXv4P6float4PKS_S2_(
.param .u64 _Z14addKernelPTXv4P6float4PKS_S2__param_0,
.param .u64 _Z14addKernelPTXv4P6float4PKS_S2__param_1,
.param .u64 _Z14addKernelPTXv4P6float4PKS_S2__param_2
)
{
.reg .b64 %rd<4>;
ld.param.u64 %rd1, [_Z14addKernelPTXv4P6float4PKS_S2__param_0];
ld.param.u64 %rd2, [_Z14addKernelPTXv4P6float4PKS_S2__param_1];
ld.param.u64 %rd3, [_Z14addKernelPTXv4P6float4PKS_S2__param_2];
// inline asm
{
.reg.f32 aa<4>, bb<4>, cc<4>;
.reg.s32 rr0;
.reg.s64 rrd<4>;
mov.s32 rr0, %tid.x;
mul.wide.s32 rrd0, rr0, 16;
add.s64 rrd1, %rd1, rrd0;
add.s64 rrd2, %rd2, rrd0;
add.s64 rrd3, %rd3, rrd0;
ld.global.v4.f32 { aa0, aa1, aa2, aa3 }, [rrd2];
ld.global.v4.f32 { bb0, bb1, bb2, bb3 }, [rrd3];
add.f32 cc0, aa0, bb0;
add.f32 cc1, aa1, bb1;
add.f32 cc2, aa2, bb2;
add.f32 cc3, aa3, bb3;
st.global.v4.f32 [rrd1], { cc0, cc1, cc2, cc3 };
}
// inline asm
ret;
}
原始的CUDA代码:
__global__ void addKernelPTXv4(float4 *c, const float4 *a, const float4 *b)
{
int i = threadIdx.x;
c[i].x = a[i].x + b[i].x;
c[i].y = a[i].y + b[i].y;
c[i].z = a[i].z + b[i].z;
c[i].w = a[i].w + b[i].w;
}
编译后:
// .globl _Z14addKernelPTXv4P6float4PKS_S2_
.visible .entry _Z14addKernelPTXv4P6float4PKS_S2_(
.param .u64 _Z14addKernelPTXv4P6float4PKS_S2__param_0,
.param .u64 _Z14addKernelPTXv4P6float4PKS_S2__param_1,
.param .u64 _Z14addKernelPTXv4P6float4PKS_S2__param_2
)
{
.reg .f32 %f<21>;
.reg .b32 %r<2>;
.reg .b64 %rd<11>;
ld.param.u64 %rd1, [_Z14addKernelPTXv4P6float4PKS_S2__param_0];
ld.param.u64 %rd2, [_Z14addKernelPTXv4P6float4PKS_S2__param_1];
ld.param.u64 %rd3, [_Z14addKernelPTXv4P6float4PKS_S2__param_2];
cvta.to.global.u64 %rd4, %rd1;
cvta.to.global.u64 %rd5, %rd3;
cvta.to.global.u64 %rd6, %rd2;
mov.u32 %r1, %tid.x;
mul.wide.s32 %rd7, %r1, 16;
add.s64 %rd8, %rd6, %rd7;
add.s64 %rd9, %rd5, %rd7;
add.s64 %rd10, %rd4, %rd7;
ld.global.v4.f32 {%f1, %f2, %f3, %f4}, [%rd8];
ld.global.v4.f32 {%f5, %f6, %f7, %f8}, [%rd9];
add.f32 %f11, %f4, %f8;
add.f32 %f14, %f3, %f7;
add.f32 %f17, %f2, %f6;
add.f32 %f20, %f1, %f5;
st.global.v4.f32 [%rd10], {%f20, %f17, %f14, %f11};
ret;
}
因此,可以比CU.VS编译的VS.2015短一些PTX代码;-)