使用 clang 编译 CUDA 时 C++ 虚拟类出现 nvlink 错误

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

在处理 CUDA 项目时,我收到

 nvlink
错误,指出
 __cxa_pure_virtual
具有未定义的引用。我的存储库的结构类似于 ModernCMake - 扩展示例中的示例。

令人惊讶的是,我在使用

nvcc
编译时没有收到此错误,我想使用
clang
编译我的代码,因为我想使用
clang
的LSP。

这可能是由于我处理虚拟课程的方式所致。这是我的编译命令以及相关错误:

➜  CUDA-Path-Tracer git:(main) ✗ make build
cmake -S . -B build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_CUDA_COMPILER=clang++-20 -DCMAKE_CXX_COMPILER=clang++-20 -DCMAKE_CUDA_ARCHITECTURES=native
-- The CXX compiler identification is Clang 20.0.0
-- The CUDA compiler identification is Clang 20.0.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/clang++-20 - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Detecting CUDA compiler ABI info
-- Detecting CUDA compiler ABI info - done
-- Check for working CUDA compiler: /usr/bin/clang++-20 - skipped
-- Detecting CUDA compile features
-- Detecting CUDA compile features - done
-- Performing Test HAVE_FLAG__ffile_prefix_map__home_eduard_Git_CUDA_Path_Tracer_build__deps_catch2_src__
-- Performing Test HAVE_FLAG__ffile_prefix_map__home_eduard_Git_CUDA_Path_Tracer_build__deps_catch2_src__ - Success
-- Configuring done (14.8s)
-- Generating done (0.1s)
-- Build files have been written to: /home/eduard/Git/CUDA-Path-Tracer/build
cmake --build build
gmake[1]: Entering directory '/home/eduard/Git/CUDA-Path-Tracer/build'
gmake[2]: Entering directory '/home/eduard/Git/CUDA-Path-Tracer/build'
gmake[3]: Entering directory '/home/eduard/Git/CUDA-Path-Tracer/build'
gmake[3]: Leaving directory '/home/eduard/Git/CUDA-Path-Tracer/build'
gmake[3]: Entering directory '/home/eduard/Git/CUDA-Path-Tracer/build'
[  0%] Building CUDA object src/CMakeFiles/cuda_path_tracer_lib.dir/error.cu.o
clang++-20: warning: CUDA version 12.6 is only partially supported [-Wunknown-cuda-version]
[  0%] Building CUDA object src/CMakeFiles/cuda_path_tracer_lib.dir/vec3.cu.o
clang++-20: warning: CUDA version 12.6 is only partially supported [-Wunknown-cuda-version]
[  1%] Building CUDA object src/CMakeFiles/cuda_path_tracer_lib.dir/sphere.cu.o
clang++-20: warning: CUDA version 12.6 is only partially supported [-Wunknown-cuda-version]
[  2%] Building CUDA object src/CMakeFiles/cuda_path_tracer_lib.dir/render.cu.o
clang++-20: warning: CUDA version 12.6 is only partially supported [-Wunknown-cuda-version]
[  3%] Building CUDA object src/CMakeFiles/cuda_path_tracer_lib.dir/world.cu.o
clang++-20: warning: CUDA version 12.6 is only partially supported [-Wunknown-cuda-version]
[  4%] Building CUDA object src/CMakeFiles/cuda_path_tracer_lib.dir/ray.cu.o
clang++-20: warning: CUDA version 12.6 is only partially supported [-Wunknown-cuda-version]
[  5%] Building CXX object src/CMakeFiles/cuda_path_tracer_lib.dir/image.cpp.o
nvlink error   : Undefined reference to '__cxa_pure_virtual' in 'src/CMakeFiles/cuda_path_tracer_lib.dir/sphere.cu.o'
gmake[3]: *** [src/CMakeFiles/cuda_path_tracer_lib.dir/build.make:177: src/CMakeFiles/cuda_path_tracer_lib.dir/sm_90.cubin] Error 255
gmake[3]: Leaving directory '/home/eduard/Git/CUDA-Path-Tracer/build'
gmake[2]: *** [CMakeFiles/Makefile2:924: src/CMakeFiles/cuda_path_tracer_lib.dir/all] Error 2
gmake[2]: Leaving directory '/home/eduard/Git/CUDA-Path-Tracer/build'
gmake[1]: *** [Makefile:101: all] Error 2
gmake[1]: Leaving directory '/home/eduard/Git/CUDA-Path-Tracer/build'
make: *** [Makefile:12: build] Error 2

我的存储库 atm 的结构如下:

├── apps
│   ├── CMakeLists.txt
│   └── main.cpp
├── CMakeLists.txt
├── include
│   └── cuda_path_tracer
│       ├── error.cuh
│       ├── image.hpp
│       ├── ray.cuh
│       ├── render.cuh
│       ├── shape.cuh
│       ├── sphere.cuh
│       ├── vec3.cuh
│       └── world.cuh
├── LICENSE
├── llvm.sh
├── Makefile
├── README.md
├── report
│   └── report.typ
├── src
│   ├── CMakeLists.txt
│   ├── error.cu
│   ├── image.cpp
│   ├── ray.cu
│   ├── render.cu
│   ├── sphere.cu
│   ├── vec3.cu
│   └── world.cu
└── tests
    ├── CMakeLists.txt
    ├── test_error.cpp
    ├── test_image.cpp
    ├── test_ray.cpp
    └── test_vec3.cpp

我唯一的虚拟类是

Shape
,其定义为

/**
 * @file shape.cuh
 */

#pragma once

#include "cuda_path_tracer/ray.cuh"

class Shape {
public:
  __host__ __device__ virtual ~Shape() = default;
  __host__ __device__ virtual auto hit(const Ray &r) const -> bool = 0;
};

对应的

Sphere
类是

/**
 * @file sphere.cuh
 */

#pragma once

#include "shape.cuh"

class Sphere : public Shape {
public:
  __host__ __device__ Sphere(const Vec3 &center, float radius);
  __host__ __device__ auto hit(const Ray &r) const -> bool override;

private:
  Vec3 center;
  float radius;
};

/**
 * @file sphere.cu
 */

#include "cuda_path_tracer/sphere.cuh"

__host__ __device__ Sphere::Sphere(const Vec3 &center, float radius)
    : center(center), radius(radius) {}

__host__ __device__ auto Sphere::hit(const Ray &r) const -> bool {
  Vec3 oc = r.getOrigin() - center;
  float a = r.getDirection().dot(r.getDirection());
  float b = 2.0f * oc.dot(r.getDirection());
  float c = oc.dot(oc) - radius * radius;
  float discriminant = b * b - 4 * a * c;
  return discriminant > 0;
}

我尝试过不同版本的

llvm
套件,特别是v18、19和现在的20。我尝试按照
clang-tidy
的建议定义隐式复制/移动成员,我尝试在
shape.cuh
中定义默认构造函数,但是没有效果。

我可以确认问题源于这些类,因为当它们的代码被注释掉时,代码就会编译。

我还尝试按照某些问题(

__cxa_pure_virtual
)中的建议将
while(1) {}
函数定义为循环,但这也不起作用,或者也许我在错误的标头中定义了它。

c++ cmake cuda clang clang++
1个回答
0
投票

事实证明,解决方案确实是将

__cxa_pure_virtual
定义为虚拟函数,因为 https://bugs.llvm.org/show_bug.cgi?id=49839 ,问题是我没有添加
 __device__
属性位于前面。该函数应该类似于:

extern "C" __device__ void __cxa_pure_virtual() {
  while (1) {
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.