如何禁用特定的 nvcc 编译器警告

21
我希望能够使用nvcc禁用特定的编译器警告,具体来说是禁用以下警告:
warning: NULL reference is not allowed
我正在处理的代码中使用了NULL引用作为SFINAE的一部分,因此无法避免使用它们。理想的解决方案是在我们要禁用警告的源文件中使用#pragma,但如果存在可以关闭仅针对此警告的编译器标志,则也可以接受。

你可以通过谷歌搜索或者阅读nvcc手册来了解相关内容。 - Soroosh Bateni
2
通过输入 nvcc --help 命令,我可以看到有一个 --disable-warnings 选项或者等价的 -w 选项。 - Soroosh Bateni
1
警告是来自主机代码还是设备代码(记住,nvcc不是编译器..)? - talonmies
3
这是一个“编译器驱动程序”。警告信息可能来自宿主编译器(微软C++或GCC)或设备编译器(LLVM或Open64,取决于你编译的架构)。因此我问你这些警告是否出现在设备代码还是宿主代码中。 - talonmies
你是否在设备代码中使用模板?如果没有,你可能想把你的模板移到.cu文件之外。CUDA C接近但不完全兼容C++。当尝试使用更晦涩的C++特性时,你可能会遇到其他问题。.cu文件编译速度也可能相对较慢,因此从长远来看,只在其中保留设备代码可能是一个优势。 - Roger Dahl
显示剩余5条评论
7个回答

31

实际上,使用NVCC可以禁用设备上特定的警告。我花了很长时间才弄清如何做到这一点。

您需要使用-Xcudafe标志与此页面列出的标记相结合。例如,要禁用"controlling expression is constant"警告,请将以下内容传递给NVCC:

-Xcudafe "--diag_suppress=boolean_controlling_expr_is_constant"

对于其他警告,请参见上述链接

