高效,极不可能的条件
efficient, extremely-unlikely conditionals?
我有一些性能关键型代码,在极不可能的情况下会崩溃和烧毁(例如,当中间double
等于0.0
时,当该双精度值为零的可能性不大于任何其他值时(。
当然,一种选择是吹口哨并忽略角落情况,并祈祷它永远不会出现。但如果可能的话,我想抓住它;另一方面,我不太热衷于在性能关键型代码中添加条件。添加表单检查有什么技巧吗
if(val == 0.0)
{
// extremely unlikely code path
}
以一种将性能损失降至最低的方式?在某些编译器上,可以传递 CPU 分支预测提示,但我听说这些对现代处理器不再有任何影响?
可能 , 不太可能
在 Linux 内核中,它们被定义为
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
__builtin_expect宏是使用分支预测的 GCC 特定宏;它们告诉处理器条件是否可能为真,以便处理器可以在分支的正确"侧"预取指令。
您应该将定义包装在 ifdef 中,以确保在其他编译器上进行编译:
#ifdef __GNUC__
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
#else
#define likely(x) (x)
#define unlikely(x) (x)
#endif
你可能想看看这个问题的答案。如果您有任何在Windows上运行的想法,则可能需要也看看这个。
几乎可以肯定的是,值得你花时间看看分支预测的解释在回答这个问题时。(请注意,该问题中观察到的行为不仅在编译器中很常见,而且在语言中也很常见,Java 和 C++ 中的示例对此进行了说明。
据我了解,问题在于
if (val == 0.0)
{
// extremely unlikely code path
}
是分支预测器最初将假定条件为真,也就是说,它将开始执行您极不可能的第一次遇到这种情况时立即提供代码路径。分支机构的成本与其说是对val == 0.0
的评估但是,当val == 0.0
被证明是错误的时,退出不太可能的分支的成本是错误的。但是,在遇到几次分支语句之后,分支预测器将猜测条件为假,并执行将继续进行,就像您告诉编译器"false"分支一样可能采取的那个。
在这样的环境中运行,一般不需要优化分支,因为它将为您优化。您可以对分支进行的唯一优化是第一次优化当它被调用时(也许还有其他几次,取决于确切的内容分支预测算法查找(。如果您的应用程序对性能非常关键,以至于您无法承受该成本即使是运行函数的前一两次,您是否应该在C++中编程?
为了鼓励分支预测器第一次走正确的道路,但是,你可以写
if (val != 0.0)
{
// stuff you want to do almost every time
}
else
{
// extremely unlikely code path
}
这有两个优点:首先,它是便携式的,其次,它获得了极不可能的代码这样您就可以更轻松地查看代码通常应该做什么。缺点是它增加了另一个级别的缩进 // stuff you want to do almost every time
.
我承认自己也使用过这种技术。
您需要知道是否有条件实际上会严重损害性能。这是我使用的方法。
我倾向于假设,如果时间关键型代码中存在性能问题,则应追查该问题的实际问题。在诊断证明之前,不要假设有条件的伤害。
- 如果条件不相关,我应该更喜欢两个 if 语句而不是 if-else 语句吗?
- 条件不起作用,谁能解释为什么会这样?
- C# HashSet VS C++ std::unordered_set 使用自定义类键。C++慢...不可能。如何实现 C# 的速度?
- 为什么在C++不可能递增或进行数学运算,例如在声明为数组的变量上乘法
- 条件不变的 if 语句会减慢我的C++代码吗?
- fopen 与常量字符 * 从 QString 是不可能的
- 矢量返回常量引用,不可能向下转换
- 分配取消引用的字符指针真的不可能吗?
- C#类过程 - 控制C 应用程序,不可能读取输出
- 可能是不可能的模板参数规范/推论
- 易失性结构 = 结构不可能,为什么?
- 矢量超出范围,将值分配给空矢量>不可能?
- 为什么不可能实例化原子对
- 一个倒梯形,但如果输入高度对于宽度来说太大,那么它应该报告,不可能("不可能的形状"是什么)
- W10上不可能使用十字架编译的libpng16-16.dll执行
- 如果明确给出多维数组,为什么不可能char [] [] [] = {..},{..}}
- 为什么我的自定义界面总是返回不可能的0x80040213/VFW_E_NO_CLOCK
- 从张量的读取设备不可能的方法
- 多态性抽象语法树(递归下降解析器):不可能
- 高效,极不可能的条件