我尝试从源代码编译 PyTorch,但遇到了一个非常奇怪的链接错误。经过调查,我发现 C++ 文件中定义的模板化函数及其在 CUDA 文件中的声明会生成两个不同的损坏名称。
C++ 定义:_ZNK2at10TensorBase14const_data_ptrIdTnNSt9enable_ifIXntsr3stdE10is_const_vIT_EEiE4typeELi0EEEPKS3_v
CUDA 声明:_ZNK2at10TensorBase14const_data_ptrIdTnNSt9enable_ifIXntsr4__T0E10is_const_vIT_EEiE4typeELi0EEEPKS3_v
除了粗体部分之外,这两个名称看起来几乎相同。 当我使用
llvm-cxxfilt
时,2 个损坏的名称返回相同的函数名称 double const* at::TensorBase::const_data_ptr<double, 0>() const
工具版本:
您能帮我解释一下吗:
这里有一个重组提示:在重组名称中,字符串前面已指示了长度。在本例中,不同的部分是“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 提交错误报告,因为我认为没有充分的理由。