C/C++ 分支预测(likely unlikely)

2023-05-16

看一些代码时,会遇到likely unlikely, 查了查网上的资料,结合自己的理解记录一下。

1. 一些概念

  指令周期是指执行一条指令所需要的时间,一般由若干个机器周期组成,是从取指令、分析指令到指令执行完所需的全部。

  预取指令具体方法就是在不命中时,当数据从主存储器中取出送往CPU的同时,把主存储器相邻几个单元中的数据(称为一个数据块)都取出来送入Cache中。预取指令可以更好的利用 cpu资源。简单说就是从内存取指令很慢, cpu要等待这个过程。如果能提前预测可能执行的指令,就提前从内存把指令读到 cache, 由于 cache的访问速度较内存快,cpu要执行时就不用等很长时间了。

  如果开发人员可以告诉编译器,哪个分支更有可能发生(likely) 或者 非常不可能发生(unlikely), 可以帮助编译器进行代码编译

2. 看看代码

unlikely.cpp:


 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 
 4 #define likely(x) __builtin_expect(!!(x), 1) //gcc内置函数, 帮助编译器分支优化
 5 #define unlikely(x) __builtin_expect(!!(x), 0)
 6 
 7 int main(int argc, char* argv[]){
 8     int x = 0;
 9     x = atoi(argv[1]);
10 
11     if (unlikely(x == 3)){  //告诉编译器这个分支非常不可能为true
12         x = x + 9;
13     }
14     else{
15         x = x - 8;
16     }
17 
18     printf("x=%d\n", x);
19     return 0;
20 }  

3. 分析一下

gcc版本:gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3

编译:gcc -O2 unlikely.cpp -o unlikely

反汇编一下,看看汇编:objdump -S unlikely


 1 08048380 <main>:
 2  8048380:   55                      push   %ebp
 3  8048381:   89 e5                   mov    %esp,%ebp
 4  8048383:   83 e4 f0                and    $0xfffffff0,%esp
 5  8048386:   83 ec 10                sub    $0x10,%esp
 6  8048389:   8b 45 0c                mov    0xc(%ebp),%eax
 7  804838c:   c7 44 24 08 0a 00 00    movl   $0xa,0x8(%esp)
 8  8048393:   00
 9  8048394:   c7 44 24 04 00 00 00    movl   $0x0,0x4(%esp)
10  804839b:   00
11  804839c:   8b 40 04                mov    0x4(%eax),%eax
12  804839f:   89 04 24                mov    %eax,(%esp)
13  80483a2:   e8 c9 ff ff ff          call   8048370 <strtol@plt>
14  80483a7:   83 f8 03                cmp    $0x3,%eax
15  80483aa:   74 1f                   je     80483cb <main+0x4b>
16  80483ac:   83 e8 08                sub    $0x8,%eax
17  80483af:   89 44 24 08             mov    %eax,0x8(%esp)
18  80483b3:   c7 44 24 04 60 85 04    movl   $0x8048560,0x4(%esp)
19  80483ba:   08
20  80483bb:   c7 04 24 01 00 00 00    movl   $0x1,(%esp)
21  80483c2:   e8 99 ff ff ff          call   8048360 <__printf_chk@plt>
22  80483c7:   31 c0                   xor    %eax,%eax
23  80483c9:   c9                      leave
24  80483ca:   c3                      ret
25  80483cb:   b8 0c 00 00 00          mov    $0xc,%eax
26  80483d0:   eb dd                   jmp    80483af <main+0x2f>
27  80483d2:   90                      nop
28  80483d3:   90                      nop  

 我们从汇编代码可以看到,代码并不是按照顺序生成的。

unlikely分支(x==3)非常不可能发生,汇编代码生成到了最后。

这个对于庞大的代码还是非常有用的,毕竟在代码预期阶段,可以根据局部性原理把最可能发生的分支对应的指令缓存进来。

分类:  C/C++学习
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C/C++ 分支预测(likely unlikely) 的相关文章

