Cuda 使用make_int3与直接赋值
我需要在cuda内核中为int3(比如p)类型的变量赋值。该赋值在内核中执行约10次Cuda 使用make_int3与直接赋值,cuda,parallel-processing,Cuda,Parallel Processing,我需要在cuda内核中为int3(比如p)类型的变量赋值。该赋值在内核中执行约10次 int3 p; p = make_int3(a,b,c); int3 p; p.x = a; p.y = b; p.z = c; 以上哪种方法更好,或者两者在速度方面效果相同 我在某个地方读到(不记得源代码)make_int3是一种构造函数,因此直接初始化值会更好吗?您可以使用以下代码和nvvp对差异进行基准测试 #include "cuda_runtime.h" __global__ void assi
int3 p;
p = make_int3(a,b,c);
int3 p;
p.x = a; p.y = b; p.z = c;
以上哪种方法更好,或者两者在速度方面效果相同
我在某个地方读到(不记得源代码)make_int3是一种构造函数,因此直接初始化值会更好吗?您可以使用以下代码和nvvp对差异进行基准测试
#include "cuda_runtime.h"
__global__
void assign_int3(int3* ptr)
{
int offset = threadIdx.x+blockIdx.x*blockDim.x;
int3 value = {0};
for(int i=0;i<10;i++)
{
value = make_int3(i, i*2, i*3);
}
ptr[offset] = value;
}
__global__
void assign_values(int3* ptr)
{
int offset = threadIdx.x+blockIdx.x*blockDim.x;
int3 value = {0};
for(int i=0;i<10;i++)
{
value.x=i;
value.y=i*2;
value.z=i*3;
}
ptr[offset]=value;
}
int main()
{
int3* ptr;
cudaMalloc(&ptr, 64*1024*sizeof(int3));
assign_int3<<<1024, 64>>>(ptr);
assign_values<<<1024, 64>>>(ptr);
cudaDeviceSynchronize();
cudaFree(ptr);
}
#包括“cuda_runtime.h”
__全球的__
无效分配\u int3(int3*ptr)
{
int offset=threadIdx.x+blockIdx.x*blockDim.x;
int3值={0};
对于(inti=0;iIt)来说,这绝对没有区别。这里显示的(后来添加的)PTX比较非常有指导意义,但是“基准测试”这完全是胡说八道,PTX清楚地说明了原因。微基准测试需要非常仔细地构造代码,以确保测量的时间实际上与分析的内容相关。这两个内核在这方面完全失败。我将尝试解释我的理由来证明源代码的合理性:通过基准测试,我回答了问题n:“两者在速度方面是否具有相同的效果?”,询问者的迭代次数相同(大约10次),他可以很容易地复制和运行一个代码示例。你能解释一下为什么执行时间的增量不应该显示make_int3(x,y,z)之间的差异吗和value.x=x;value.y=y;value.z=z?编译器已经优化了您的所有内核代码(循环,您在本答案的第一个版本中提到的原始“寄存器操作”)并用9,8,27的全局内存存储代替它们。在计算写操作索引时,PTX代码中的总指令数和延迟比其他任何东西都多。它不是任何东西的代表性基准。而在最近的CUDA版本中,惰性上下文建立的工作方式,我猜assign_int3
call将拥有相当多的启动开销,并且即使使用相同的PTX,配置文件也会变慢。
.visible .entry _Z11assign_int3P4int3(
.param .u64 _Z11assign_int3P4int3_param_0
)
{
.reg .s32 %r<8>;
.reg .s64 %rd<5>;
ld.param.u64 %rd1, [_Z11assign_int3P4int3_param_0];
cvta.to.global.u64 %rd2, %rd1;
mov.u32 %r1, %tid.x;
mov.u32 %r2, %ctaid.x;
mov.u32 %r3, %ntid.x;
mad.lo.s32 %r4, %r3, %r2, %r1;
mul.wide.s32 %rd3, %r4, 12;
add.s64 %rd4, %rd2, %rd3;
mov.u32 %r5, 27;
st.global.u32 [%rd4+8], %r5;
mov.u32 %r6, 18;
st.global.u32 [%rd4+4], %r6;
mov.u32 %r7, 9;
st.global.u32 [%rd4], %r7;
ret;
}
.visible .entry _Z13assign_valuesP4int3(
.param .u64 _Z13assign_valuesP4int3_param_0
)
{
.reg .s32 %r<8>;
.reg .s64 %rd<5>;
ld.param.u64 %rd1, [_Z13assign_valuesP4int3_param_0];
cvta.to.global.u64 %rd2, %rd1;
mov.u32 %r1, %tid.x;
mov.u32 %r2, %ctaid.x;
mov.u32 %r3, %ntid.x;
mad.lo.s32 %r4, %r3, %r2, %r1;
mul.wide.s32 %rd3, %r4, 12;
add.s64 %rd4, %rd2, %rd3;
mov.u32 %r5, 27;
st.global.u32 [%rd4+8], %r5;
mov.u32 %r6, 18;
st.global.u32 [%rd4+4], %r6;
mov.u32 %r7, 9;
st.global.u32 [%rd4], %r7;
ret;
}