问题描述
我的目标是 Skylake 硬件并使用 Clang 进行编译。
假设我们有一些代码结构如下:
int always_runs(int i,int acc); // ~30 cycles
int sometimes_runs(int i,int acc); // ~20 cycles
int foo(const std::array<bool,1000000> should_branch) {
int acc = 0;
for (int i = 0; i < should_branch.size(); i++) {
acc += always_runs(i,acc); // takes in acc,loop carried dependency
// unpredictable branch based on constant data
if (should_branch[i]) acc += sometimes_runs(i,loop carried dependency
}
return acc;
}
should_branch
中的数据没有遵循特定的模式,分支预测器对此很不满意。
一种选择是删除分支并用这样的条件移动替换它:
acc += should_branch[i] ? sometimes_runs(i,acc) : 0;
这消除了分支预测错误,但意味着正在完成不必要的工作。这是迄今为止我找到的最快的解决方案,也是我目前实施的方案。
有什么办法可以利用 should_branch
是已知且恒定的这一事实,以便预测器可以以某种方式向前看并根据数据正确预测?从人类的角度来看,这是是一个微不足道的预测。
我看过的一个选项是手动展开预测,这样我就有一个路径用于运行 {true,true}
,一个用于 {true,false}
,一个用于 {false,true}
,一个对于 {false,false}
等。这没有帮助,因为静态路径之间的分支导致的错误预测仍然导致代码比简单地消除上述分支慢。
是否还有其他方法可以优化遵循此模式的代码?改变算法来避免问题不是一种选择。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)