CUDA:巨大的性能影响调用成员函数

时间:2016-02-01 21:11:50

标签: c++ performance cuda member

当我正确理解Robert Crovella's SO answer时,GPU编译器应出于性能原因积极内联函数

我在这里有一个测试用例,它不会发生,甚至这个非常简单的函数也没有内联,编译器每次调用成员函数时都会生成:

__device__ auto foo::isMemberHighest( int iParameterBar ) -> bool
{
    return iParameterBar == 1;
}

运行-cubin参数并用nvdiasm反汇编我得到此输出:

//--------------------- .text._ZN27foo15isMemberHighestEi --------------------------
    .section    .text._ZN27foo15isMemberHighestEi,"ax",@progbits
    .sectioninfo    @"SHI_REGISTERS=7"
    .align  64
        .global         _ZN27foo15isMemberHighestEi
        .type           _ZN27foo15isMemberHighestEi,@function
        .size           _ZN27foo15isMemberHighestEi,(.L_969 - _ZN27foo15isMemberHighestEi)
_ZN27foo15isMemberHighestEi:
.text._ZN27foo15isMemberHighestEi:
        /*0000*/                   MOV R0, R6;
        /*0008*/                   MOV R5, R5;
        /*0010*/                   MOV R4, R4;
        /*0018*/                   MOV R4, R4;
        /*0020*/                   MOV R5, R5;
        /*0028*/                   MOV R4, R4;
        /*0030*/                   MOV R5, R5;
        /*0038*/                   MOV R0, R0;
        /*0040*/                   MOV R0, R0;
.L_605:
        /*0048*/                   ISUB R3.CC, R4, RZ;
        /*0050*/                   ISETP.NE.X.AND P0, PT, R5, RZ, PT;
        /*0058*/                   PSETP.AND.AND P0, PT, !P0, PT, PT;
        /*0060*/                   PSETP.AND.AND P0, PT, !P0, PT, PT;
        /*0068*/                   NOP;
        /*0070*/                   SSY `(.L_449);
        /*0078*/               @P0 BRA `(.L_450);
        /*0080*/                   BRA `(.L_450);
.L_450:
        /*0090*/                   NOP.S              (*"TARGET= .L_449 "*);
.L_449:
        /*0098*/                   ISETP.EQ.AND P0, PT, R0, 0x1, PT;
        /*00a0*/                   SEL R0, RZ, 0x1, !P0;
        /*00a8*/                   MOV R0, R0;
        /*00b0*/                   MOV R4, R0;
        /*00b8*/                   RET;
.L_606:
        /*00c0*/                   EXIT;
.L_604:
        /*00c8*/                   EXIT;
.L_451:
        /*00d0*/                   BRA `(.L_451);
.L_969:

/*0098*//*00a0*/之间有比较命令,然后是return

我的C ++代码有5个成员调用此函数,我在反汇编代码中看到了对此函数的5个调用:

JCAL `(_ZN27foo15isMemberHighestEi);

我现在遇到了这个问题:在开始时 - 当我有一个纯C代码时 - 我有一个非常好的性能[我用一个#define“内联”代码]。然后我通过评论和文档对C ++进行了调整 - 鼓励 - 使用类,现在我的代码是1'500!慢。

在需要大约73ms的18m迭代之前 - 现在560k迭代需要3'300ms!这意味着它慢了1,500倍,这自然是非常令人沮丧的。当然,这不是导致这种延迟的唯一一个成员函数。我有大约10个,每次迭代导致50 call个语句[包括函数开销],显然这是瓶颈。

我可以改进什么,或者是将代码“拆除”回可怕的C代码的唯一解决方案?

当我将成员代码放入类声明时,代码不会改变。这意味着,编译器已经“知道”了成员函数的代码。并且,如果我更改优化级别-O1 -O2 -O3,则代码根本不会更改!

更新

编写本声明:

/usr/local/cuda-7.5/bin/nvcc -cubin -O3 -Xcompiler -Wall -Xcompiler -Wextra
   -Xcompiler -Werror -std=c++11 --compile --relocatable-device-code=false
   -gencode arch=compute_30,code=sm_30  -x cu -o CudaCore.cubin "../cuda/CudaCore.cu"
&& nvdisasm CudaCore.cubin > CudaCore.cubin.asm

1 个答案:

答案 0 :(得分:2)

将评论总结为某种答案:

我还没有看到C ++比C慢的情况。 您的代码速度较慢,因为它在调试模式下显然编译。

我无法强调显然足够