C++ 和 CUDA 名称修饰不一致

问题描述 投票:0回答:1

我尝试从源代码编译 PyTorch,但遇到了一个非常奇怪的链接错误。经过调查,我发现 C++ 文件中定义的模板化函数及其在 CUDA 文件中的声明会生成两个不同的损坏名称。

  1. C++ 定义:_ZNK2at10TensorBase14const_data_ptrIdTnNSt9enable_ifIXntsr3stdE10is_const_vIT_EEiE4typeELi0EEEPKS3_v

  2. CUDA 声明:_ZNK2at10TensorBase14const_data_ptrIdTnNSt9enable_ifIXntsr4__T0E10is_const_vIT_EEiE4typeELi0EEEPKS3_v

除了粗体部分之外,这两个名称看起来几乎相同。 当我使用

llvm-cxxfilt
时,2 个损坏的名称返回相同的函数名称
double const* at::TensorBase::const_data_ptr<double, 0>() const

工具版本:

  • clang:Ubuntu clang 版本 18.1.8
  • NVCC:Cuda编译工具,版本12.6,V12.6.85
  • NVCC 的主机编译器:clang 18.1.8 如上

您能帮我解释一下吗:

  1. 损坏的名称中的粗体部分是什么?我在分解后的名字中没有看到它们。
  2. 为什么 2 个不同的损坏符号会产生相同的损坏名称?
c++ cuda linker-errors
1个回答
0
投票

这里有一个重组提示:在重组名称中,字符串前面已指示了长度。在本例中,不同的部分是“3”后跟 3 个字母与“4”后跟 4 个字母,所以这应该是我们的情况。

接下来,替换什么样的字符串?我们有“std”和“__T0”,所以合理的猜测是带有“E10”的命名空间,表示

::
。区别在于,一个编译器使用
std::is_const_v
,而另一个编译器使用
__T0::is_const_v
。事实上,在一个最小的例子中,你的函数

namespace at {
    class TensorBase {
public:
        template <typename T, typename std::enable_if<!std::is_const_v<T>, int>::type = 0>
        const T * const_data_ptr() const { return nullptr; }
    };
}

int main() {
    at::TensorBase tensorBase;
    tensorBase.const_data_ptr<double>();
}

模板成员函数与您的 C++ 符号完全对应。将

std::is_const_v
替换为
__T0::is_const_v
would 会得到您的 Cuda 符号,最终得到此符号的自然方法是在其自己的命名空间中重新定义
std::
部分的标头,但这可能不是正在发生的情况,而且是更深层的情况需要调查 nvcc 才能弄清楚。我在 Cuda 上下文中发现的对
__T0
的唯一引用与此无关,但总是涉及一些编译器细节 - 由 nvcc 注入的额外模板参数或设备/主机属性。

请注意,在损坏的名称中包含模板评估的整个处理是相当新的,因此当考虑到 nvcc 时,可能并非所有内容都始终正常工作。例如,使用 Cuda/NVCC 12.2.140、Clang 18.1.8,我无法重现您的问题,上面的代码使用 nvcc 和 clang 编译成您的 C++ 符号。一定还有更多特定于 nvcc 的东西导致了这种差异,您也可以在 NVCC 和/或 Clang 提交错误报告,因为我认为没有充分的理由。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.