优化点积

时间:2018-03-12 12:44:41

标签: cuda ptx

我正在开发一个内核函数,它具有几个矢量运算,如标量和矢量积。内核使用大量寄存器,因此占用率非常低。我正在尝试减少使用的寄存器数量,以提高占用率。

例如,考虑以下__device__函数在两个float3之间执行标量积:

__device__ float dot(float3 in1, float3 in2) { return in1.x * in2.x + in1.y * in2.y + in1.z * in2.z; }

如果我使用

生成.ptx文件
nvcc -ptx -gencode arch=compute_52,code=sm_52 -rdc=true simpleDot2.cu

(文件simpleDot2.cu仅包含__device__函数的定义),我基本上获得了

    // .globl   _Z3dot6float3S_
.visible .func  (.param .b32 func_retval0) _Z3dot6float3S_(
    .param .align 4 .b8 _Z3dot6float3S__param_0[12],
    .param .align 4 .b8 _Z3dot6float3S__param_1[12]
)
{
    .reg .f32   %f<10>;


    ld.param.f32    %f1, [_Z3dot6float3S__param_0+8];
    ld.param.f32    %f2, [_Z3dot6float3S__param_0];
    ld.param.f32    %f3, [_Z3dot6float3S__param_0+4];
    ld.param.f32    %f4, [_Z3dot6float3S__param_1+8];
    ld.param.f32    %f5, [_Z3dot6float3S__param_1];
    ld.param.f32    %f6, [_Z3dot6float3S__param_1+4];
    mul.f32     %f7, %f3, %f6;
    fma.rn.f32  %f8, %f2, %f5, %f7;
    fma.rn.f32  %f9, %f1, %f4, %f8;
    st.param.f32    [func_retval0+0], %f9;
    ret;
}

.ptx代码中,似乎使用了许多9个寄存器,可能会降低这些寄存器。我知道.ptx代码不是GPU执行的最终代码。

问题

是否有机会重新安排.ptx代码中的寄存器使用情况,例如回收寄存器f1 - f6,以减少占用寄存器的总数?

非常感谢您的帮助。

1 个答案:

答案 0 :(得分:2)

TL; DR 要先订购,否。

PTX既是虚拟ISA又是编译器中间表示。 PTX代码中使用的寄存器是虚拟寄存器,并且与GPU的物理寄存器没有固定的关系。 CUDA工具链生成的PTX代码遵循SSA(静态单一赋值)约定。这意味着每个虚拟寄存器只写入一次。换句话说:当指令产生结果时,它被分配给新的寄存器。这意味着更长的内核可能会使用数千个寄存器。

在CUDA工具链中,ptxas组件将PTX代码编译到机器代码(SASS)。因此,尽管有名称,但这不是汇编程序,而是优化编译器,它可以执行循环展开,CSE(公共子表达式消除)等等。最重要的是,ptxas负责寄存器分配和指令调度,以及特定于GPU架构的所有优化。

因此,对寄存器使用问题的任何检查都需要关注机器代码,可以使用cuobjdump --dump-sass提取。此外,程序员对所使用的寄存器数量的影响非常有限,因为ptxas在确定寄存器分配时使用了许多启发式算法,特别是在寄存器使用与性能之间进行权衡:早期调度负载往往会增加寄存器压力。寿命范围,在CSE期间创建临时变量或创建感应变量以减少循环中的强度。

目标计算能力为3.0或更高的CUDA现代版通常在确定这些权衡时做出了很好的选择,程序员很少需要考虑注册压力。目前尚不清楚提问者在这方面的问题是什么。

CUDA中用于控制最大寄存器使用的文档化机制是-maxrregcount nvcc命令行标志,它适用于整个编译单元,以及允许控制的__launch_bounds__属性在每个内核的基础上。有关详细信息,请参阅CUDA文档。除此之外,通过选择pxtas优化级别-Xptxas -O{1|2|3}(默认为-O3)或重新安排源代码,可以尝试来影响注册用量,或使用倾向于简化生成代码的编译器标志,例如-use_fast_math

当然,这种间接方法可能具有许多通常不可预测的其他效果,并且所实现的任何期望的结果将是“脆弱的”,例如,通过更改为新版本的工具链轻松销毁。