随机推荐

  • 鸿蒙OS Hi3861的芯片实际开发中遇到的问题

    鸿蒙OS Hi3861的芯片实际开发中遇到的问题 优点 比较适合开发者快速开发 xff0c 上面的硬件操作的函数封装很简单 xff0c 非常适合初学者使用封装好的函数调用硬件管脚 xff0c 比如I2c gpio spi sdio 都被封装
  • private和public

    一 结构体 类的定义和实现分离 xff0c 代码可读性更强 xff08 非必须 xff09 span class token comment xxx h头文件 span span class token keyword struct spa
  • Mac下配置adb命令到系统变量与其后基本的adb操作

    1 进入terminal并输入echo HOME 2 命令行输入touch bash profile 注意 xff0c touch后面有一个空格 xff0c 为了在访达下的个人文件夹下面创建一个 bash profile文件 xff0c 类
  • Ubuntu 16.04 安装samba服务

    安装samba服务 sudo apt get install samba samba common 创建用于共享的目录 sudo mkdir span class token operator span home long share 给共
  • Cortex M4 SVC 中断

    Cortex SVC 中断 SVC 系统管理调用 异常优先级为1 xff0c SVC异常是由SVC指令触发 也可以直接设置NVIC寄存器触发异常 应用程序工作在非特权访问模式 xff0c 当需要特权模式访问系统资源时 xff0c 可以使用S
  • FreeRTOS --(4)任务管理之启动调度器

    目录 1 vTaskStartScheduler 2 xPortStartScheduler 3 vPortSetupTimerInterrupt 4 prvStartFirstTask 5 vPortSVCHandler 在使用 Free
  • FreeRTOS --(7)任务管理之任务切换

    现在创建任务 xff08 xTaskCreate xff09 启动调度器 xff08 vTaskStartScheduler xff09 xff0c 任务控制 xTaskDelay xff0c 以及Tick 中断 xff08 xPortSy
  • Spring Aop到底有什么用处?

    假如没有aop xff0c 在做日志处理的时候 xff0c 我们会在每个方法中添加日志处理 xff0c 比如 但大多数的日子处理代码是相同的 xff0c 为了实现代码复用 xff0c 我们可能把日志处理抽离成一个新的方法 但是这样我们仍然必
  • 获取对象自身的属性

    问题 找出对象 obj 不在原型链上的属性 注意这题测试例子的冒号后面也有一个空格 1 返回数组 xff0c 格式为 key value 2 结果数组不要求顺序 答案 Object keys 方法 xff08 156 ms xff09 返回
  • 重启linux后无法ssh登录

    博客搬运自我的个人博客 chantAria的博客 精力有限 新博客我会同步到CSDN 但博客内容的更新只会出现在个人博客 欢迎大家来玩耍哦 重启llinux后无法ssh登录的情况很多 其中一种情况是在之前update的时候产生了一个坏的内核
  • 使用FFmpeg将视频编码格式转化为H264编码

    背景介绍 xff1a web开发中涉及到视频播放的前端一般会使用h5的video标签对后端提供的视频文件url直接加载进行播放 xff0c 虽然视频文件后缀都是mp4 xff0c 但并非所有视频文件的编码格式都支持用video播放 xff0
  • Cause: org.xml.sax.SAXParseException; lineNumber: 5; columnNumber: 26; 1 字节的 UTF-8 序列的字节 1 无效。

    报错为 xff1a Cause org xml sax SAXParseException lineNumber 5 columnNumber 26 1 字节的 UTF 8 序列的字节 1 无效 是你的xml文件里面的 设置成了默认的UTF
  • Centos7 java服务开机自启动

    1 在 etc systemd system 目录下 新建脚本 cd span class token operator span usr span class token operator span lib span class toke
  • 我使用过的linux命令之strings

    strings命令用于输出文件中可打印的字符串 不论文件是普通文本 xff0c 还是可执行文件 xff0c 任何文件都可以 最常用的选项 xff1a a 扫描整个文件的任何段 xff0c 这是strings的默认行为 xff0c 但是这种默
  • HashMap的工作原理

    HashMap主要是用来处理键值对数据 xff0c 随着JDK版本的更新 xff0c JDK1 8对HashMap的底层也做了一些优化 xff0c HashMap是基于哈希表对Map接口的实现类 xff0c 它的特点是访问数据速度快 xff
  • 如何配置终端代理apt 代理

    1 临时用代理 xff0c 直接在终端里export代理 export http proxy 61 http 127 0 0 1 7890 export https proxy 61 http 127 0 0 1 7890 2 在 etc
  • ssh修改连接端口,以及修改端口之后连接不上的问题

    SSh服务配置文件路径一般都是在 etc ssh这个目录下面 sshd config 这个文件 使用VI vim编辑器 xff0c 打开sshd config这个文件 xff0c 搜索找到 port字段 去掉 xff0c 修改port 后面
  • FreeRTOS原理剖析:任务的创建

    1 任务创建API函数 任务的最基本功能是任务管理 xff0c 任务管理中最基本操作是任务的创建和删除 对于任务的创建和删除 xff0c 由于篇幅有点长 xff0c 分两篇分别讲解 在FreeRTOS中任务的创建函数如下 xff1a 函数描
  • @xmlAttribute等注解它的用处?

    用的是jdk自带的javax xml bind JAXBContext将对象和xml字符串进行相互转换 如果对要生成的 xml 格式有点些许的限制 xff0c 就会对生成xml的对象就需要进行些许控制 xff0c 控制对象的一个最可行的办法
  • C/C++ 分支预测(likely unlikely)

    看一些代码时 xff0c 会遇到likely unlikely 查了查网上的资料 xff0c 结合自己的理解记录一下 1 一些概念 指令周期 是指执行一条指令所需要的时间 xff0c 一般由若干个机器周期组成 xff0c 是从取指令 分析指