Cuda 使用make_int3与直接赋值

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

我需要在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 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;
}