"M_PI" 和 "or" 的 nvcc 编译错误

nvcc compilation errors with "M_PI" and "or"

当试图编译这段代码时:

#define _USE_MATH_DEFINES
#include <cmath>
#include <cstdio>

void minimal_example(){
    int i=2;
    if(i==3 or i==4) printf("I want %d!\n",M_PI);
}

使用

nvcc -x cu -Xcompiler=/permissive- -dc cuda_nvcc_cl_test.cu -o cuda_nvcc_cl_test.obj

我得到以下错误(第 7 行):

error: expected a ")"
error: identifier "M_PI" is undefined

我正在使用 Windows 10 和 Visual Studio 的 cl.exe(x64 版本 19.16.27031.1)和 CUDA 工具包 10.1。

cmath 替换为 math.h 并将 or 替换为 ||(或者添加 #include <ciso646>)时,错误消失。但是,是否有一些编译器选项或其他可能性,以便我可以保持代码不变?

还有为什么 -Xcompiler=/permissive- 没有帮助?

这里有两个问题:

  1. 显然 nvcc 在解析您的代码之前包含 cmath。正如已接受的答案 here 中所讨论的,如果您包含 cmath 并且此时没有实例化定义,您将不会得到 M_PI 定义,并且 随后包含的 cmath 不会解决这个问题,因为包含了守卫。一种可能的解决方法是将 -D_USE_MATH_DEFINES 添加到编译命令行。这从编译过程开始就将定义放在适当的位置,并且 M_PI 以这种方式定义。

  2. 与我所读的正确或标准行为相反,使用 or 代替 || 似乎以包含 ciso646 为条件( on nvcc on windows/visual only only. nvcc on linux 似乎不需要这个)。是的,我知道它不应该那样工作,但它似乎是必要的。 This may be an issue with Visual Studio。如果愿意,您可以尝试使用 /Za 开关。 (我试了一下好像没什么用。)

使用 CUDA 10.1,在 VS2019 上,当我编译这个时:

#include <cstdio>
#include <ciso646>

void minimal_example(){
    int i=2;
    if(i==3 or i==4) printf("I want %f!\n",M_PI);
}

使用此命令行:

nvcc -x cu -dc test.cu -o test.obj -D_USE_MATH_DEFINES

我没有收到任何错误或警告。请注意,我还将您的 printf 格式说明符从 %d 更改为 %f 以与 M_PI.

的类型一致

如果您真的不想包含 ciso646nvcc supports 开关 -include 直接从命令行包含文件。因此我可以编译这个:

#include <cstdio>

void minimal_example(){
    int i=2;
    if(i==3 or i==4) printf("I want %f!\n",M_PI);
}

像这样:

nvcc -x cu -dc test.cu -o test.obj -D_USE_MATH_DEFINES -include ciso646

没有错误或警告。