我无法在Visual Studio 2012和CUDA 5.5上进行设置。但是,在4.2和旧版本的Studio 中可以工作。顺便说一下,这个问题已经在devtalk.nvidia.com上讨论过(得出了与此处相同的结论)。请查看:https://devtalk.nvidia.com/default/topic/370952/disable-a-warning-/. - hthms
@cudafe 除了你提到的那些标记之外,还接受其他几个(很多?)标记,而且我不确定它是否实际上会接受列表中的所有内容。你试过其中大部分吗? - einpoklum
如果您包含像Eigen这样的库,那么这个答案就是救星,因为控制表达式警告垃圾邮件使得其他任何警告都难以看到。 - Mranz
有没有办法使用编译指示 pragma 更本地化地完成这个任务? - Joe
3
还发现您可以在nvcc命令中添加“-Xcudafe --display_error_number”以生成错误编号。该数字(不包括任何符号或字母)可用作diag_suppress的参数(例如,在文件中:#pragma diag_suppress 2381)。 - Aaron Swan
显示剩余3条评论

17

关于-xcudafe的问题,补充一下之前的回答(由于声望不够,无法在评论中留言):

重要修改:

cudaFE显然是Nvidia从Edison Design Group获得的C++前端的定制版本。您可以在此处找到其文档:http://www.edg.com/docs/edg_cpp.pdf。我目前正在参考2019年7月v5.1手册的页码。

@einpoklum指出,就像我在最初的帖子中最初陈述的那样,仅进行push/pop并不起作用,特别是#pragma push会生成一个警告,表示它被忽略了。我无法复制这个警告,但确实在下面的测试程序中,CUDA 10.1和CUDA 9.2都没有实际执行push/pop操作(请注意,第20行和第22行都没有生成警告)。

但是,在该手册的第75页中,他们介绍了如何在不使用push/pop的情况下进行局部诊断严重性控制:

以下示例抑制了对类A声明中“无意义的友元声明”的警告:

#pragma diag_suppress 522
class A { friend class A; };
#pragma diag_default 522
class B { friend class B; };
#pragma diag_default 将警告返回到默认状态。另一个示例是:
#pragma diag_suppress = code_is_unreachable
...
#pragma diag_default = code_is_unreachable

等号符是可选的。测试表明这样做可以正确地本地化严重性控制。此外,测试还显示以这种方式添加诊断抑制会增加先前的诊断抑制,而不是替换它们。值得注意的是,在CUDA 10.1中,无法访问的代码没有生成警告,而在CUDA 9.2中则有。最后,手册第77页提到了一种新的推入/弹出语法:

#pragma push_macro(“identifier”)
#pragma pop_macro(“identifier”)

但是我无法让它在下面的程序中工作。

以上所有内容都经过以下程序测试,使用nvcc -std=c++14 test_warning_suppression.cu -o test_warning_suppression编译:

#include <cuda_runtime.h>

__host__ __device__ int return1(){
    int j = -1; //warning given for both CUDA 9.2 and 10.1
    return 1;
    if(false){ return 0; } //warning given here for CUDA 9.2
}

#pragma push
#pragma diag_suppress = code_is_unreachable 
#pragma diag_suppress = declared_but_not_referenced
__host__ __device__ int return2(){
    int j = -1;
    return 2;
    if(false){ return 0; }
}
#pragma pop

__host__ __device__ int return3(){
    int j = -1; //no warning given here
    return 3;
    if(false){ return 0; } //no warning here even in CUDA 9.2 
}

//push/pop did not localize warning suppression, so reset to default
#pragma diag_default = declared_but_not_referenced
#pragma diag_default = code_is_unreachable

//warning suppression localized to lines above by diag_default!
__host__ __device__ int return4(){
    int j = -1; //warning given for both CUDA 9.2 and 10.1
    return 4;
    if(false){ return 0; } //warning given here for CUDA 9.2
}

/* below does not work as of CUDA 10.1
#pragma push_macro(“identifier”)
#pragma diag_suppress = code_is_unreachable 
__device__ int return5(){
    return 5;
    if(false){ return 0; }
}
#pragma pop_macro(“identifier”)

__device__ int return6(){
    return 6;
    if(false){ return 0; }
} */

int main(){ return 0; }

没问题!我花了一些时间才搞清楚,所以想分享一下。 - dada_dave
2
diag_suppress的可能性列表在这里:http://www.ssl.berkeley.edu/~jimm/grizzly_docs/SSL/opt/intel/cc/9.0/lib/locale/en_US/mcpcom.msg - Aaron Swan
1
这个编译指示是否会在周围环境中添加抑制项,还是替换掉原有的抑制项? - einpoklum
1
无论如何,如果我这样做,就会收到有关push和pop的投诉:“警告:忽略#pragma push”等。 - einpoklum
@einpoklum 看了用户手册,似乎 push/pop 的语法已经改变了(第77页)。在第75页,他们介绍了如何在不使用 push/pop 的情况下完成 - 无论哪种方式都应该只是添加抑制而不是压制它们,但我一直忙于工作,没有时间测试。我会编辑我的答案以反映新的语法。感谢您提醒我! - dada_dave
显示剩余3条评论

9

补充user2333829的回答:如果您知道警告名称,可以像这样禁用它:

-Xcudafe "--diag_suppress=boolean_controlling_expr_is_constant"

如果您不知道名称,请通过编译获取警告编号:

-Xcudafe --display_error_number

然后使用以下代码:
-Xcudafe --diag_suppress=<warning_number>

(注:同时选择两个选项似乎不起作用。)

1
两个选项都可以同时使用,但需要额外小心。要么是-Xcudafe --display_error_number -Xcudafe --diag_suppress=<warning_number>,要么是-Xcudafe "--display_error_number --diag_suppress=<warning_number>" - Jakub Klinkovský
如果你得到的警告“数字”不是一个数字,而是一个字符串,例如#20208-D,那么你该使用什么来进行抑制? - einpoklum
好的,看起来你只是使用数字就可以了。但是,你使用什么来使用 #pragma diag_suppress 进行抑制呢? - einpoklum

3

您可以使用w标志来抑制警告

nvcc -w

2
我找不到一个可以匹配我的警告的-Xcudafe,所以这里有另一种方法。
您可以向 CL.exe 传递编译器标志来禁用特定警告。例如,要禁用有关未检查迭代器的警告,可以传递 /wd4996
warning C4996: 'std::_Copy_impl': Function call with parameters that may be
unsafe - this call relies on the caller to check that the passed values are 
correct. To disable this warning, use -D_SCL_SECURE_NO_WARNINGS. See 
documentation on how to use Visual C++ 'Checked Iterators'

这里的棘手之处在于默认情况下,主机编译器设置中的参数不会传递给 nvcc,因此您需要通过 CUDA C/C++ 对话框添加它。
请参考以下截图进行操作:enter image description here

0

我在使用Ubuntu g++编译器的情况下,使用nvcc进行编译,我的情况下是openmpi mpic++。对于g++编译器的"-Wunused-result",相应的消息抑制是"-Wno-unused-result"。因此,在nvcc中传递像"-Xcompiler“-Wno-unused-result”这样的参数对我很有效。



网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接