【问题标题】:constexpr function params for not known at compile time booleans C++编译时未知的 constexpr 函数参数 booleans C++
【发布时间】:2021-10-24 10:48:58
【问题描述】:

我需要运行一个带有 N 个布尔变量的函数,我想让它们成为 constexpr 以消除比较并保存代码免受分支预测失败的影响。

我的意思是:

templateFunc<b1, b2, b3, b4 ...>(args...);

由于 b1..bn 变量只是布尔变量并且可能只有 2 个状态,我可以这样写:

if (b1 && b2)
  templateFunc<true, true>(args...);
else if (b1 && !b2)
  templateFunc<true, false>(args...);
else if (!b1 && b2)
  templateFunc<false, true>(args...);
else
  templateFunc<false, false>(args...);

问题很明显,我需要对 5 个变量进行 64 次调用。有什么解决方案吗?

【问题讨论】:

  • 布尔值当前不是constexpr?如果不是,这种方法只是将比较移到其他地方 - 不会消除分支预测失败。顺便说一句,您测量到这是您代码中的瓶颈吗?
  • 不,不幸的是,它们在编译时并不为人所知。是的,这就是瓶颈,一个预计会经历数百万次迭代并被频繁调用的循环
  • 在这种情况下,您只是将比较移出run,这仅在您对每个run 进行多次比较时才有用。好吧,如果您启用优化,编译器可以将独立检查移出循环或通过调用传播常量。
  • 你能告诉我具体有哪些优化吗?我启用了矢量化(不是这里的情况吗?)和-O3。为 constexpr 和 just if() 运行代码,差异为 100 倍。一个调用使用模板而另一个不使用的完全相同的代码。
  • 这不是一个公平的比较,对吧?没有优化可以消除依赖于运行时值的比较,但如果它不依赖于它,它可以将它移出循环。但不确定 Arduino 编译器的特定标志。

标签: c++ templates variadic-templates constexpr branch-prediction


【解决方案1】:

使用std::variant (C++17),您可以通过std::visit 进行动态调度:

// helper
std::variant<std::false_type, std::true_type> to_boolean_type(bool b)
{
    if (b) return std::true_type{};
    return std::false_type{};
}

然后

std::visit([&](auto... bs){templateFunc<bs...>(args...);},
           to_boolean_type(b1), to_boolean_type(b2));

Demo

【讨论】:

  • 这实际上是否使生成的 asm 更高效,或者这只是让编译器用更少的源代码为您发明分支?它必须以某种方式分支以调用模板的不同版本(或跳转到它们的内联版本),但可能使用跳转表而不是分支树,这可能会或可能不会得到更好的优化。
  • 它确实有效。我检查了汇编代码,它有 8 个不同的函数,具有 3 个布尔变量的函数的预期返回值。 (所有 if 语句都是 constexpr,所以即使在编译时也有意义)
  • @PeterCordes:分支可以发生在循环之外,例如 for (auto e : v) { if (cond) { foo(e); } else { bar(e); }}if (cond) {for (auto e : v) { foo(e); } } else { for (auto e : v) { bar(e); } } (而我的示例可能会通过一些优化正常转换,类似的代码可能更难为编译器优化)。
  • 对,我第一次误解了这个问题。我认为它希望消除 all 分支,而不是仅仅保存键入而不是手动分派到函数/循环的 2^5 个版本之一(手动将分支提升出循环)。所以这相当于你想要的,希望没有额外的开销。条件分支树与循环外的一个间接分支如果很短可能仍然很重要,但主要目标仍在实现中。
猜你喜欢
  • 2021-02-13
  • 1970-01-01
  • 1970-01-01
  • 2021-11-28
  • 1970-01-01
  • 1970-01-01
  • 2020-08-29
  • 2013-09-29
  • 2021-11-09
相关资源
最近更新 更多