C/C++ 分支预测(likely unlikely)
看一些代码时,会遇到likely unlikely, 查了查网上的资料,结合自己的理解记录一下。
1. 一些概念
指令周期是指执行一条指令所需要的时间,一般由若干个机器周期组成,是从取指令、分析指令到指令执行完所需的全部。
预取指令具体方法就是在不命中时,当数据从主存储器中取出送往CPU的同时,把主存储器相邻几个单元中的数据(称为一个数据块)都取出来送入Cache中。预取指令可以更好的利用 cpu资源。简单说就是从内存取指令很慢, cpu要等待这个过程。如果能提前预测可能执行的指令,就提前从内存把指令读到 cache, 由于 cache的访问速度较内存快,cpu要执行时就不用等很长时间了。
如果开发人员可以告诉编译器,哪个分支更有可能发生(likely) 或者 非常不可能发生(unlikely), 可以帮助编译器进行代码编译。
2. 看看代码
unlikely.cpp:
#include<stdio.h>
#include<stdlib.h> #define likely(x) __builtin_expect(!!(x), 1) //gcc内置函数, 帮助编译器分支优化
#define unlikely(x) __builtin_expect(!!(x), 0) int main(int argc, char* argv[]){
int x = ;
x = atoi(argv[]); if (unlikely(x == )){ //告诉编译器这个分支非常不可能为true
x = x + ;
}
else{
x = x - ;
} printf("x=%d\n", x);
return ;
}
3. 分析一下
gcc版本:gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
编译:gcc -O2 unlikely.cpp -o unlikely
反汇编一下,看看汇编:objdump -S unlikely
<main>:
: push %ebp
: e5 mov %esp,%ebp
: e4 f0 and $0xfffffff0,%esp
: ec sub $0x10,%esp
: 8b 0c mov 0xc(%ebp),%eax
804838c: c7 0a movl $0xa,0x8(%esp)
:
: c7 movl $0x0,0x4(%esp)
804839b:
804839c: 8b mov 0x4(%eax),%eax
804839f: mov %eax,(%esp)
80483a2: e8 c9 ff ff ff call <strtol@plt>
80483a7: f8 cmp $0x3,%eax
80483aa: 1f je 80483cb <main+0x4b>
80483ac: e8 sub $0x8,%eax
80483af: mov %eax,0x8(%esp)
80483b3: c7 movl $0x8048560,0x4(%esp)
80483ba:
80483bb: c7 movl $0x1,(%esp)
80483c2: e8 ff ff ff call <__printf_chk@plt>
80483c7: c0 xor %eax,%eax
80483c9: c9 leave
80483ca: c3 ret
80483cb: b8 0c mov $0xc,%eax
80483d0: eb dd jmp 80483af <main+0x2f>
80483d2: nop
80483d3: nop
我们从汇编代码可以看到,代码并不是按照顺序生成的。
unlikely分支(x==3)非常不可能发生,汇编代码生成到了最后。
这个对于庞大的代码还是非常有用的,毕竟在代码预期阶段,可以根据局部性原理把最可能发生的分支对应的指令缓存进来。
C/C++ 分支预测(likely unlikely)的更多相关文章
- __builtin_expect — 分支预测优化
1.引言 在很多源码如Linux内核.Glib等,我们都能看到likely()和unlikely()这两个宏,通常这两个宏定义是下面这样的形式. #define likely(x) __builtin ...
- 【CPU微架构设计】利用Verilog设计基于饱和计数器和BTB的分支预测器
在基于流水线(pipeline)的微处理器中,分支预测单元(Branch Predictor Unit)是一个重要的功能部件,它负责收集和分析分支/跳转指令的执行结果,当处理后续分支/跳转指令时,BP ...
- CPU 分支预测
去年在安宁庄的时候, 有个同事阐述了一个观点:php中的if else 在执行时考虑到效率的原因,不会按我们的代码的顺序一条一条去试,而是随机找出一个分支,执行,如果不对,再随机找到一个分支 当时由 ...
- 【操作系统之十二】分支预测、CPU亲和性(affinity)
一.分支预测 当包含流水线技术的处理器处理分支指令时就会遇到一个问题,根据判定条件的真/假的不同,有可能会产生转跳,而这会打断流水线中指令的处理,因为处理器无法确定该指令的下一条指令,直到分支执行完毕 ...
- 分支预测(branch prediction)
记录一个在StackOverflow上看到一个十分有趣的问题:问题. 高票答案的优化方法: 首先找到罪魁祸首: if (data[c] >= 128) sum += data[c]; 优化方案使 ...
- GCC的分支预测优化__builtin_expect
智能指针笔记 GCC的原子操作函数 将流水线引入cpu,可以提高cpu的效率.更简单的说,让cpu可以预先取出下一条指令,可以提供cpu的效率.如下图所示: 取指令 执行指令 输出结果 取指令 执行 ...
- 从一段 Dubbo 源码到 CPU 分支预测的一次探险之旅
每个时代,都不会亏待会学习的人. 大家好,我是 yes. 这次本来是打算写一篇 RocketMQ 相关文章的,但是被插队了,我也是没想到的. 说来也是巧最近在看 Dubbo 源码,然后发现了一处很奇怪 ...
- 现代中央处理器(CPU)是怎样进行分支预测的?
人们一直追求CPU分支预测的准确率,论文Simultaneous Subordinate Microthreading (SSMT)中给了一组数据,如果分支预测的准确率是100%,大多数应用的IPC会 ...
- 如何在代码层面提供CPU分支预测效率
关于分支预测的基本概念和详细算法可以参考我之前写的知乎回答,基本概念不再阐述了~~ https://www.zhihu.com/question/486239354/answer/2410692045 ...
随机推荐
- git入门教程,主要命令详解。
准备工作 git clone url / ssh ----------------------------------------------------------------------从git ...
- 整理低版本ie兼容问题的解决方案
CSS hack \9 所有的IE10及之前 * IE7以及IE7以下版本的 _ IE6以及IE6以下版本的 !important 提升样式优先级权重 1.ie6,7 ...
- android 静音
语音朗读 静音,设置变量识别好了. android插件下载开发. 实际可以这样, 保存应用的图标,名称,包名,下载地址. 插件作为apk. 或许希望apk不在桌面有图标.也可以.但是也没必要. 当下 ...
- 网络与多线程---OC中多线程方法GCD(二)
小编在前一篇中介绍了多线程实现的五种常用方法.在接下来所介绍的这种方法是最具有魅力的,最具有诱惑的实现多线程的方案---GCD 一.什么是GCD GCD是Grand Central Dispatch的 ...
- BZOJ2905: 背单词 AC自动机+fail树+线段树
$zjq$神犇一眼看出$AC$自动机 $Orz$ 直接就讲做法了 首先对每个串建出$AC$自动机 将$fail$树找到 然后求出$dfs$序 我们发现一个单词 $S_i$是$S_j$的子串当且仅当$S ...
- word标题编号与上一级不一致的解决方法
前段时间时间就遇到了这个问题,情形如下: 1.标题内容一 1.1二级标题 1.2二级标题 2.第二个一级标题 1.3第二个一级下的二级标题 1.4.就这样乱了 当时搜索一通后很容易就解决了……于是忘记 ...
- Jedis使用总结【pipeline】【分布式的id生成器】【分布式锁【watch】【multi】】【redis分布式】(转)
前段时间细节的了解了Jedis的使用,Jedis是redis的java版本的客户端实现.本文做个总结,主要分享如下内容: [pipeline][分布式的id生成器][分布式锁[watch][multi ...
- ARM架构--CPU的微架构
网上确实有说ARM架构的,但是此架构泛指用ARM指令系统的CPU,而不是CPU的微架构.,硬件电路上,要用ARM指令集系统,必然硬件设计电路上要要遵循,ARM指令的特点和寻址方式,所以说高通和苹果的C ...
- Delphi 类的类 class of 用法
http://blog.csdn.net/blue_morning/article/details/8815609 Delphi 类的类 class of 用法 这个概念本来在一个关于Delphi ...
- [Winform]无边框窗口悬浮右下角并可以拖拽移动
摘要 简单实现了一个这样的功能,程序启动时,窗口悬固定在右下角,并可以通过鼠标拖拽移动. 核心代码块 无边框窗口并不出现在任务栏 //无边框 this.FormBorderStyle = System ...