cuda:设备函数内联和不同的.cu文件

时间:2013-06-13 18:14:45

标签: cuda gpu inline nvidia ptx

两个事实:CUDA 5.0允许您在不同的对象文件中编译CUDA代码,以便稍后进行链接。 CUDA架构2.x不再自动内联函数。

像在C / C ++中一样,我在__device__ int foo()中实现了一个函数functions.cu,并将其标题放在functions.hu中。函数foo在其他CUDA源文件中调用。

当我检查functions.ptx时,我看到foo()溢出到本地内存。出于测试目的,我对foo()的所有内容进行了评论,并将其return 1;根据.ptx仍然溢出到本地内存中。 (我无法想象它是什么,因为函数什么都不做!)

但是,当我将foo()的实现移动到头文件functions.hu并添加__forceinline__限定符时,则没有任何内容写入本地内存!

这里发生了什么?为什么CUDA不会自动内联这么简单的功能?

单独标题&的整点。实现文件是为了让我的生活更轻松地维护代码。但是如果我必须在标题和__forceinline__中添加一堆函数(或者所有函数),那么它会破坏CUDA 5.0的不同编译单元的目的......

有什么方法吗?


简单,真实的例子:

functions.cu:

__device__  int  foo
        (const uchar param0,
        const uchar *const param1,
        const unsigned short int param2,
        const unsigned short int param3,
        const uchar param4) 
{    
    return 1; //real code commented out.
} 

上述功能溢出到本地内存。

functions.ptx:

.visible .func  (.param .b32 func_retval0) _Z45fooPKhth(
        .param .b32 _Z45foohPKhth_param_0,
        .param .b64 _Z45foohPKhth_param_1,
        .param .b32 _Z45foohPKhth_param_2,
        .param .b32 _Z45foohPKhth_param_3
)
{
        .local .align 8 .b8     __local_depot72[24];
        .reg .b64       %SP;
        .reg .b64       %SPL;
        .reg .s16       %rc<3>;
        .reg .s16       %rs<4>;
        .reg .s32       %r<2>;
        .reg .s64       %rd<2>;

1 个答案:

答案 0 :(得分:4)

并非所有本地内存使用都代表溢出。被调用的函数需要遵循ABI调用约定,包括创建位于本地内存中的堆栈帧。当nvcc传递命令行开关-Xptxas -v时,编译器会报告堆栈使用情况并将其作为子组件溢出。

目前(CUDA 5.0),CUDA工具链不支持跨编译单元边界的函数内联,就像一些主机编译器那样。因此,在单独编译的灵活性(例如重新编译大型项目的一小部分,编译时间较长,创建设备端库的可能性)和通常由函数产生的性能增益之间存在权衡内联(例如,消除由于ABI调用约定导致的开销,实现额外的优化,例如跨函数边界的不断增长)。

单个编译单元中的函数内联由编译器启发式控制,该编译器启发式试图确定内联是否可能在性能方面有利可图(如果可能的话)。这意味着并非所有函数都可以内联。程序员可以使用函数属性__forcinline____noinline__覆盖启发式。