[英]Can using `__builtin_expect` affect program semantics?
海湾合作委员会(和锵也),提供这种__builtin_expect
人类辅助的分支预测,为解释在这里 。 非正式地,人们通过以下方式解释其语义:“编译器只是无条件地处理指定的分支,如果条件应该与指示的不同,则会发生昂贵的回滚”。
但如果我有一段代码如下:
if (__builtin_expect(p != 0, 1)) // line 1
p->access_object(); // line 2
如果我按字面意思处理上面的非正式解释,编译器只需执行第2行而不等待第1行中的条件计算,因此如果指针恰好为空,则会导致未定义的行为(空指针解除引用)。
我的问题是,如果我使用__builtin_expect
,我仍然得到保证,我的防御性检查有效吗? 如果是这样的话,如果我在防御性检查中使用__builtin_expect
作为上述内容,我会获得任何运行时间的好处吗?
(注意:我这样使用__builtin_expect
目的是为了获得p
非空的情况下的最大性能,代价是减速(甚至是数量级) p
为空的情况;即使后者案件经常出现。)
不,builtin_expect不会影响无竞赛计划的语义。
特别是,如果该代码具有无法撤消的副作用,则编译器不得发出执行if
块主体的代码。 除了性能之外,代码必须“好像”不使用builtin_expect
。
对于您的具体示例:
if (__builtin_expect(p != 0, 1)) // line 1
p->access_object(); // line 2
如果p
为null,则无法取消引用。 那么在这种情况下, builtin_expect
什么意义呢? 它能做的最多就是告诉编译器“ p
可能不是null,所以可能会调用access_object()
。” 如果access_object()
的定义是inline
,编译器可能会尝试内联它,而如果您说“ p
可能为null”,编译器可能会决定最好不要在此调用站点内联access_object()
的代码,因为它不太可能被使用。
事实上,这导致在实践中非直观地使用了builtin_expect
:你可以用来表示“这段代码是慢速路径”,而不管它是多么“可能”。 作为一个简单的例子,服务器程序可能会这样做:
if (__builtin_expect(is_allowed(user, request), 1))
process(request);
else
reject(request);
即使我们发现50%的请求是非法的并且将被拒绝,我们仍可能决定标记可能采取的“快乐路径”,因为我们不关心减缓拒绝。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.