由于编译时计算的值,如何避免“无法访问的语句”?
Posted
技术标签:
【中文标题】由于编译时计算的值,如何避免“无法访问的语句”?【英文标题】:How to avoid an "unreachable statement" due to compile-time-computed values? 【发布时间】:2017-08-26 19:01:24 【问题描述】:如果我编写以下 CUDA 代码:
#include <stdio.h>
template <unsigned N>
__global__ void foo()
printf("In kernel foo() with N = %u\n", N);
if (N < 10) return;
printf("Wow, N is really high!\n");
/* a whole lot of code here which I don't want to indent */
int main()
foo<5><<<1,1>>>();
foo<20><<<1,1>>>();
return 0;
我收到编译器警告:
a.cu(8): warning: statement is unreachable
detected during instantiation of "void foo<N>() [with N=5U]"
(12): here
我“感觉”我不应该收到此警告,因为无法访问的代码仅对于模板参数的某些值是无法访问的。如果我写“CPU 等价物”,可以这么说:
#include <cstdio>
template <unsigned N>
void foo()
std::printf("In kernel foo() with N = %u\n", N);
if (N < 10) return;
std::printf("Wow, N is really high!\n");
/* a whole lot of code here which I don't want to indent */
int main()
foo<5>();
foo<20>();
return 0;
并使用 gcc (5.4.0) 构建它 - 即使我使用 -Wall
编译,我也没有收到任何警告。
现在,我可以通过写作来规避这个问题
if (not (N < 10))
printf("Wow, N is really high!\n");
/* a whole lot of code here which I don't want to indent */
但我宁愿避免不得不颠倒我的逻辑来跳过 nvcc 的“箍”。我也可以写
if (not (N < 10))
return;
else
printf("Wow, N is really high!\n");
/* a whole lot of code here which I don't want to indent */
但是 - 我不想缩进所有代码(同样的问题可能会再次出现,需要在 else 块内进行更多的缩进。
有什么我可以做的吗?另外,这不是一个“错误”,还是我应该将其报告为错误的错误功能?
【问题讨论】:
我首先要考虑的是在其中添加一个else
我不明白你在抱怨什么。对于无法访问代码的实例,您会收到警告。为什么编译器不应该这样做?
我和@talonmies 在一起。如果您调用foo<5>()
,您正在调用一个已“编译”的函数(不确定这是否是模板函数的正确术语),用于 N==5 的特殊情况。该结果与 N==20 的结果不同,它假定 N==5,而不将其视为变量。这是我考虑模板编程的想法。编译器非常正确地提及使用该常量无法访问的代码。其他编译器不警告也可以;他们可以实现非常相似的代码,但要注意常数 N 的变化性质。
现在好像在咆哮。为什么不在 developer.nvidia.com 上提交错误?对于这种行为有许多合理的解释,并不依赖于 NVIDIA 是一个邪恶的组织。与主机编译器的处理方式相比,nvcc
中主机/设备编译路径的分叉性质可能会使您更难以按您希望的方式处理这种情况。我不是语言专家,所以我不知道这是否合规。警告本身来自cudafe
工具,并受该工具的-t
开关影响,该开关会影响模板实例化。
访问被拒绝消息来自激进的垃圾邮件/威胁检测系统。我的建议是首先提供一个超级简单的琐碎报告 - 将您的报告减少到几乎为零的任何类型的文本条目。然后在系统记录后根据需要添加到报告中。道歉。
【参考方案1】:
怎么样:
template<unsigned N, bool>
struct FooImpl
static void foo()
std::printf("In kernel foo() with N = %u\n", N);
;
template<unsigned N>
struct FooImpl<N, false>
static void foo()
std::printf("In kernel foo() with N = %u\n", N);
std::printf("Wow, N is really high!\n");
/* a whole lot of code here which I don't want to indent */
;
template <unsigned N>
__global__ void foo()
FooImpl<N, N < 10>::foo();
【讨论】:
嗯,这是实现相同效果的“另一种方式”,但显然我们应该更喜欢使用真实代码而不是模板元编程来影响条件......这种方式需要更多代码,而且更多让读者感到困惑。另外,如果我在原始代码中嵌套了if (condition) return;
行,我需要嵌套 +Impl 函数 - 不好玩......所以这不是我所希望的。以上是关于由于编译时计算的值,如何避免“无法访问的语句”?的主要内容,如果未能解决你的问题,请参考以下文章