【问题标题】:How to hint to Visual C++ compiler optimizer that a specific branch of an if-statement is unlikely to be executed?如何提示 Visual C++ 编译器优化器不太可能执行 if 语句的特定分支?
【发布时间】:2011-07-01 19:15:44
【问题描述】:

我们有一个用于错误检查的宏,如下所示:

#define CheckCondition( x ) \
    if( x ) { \
    //okay, do nothing \
    } else { \
       CallFunctionThatThrowsException(); \
    }

通常条件必须是true,我们希望CPU分支预测总是选择这条路径,如果它恰好是false,我们并不真正关心错误预测——抛出异常无论如何,大量的堆栈平仓将花费一大笔钱。

根据 CPU 核心描述,分支预测将处理前向跳转和后向跳转略有不同(例如总是执行后向跳转而从不执行前向跳转),编译器可以通过生成正确的代码来改进分支预测提示 CPU 分支预测器。

gcc 似乎为此提供了likely and unlikely hints。 Visual C++ 中有类似的东西吗?可以用__assume keyword吗?

【问题讨论】:

  • 阅读文档很明显__assume 不能使用,因为它使编译器完全跳过另一个分支。
  • 听起来像是微优化
  • @VJo:嗯,有点。但其目的是更改一个宏并对所有使用它的代码产生影响。如果这能让我们在执行速度上稍微提高一点,那也还不错。
  • @VJo 如果您想节省微秒,那么微优化可能很重要。
  • 仅供参考:这是一篇有趣的文章,分析了__builtin_expect在GCC中的作用:blog.man7.org/2012/10/how-much-do-builtinexpect-likely-and.html

标签: c++ visual-c++ optimization compiler-construction compiler-optimization


【解决方案1】:

启用Profile-Guided Optimization。编译器不仅会最大化分支预测,而且可能会完全将冷代码移开。这个频道 9 video 解释了各种优化。

【讨论】:

  • PGO 需要单独通过,而且我必须在我的测试运行中涵盖所有这些语句才能将它们全部 PGO。
  • 设置工作量更大,但也会生成更好的代码。微软不会实施可能的提示,因为 PGO 占主导地位。请注意,您不想使用测试来训练 PGO。测试涵盖边界情况。针对您的常见案例培训 PGO。
  • 不,PGO 并不主导 likely 提示 - 它们只是不同的东西。
【解决方案2】:

不幸的是,根据their developer center,不在 MSVC 中。

这非常令人沮丧,因为我们希望在等效 GCC 内在循环中为我们节省了关键的几微秒内循环的情况下使用它,但我们能得到的最接近的方法是交换 if 和 else 子句,所以更可能的情况是在前向跳转未采取的分支中。

【讨论】:

  • 如果一个分支是空的,如何实现这种交换?编译器似乎为if( !condition ) { action(); } else {}if( condition ) {} else { action(); } 发出完全相同的代码。
  • @sharptooth 我们从来不需要这样做——我们的案例在两个块中都有代码。恐怕这只是 MSVC 的又一个缺点。
  • 所以在条件的排序中有一个隐含的提示。所以你实际上拥有同样的能力。
  • @sharptooth 如果其中一个分支是空的,那么只有一个分支,对吧?优化器不傻!
  • @NikBougalis 假设 CPU 的分支历史足够大,可以在每次调用时记住这条特定指令。如果这个错误检查宏出现在代码中的许多不同位置,CPU 将无法将它们全部存储在其预测表中。
猜你喜欢
  • 2013-07-04
  • 1970-01-01
  • 1970-01-01
  • 2010-12-27
  • 2012-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-12
相关资源
最近更新 更多