首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么CUDA函数cudaLaunchKernel传递一个指向主机代码函数的函数指针?

为什么CUDA函数cudaLaunchKernel传递一个指向主机代码函数的函数指针?
EN

Stack Overflow用户
提问于 2022-08-29 02:00:55
回答 1查看 84关注 0票数 1

我使用以下命令编译axpy.cu

nvcc --cuda axpy.cu -o axpy.cu.cpp.ii

axpy.cu.cpp.ii中,我观察到嵌套在__device_stub__Z4axpyfPfS_中的函数cudaLaunchKernel接受一个指向在axpy.cu.cpp.ii中定义的axpy的函数指针。所以我的困惑是,cudaLaunchKernel不应该被传递一个指向内核函数axpy的函数指针吗?为什么有与内核函数同名的函数定义?任何帮助都将不胜感激!提前感谢

这两个功能如下所示。

代码语言:javascript
运行
复制
void __device_stub__Z4axpyfPfS_(float __par0, float *__par1, float *__par2){
    void * __args_arr[3]; 
    int __args_idx = 0;
    __args_arr[__args_idx] = (void *)(char *)&__par0; 
    ++__args_idx;
    __args_arr[__args_idx] = (void *)(char *)&__par1; 
    ++__args_idx;
    __args_arr[__args_idx] = (void *)(char *)&__par2; 
    ++__args_idx;
    { 
        volatile static char *__f __attribute__((unused)); 
        __f = ((char *)((void ( *)(float, float *, float *))axpy)); 
        dim3 __gridDim, __blockDim; 
        size_t __sharedMem; 
        cudaStream_t __stream; 
        if (__cudaPopCallConfiguration(&__gridDim, &__blockDim, &__sharedMem, &__stream) != cudaSuccess) 
            return; 
        if (__args_idx == 0) { 
            (void)cudaLaunchKernel(((char *)((void ( *)(float, float *, float *))axpy)), __gridDim, __blockDim, &__args_arr[__args_idx], __sharedMem, __stream); 
        } else {
            (void)cudaLaunchKernel(((char *)((void ( *)(float, float *, float *))axpy)), __gridDim, __blockDim, &__args_arr[0], __sharedMem, __stream); 
        } 
    };
}       
代码语言:javascript
运行
复制
void axpy( float __cuda_0,float *__cuda_1,float *__cuda_2)
# 3 "axpy.cu"
{
   __device_stub__Z4axpyfPfS_( __cuda_0,__cuda_1,__cuda_2);

}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-08-30 02:24:25

所以我的困惑是,cudaLaunchKernel不应该被传递一个指向内核函数axpy的函数指针吗?

不,因为这不是NVIDIA选择的设计,你关于这个功能如何工作的假设可能是不正确的。据我所知,cudaLaunchKernel的第一个参数被视为键,而不是调用的函数指针。在nvcc发出的代码中,您会发现类似于这个样板的东西:

代码语言:javascript
运行
复制
static void __nv_cudaEntityRegisterCallback( void **__T0)
{  
    __nv_dummy_param_ref(__T0); 
    __nv_save_fatbinhandle_for_managed_rt(__T0); 
    __cudaRegisterEntry(__T0, ((void ( *)(float, float *, float *))axpy), _Z4axpyfPfS_, (-1)); 
}

您可以看到,__cudaRegisterEntry调用既采用了指向axpy的静态指针,也采用了编译后的GPU内核的损坏符号形式。__cudaRegisterEntry是来自CUDA运行时API的内部的、完全没有文档的API。许多年前,我通过逆向工程( CUDA运行时API的早期版本)确信,存在一个内部查找机制,它允许主机内核存根的正确实例在运行时与编译的GPU代码的正确实例相匹配。编译器发出大量样板和静态定义的对象,保存所有必要的定义,使运行时API无缝工作,而不需要在CUDA驱动程序API或类似的计算API (如OpenCL )中使用所有额外的API开销。

为什么有与内核函数同名的函数定义?

因为这就是NVIDIA决定实现运行时API的方式。您询问的是运行时API的无文档的内部实现细节。作为程序员,您不应该看到或使用它们,而且它们也不能保证在不同版本之间是相同的。

如果如注释所示,希望在CUDA编译过程中实现一些额外的编译器基础设施,请使用CUDA驱动程序API,而不是运行时API。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73523513

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档