如何重载内置的 CUDA 函数?

How to overload a built-in CUDA function?

CUDA 有一些内置的数学函数,例如 norm()。我想创建我自己的 norm() 函数版本,并在整个代码中使用我的版本。但是,当我像这样定义自己的 norm() 函数时:

__device__ float norm(float a, float b) {
    return sqrt(a*a+b*b);
}

我得到以下编译错误:

kernel.cu(9): error: more than one instance of overloaded function "norm" has "C" linkage

有什么方法可以重载 norm() 函数,还是我必须为自己的函数指定一个唯一的名称?

我正在使用 PyCuda 编译我的 CUDA 代码。

除了 之外,我还会提出两个建议 - 如果您确实设法让重载工作:

  1. 非 CUDA 特定的一般建议:避免重载库的内置函数/API 函数,除非那是绝对必要的(这它不是你的情况)。
    这样做的原因:

    • 可能会使代码的其他读者感到困惑
    • 将 "wrapper" 代码与内置代码混合 - 这不是 "clean" 编码方式。
    • 如果内置函数发生变化,您使用内置函数+重载的代码可能也必须更改,有时会以您没有预料到的方式进行更改。
  2. 对于你的情况,我会认真考虑为你的实用函数设置一些命名空间,例如

    namespace math {
        template <typename T>  
        __device__ T norm(T a, T b) { return math::sqrt<T>(a*a+b*b); }
    }
    

    (当然你需要一个math::sqrt模板,它会从单精度sqrtf()、双精度sqrt()等中抽象出来)

这里的问题是在您的代码中使用了 C 链接。

您可能会也可能不会在任何地方明确指定 extern "C"。无论您是否使用 PyCUDA SourceModule 工具来编译您的代码,它都会(无)帮助地自动将您提交的代码用 extern "C".

括起来

如果您查看 documentation for SourceModule, you will see the option no_extern_c. Set that to True and this problem will go away. But note that everything you compile will now be compiled with C++ linkage and symbol mangling. You will have to adapt your Python code accordingly (see here 了解一些血淋淋的细节)。

然后,阅读另一个答案,其中包含一些关于重载标准库的危险的非常明智的建议和最佳实践替代方案。