【发布时间】: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