cmo*_*cmo 6 optimization assembly cuda gpu ptx
考虑这3个简单的最小内核.他们的注册用量远高于我的预期.为什么?
A:
__global__ void Kernel_A()
{
//empty
}
Run Code Online (Sandbox Code Playgroud)
对应的ptx:
ptxas info : Compiling entry function '_Z8Kernel_Av' for 'sm_20'
ptxas info : Function properties for _Z8Kernel_Av
0 bytes stack frame, 0 bytes spill stores, 0 bytes spill loads
ptxas info : Used 2 registers, 32 bytes cmem[0]
Run Code Online (Sandbox Code Playgroud)
B:
template<uchar effective_bank_width>
__global__ void Kernel_B()
{
//empty
}
template
__global__ void Kernel_B<1>();
Run Code Online (Sandbox Code Playgroud)
对应的ptx:
ptxas info : Compiling entry function '_Z8Kernel_BILh1EEvv' for 'sm_20'
ptxas info : Function properties for _Z8Kernel_BILh1EEvv
0 bytes stack frame, 0 bytes spill stores, 0 bytes spill loads
ptxas info : Used 2 registers, 32 bytes cmem[0]
Run Code Online (Sandbox Code Playgroud)
C:
template<uchar my_val>
__global__ void Kernel_C
(uchar *const device_prt_in,
uchar *const device_prt_out)
{
//empty
}
Run Code Online (Sandbox Code Playgroud)
对应的ptx:
ptxas info : Compiling entry function '_Z35 Kernel_CILh1EEvPhS0_' for 'sm_20'
ptxas info : Function properties for _Z35 Kernel_CILh1EEvPhS0_
16 bytes stack frame, 0 bytes spill stores, 0 bytes spill loads
ptxas info : Used 10 registers, 48 bytes cmem[0]
Run Code Online (Sandbox Code Playgroud)
题:
为什么空内核A和B使用2个寄存器?CUDA总是使用一个隐式寄存器,但为什么还要使用2个额外的显式寄存器?
内核C更令人沮丧.10个寄存器?但只有2个指针.这为指针提供了2*2 = 4个寄存器.即使还有2个神秘的寄存器(由内核A和内核B建议),这将总共给出6个. 仍远小于10!
如果您感兴趣,这里是ptx内核A的ptx代码.内核B 的代码完全相同,以整数值和变量名为模.
.visible .entry _Z8Kernel_Av(
)
{
.loc 5 19 1
func_begin0:
.loc 5 19 0
.loc 5 19 1
func_exec_begin0:
.loc 5 22 2
ret;
tmp0:
func_end0:
}
Run Code Online (Sandbox Code Playgroud)
而对于内核C ......
.weak .entry _Z35Kernel_CILh1EEvPhS0_(
.param .u64 _Z35Kernel_CILh1EEvPhS0__param_0,
.param .u64 _Z35Kernel_CILh1EEvPhS0__param_1
)
{
.local .align 8 .b8 __local_depot2[16];
.reg .b64 %SP;
.reg .b64 %SPL;
.reg .s64 %rd<3>;
.loc 5 38 1
func_begin2:
.loc 5 38 0
.loc 5 38 1
mov.u64 %SPL, __local_depot2;
cvta.local.u64 %SP, %SPL;
ld.param.u64 %rd1, [_Z35Kernel_CILh1EEvPhS0__param_0];
ld.param.u64 %rd2, [_Z35Kernel_CILh1EEvPhS0__param_1];
st.u64 [%SP+0], %rd1;
st.u64 [%SP+8], %rd2;
func_exec_begin2:
.loc 5 836 2
tmp2:
ret;
tmp3:
func_end2:
}
Run Code Online (Sandbox Code Playgroud)
.local)?.reg .b64 行.但是这.reg .s64条线是什么?为什么会这样?它变得更糟:
d:
template<uchar my_val>
__global__ void Kernel_D
(uchar * device_prt_in,
uchar *const device_prt_out)
{
device_prt_in = device_prt_in + blockIdx.x*blockDim.x + threadIdx.x;
}
Run Code Online (Sandbox Code Playgroud)
给
ptxas info : Used 6 registers, 48 bytes cmem[0]
Run Code Online (Sandbox Code Playgroud)
因此,操纵参数(指针)会从10个寄存器减少到6个寄存器?
要说的第一点是,如果您担心寄存器,请不要查看PTX代码,因为它不会告诉您任何信息.PTX使用静态单一赋值形式,编译器发出的代码不包括制作可运行机器代码入口点所需的任何"装饰".
有了这个,让我们看看内核A:
$ nvcc -arch=sm_20 -m64 -cubin -Xptxas=-v null.cu
ptxas info : 0 bytes gmem
ptxas info : Compiling entry function '_Z8Kernel_Av' for 'sm_20'
ptxas info : Function properties for _Z8Kernel_Av
0 bytes stack frame, 0 bytes spill stores, 0 bytes spill loads
ptxas info : Used 2 registers, 32 bytes cmem[0]
$ cuobjdump -sass null.cubin
code for sm_20
Function : _Z8Kernel_Av
/*0000*/ /*0x00005de428004404*/ MOV R1, c [0x1] [0x100];
/*0008*/ /*0x00001de780000000*/ EXIT;
.............................
Run Code Online (Sandbox Code Playgroud)
有两个寄存器.空内核不会产生零指令.
除此之外,我无法再现你所展示的内容.如果我把你的内核C看作发布,我会得到这个(CUDA 5发布编译器):
$ nvcc -arch=sm_20 -m64 -cubin -Xptxas=-v null.cu
ptxas info : 0 bytes gmem
ptxas info : Compiling entry function '_Z8Kernel_CILh1EEvPhS0_' for 'sm_20'
ptxas info : Function properties for _Z8Kernel_CILh1EEvPhS0_
0 bytes stack frame, 0 bytes spill stores, 0 bytes spill loads
ptxas info : Used 2 registers, 48 bytes cmem[0]
$ cuobjdump -sass null.cubin
code for sm_20
Function : _Z8Kernel_CILh1EEvPhS0_
/*0000*/ /*0x00005de428004404*/ MOV R1, c [0x1] [0x100];
/*0008*/ /*0x00001de780000000*/ EXIT;
........................................
Run Code Online (Sandbox Code Playgroud)
即.相同的2个寄存器代码到前两个内核.
和内核D相同:
$ nvcc -arch=sm_20 -m64 -cubin -Xptxas=-v null.cu
ptxas info : 0 bytes gmem
ptxas info : Compiling entry function '_Z8Kernel_DILh1EEvPhS0_' for 'sm_20'
ptxas info : Function properties for _Z8Kernel_DILh1EEvPhS0_
0 bytes stack frame, 0 bytes spill stores, 0 bytes spill loads
ptxas info : Used 2 registers, 48 bytes cmem[0]
$ cuobjdump -sass null.cubin
code for sm_20
Function : _Z8Kernel_DILh1EEvPhS0_
/*0000*/ /*0x00005de428004404*/ MOV R1, c [0x1] [0x100];
/*0008*/ /*0x00001de780000000*/ EXIT;
........................................
Run Code Online (Sandbox Code Playgroud)
再次,2个寄存器.
为了记录,我使用的nvcc版本是:
$ nvcc --version
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2012 NVIDIA Corporation
Built on Fri_Sep_28_16:10:16_PDT_2012
Cuda compilation tools, release 5.0, V0.2.1221
Run Code Online (Sandbox Code Playgroud)