让我们说我对预处理(使用gcc
)hpp / cpp文件感兴趣,这些文件包含CUDA内核声明。我希望预处理器不要废弃__global__
说明符,否则我将无法链接.cu
文件中的定义。
例如,文件t1.hpp
:
__global__ void foo(int* v, int n);
预处理:
gcc -E t1.hpp -I/usr/local/cuda/include -include cuda_runtime.h
但结果会废弃全球!:
...
# 1888 "/usr/local/cuda/include/cuda_runtime.h"
#pragma GCC diagnostic pop
# 1 "<command-line>" 2
# 1 "t1.hpp"
void foo();
但如果我在CUDA 9.0+中定义__CUDABE__
(在CUDA 8.0上)或__CUDA_LIBDEVICE__
,我就可以保留这些信息:
gcc -E t1.hpp -I/usr/local/cuda/include -include cuda_runtime.h -D__CUDABE__
最终结果:
...
# 1888 "/usr/local/cuda/include/cuda_runtime.h"
#pragma GCC diagnostic pop
# 1 "<command-line>" 2
# 1 "t1.hpp"
__attribute__((global)) void foo();
所以我的问题是,__CUDABE__
和__CUDA_LIBDEVICE__
是什么,以及可能是副作用。
我还看到clang在__clang_cuda_runtime_wrapper.h
中定义了这些宏。那么这可以安全吗?
答案 0 :(得分:1)
由于它没有在任何地方记录,它是他们使用的某种内部标志(可以,因为你已经注意到编译器之间的变化),所以你可能不应该依赖它。它在crt/host_defines.h
中定义,没有很好的文档记录,所以我无法破译它的含义。
有没有理由不能使用nvcc
预处理文件?
这应该做你想做的事情,并用正确的参数调用gcc
(至少在我的系统上):
nvcc -E --x=cu t1.hpp`
如果由于某种原因无法使用nvcc
,则可以始终以详细模式(nvcc -E -v --x=cu t1.hpp
)调用它,并查看它设置的标志。在我的带有CUDA 9.1的linux系统上,我得到了:
gcc -std=c++14 -D__CUDA_ARCH__=300 -E -x c++ \
-DCUDA_DOUBLE_MATH_FUNCTIONS -D__CUDACC__ \
-D__NVCC__ "-I/opt/cuda/bin/..//include" \
-D"__CUDACC_VER_BUILD__=85" -D"__CUDACC_VER_MINOR__=1" \
-D"__CUDACC_VER_MAJOR__=9" -include "cuda_runtime.h" \
-m64 "t1.hpp"
但是,您可能必须为要使用的每个CUDA版本执行此操作,因为这些标记可能会更改。