likely, unlikely的作用

在项目中看到了likely、unlikely宏的使用, 一直不是非常清楚它们的作用,所以就深究下。

likely表示被測试的表达式大多数情况下为true, unlikely则表示相反。

两个宏定义:

#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)

这两个宏常常在条件转移的语句中使用,如if, else if等,这些语句生成的汇编代码都带有jmp指令.

CPU流水线的一些基本知识.
CPU流水线设计将一条指令的运行分成了好几个阶段,每一个阶段都是独立的逻辑电路。并且每一个阶段都有自己的阶段寄存器,所以各个阶段就能够实现真正的并行运行。

这里借用下CSAPP上的插图:

这里每条指令被分成了3个阶段, 指令I1的A阶段运行完成后。指令I2进入了A阶段运行,而指令I1则进入B阶段运行。I1的B阶段和I2的A阶段是并行运行的。

jmp指令对流水线带来的影响
由于jmp指令的运行会导致CPU跳转到还有一个内存地址,运行全新的指令,导致流水线里面的指令失效。所以CPU须要flush掉流水线上的寄存器。这样的操作须要几个cycle来恢复流水线的运行. 这样的影响被称之为hazard, 详细能够參考hazard Wiki
likely,unlikely带来的优化

依据gcc手冊, 所以这两个宏是用来告诉编译器分支的可能走向,从而帮助CPU进行分支预測来增强CPU流水线性能的.

看下以下的代码


int main (char *argv[], int argc) {
        int v;

        v = atoi(argv[1]);

        if (likely(a == 5))
                a++;
        else
                a--;

        printf("%d\n", a);

        return 0;
}

编译。带上-O2选项,得到的汇编代码:


0000000000400510 <main>:
  400510:       48 83 ec 08             sub    $0x8,%rsp
  400514:       48 8b 7f 08             mov    0x8(%rdi),%rdi
  400518:       31 c0                   xor    %eax,%eax
  40051a:       e8 f1 fe ff ff          callq  400410 <atoi@plt>
  40051f:       83 f8 02                cmp    $0x2,%eax
  400522:       75 18                   jne    40053c <main+0x2c> /* likely在这里表示a非常有可能是2, 所以将运行a++和printf调用放在一起, 免去了jmp带来的影响 */
  400524:       be 03 00 00 00          mov    $0x3,%esi
  400529:       bf 48 06 40 00          mov    $0x400648,%edi
  40052e:       31 c0                   xor    %eax,%eax
  400530:       e8 bb fe ff ff          callq  4003f0 <printf@plt>
  400535:       31 c0                   xor    %eax,%eax
  400537:       48 83 c4 08             add    $0x8,%rsp
  40053b:       c3                      retq
  40053c:       8d 70 ff                lea    -0x1(%rax),%esi
  40053f:       eb e8                   jmp    400529 <main+0x19> /* jump到调用printf代码处, 导致cpu flush掉流水线上的内容. */
  400541:       90                      nop
适用场景
gcc手冊表示这两条指令应该在程序猿对分支走向相当确定的情况下使用。只是大多数程序猿还是会预測失败,所以建议经过大量profiling来确定可能性。

在linux内核代码中likely和unlikely常常被用在错误代码处理的情况, 由于发生错误的情况往往是少数的。

时间: 2024-11-04 12:41:50

likely, unlikely的作用的相关文章

@jsonignore的作用

作用是json序列化时将java bean中的一些属性忽略掉,序列化和反序列化都受影响. 如下: package com.hzboy.orm; import java.util.List; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.pe

配置虚拟域名,hosts文件起作用

快速打开hosts方法 开始->运行->system32->回车 当前路径文件夹drivers\etc\hosts hosts文件起作用,目前楼主知道有两个可能原因 1.刷新dns cmd里面运行 ipconfig /flushdns 2.没配置前访问了一次域名,配置完之后浏览器没重启.所以不起作用 重新启动浏览器或者换一个浏览器

Linux中的环境变量配置文件及其作用

登录相关的配置文件: /etc/profile 范围:对所有用户生效 作用: a.定义USER变量 b.定义LOGNAME变量 c.定义MAIL变量 d.定义PATH变量 e.定义HOSTNAME变量 f.定义HISTSIZE变量 g.定义umask值 i.调用/etc/profile.d/*.sh文件 /etc/profile.d/*.sh 范围:对所有用户生效 说明:这是一族sh文件,没个都会被调用 例如: /etc/profile.d/lang.sh 作用:调用/etc/sysconfg/

表单的作用

①input的作用分为:单选按钮.文本框.密码框.复选按钮.隐藏表单域.文本选择框.图片按钮.普通按钮.提交按钮.重置按钮 ②select的作用:可创建单选或多选菜单,含有<option>标签 在HTML5中的新属性:1.autofocus属性            值autofocus                     规定在页面加载后文本区域自动获得焦点: 2.disabled                        disabled                      

shell中各种括号的作用

小括号里是命令大括号是变量值   一.小括号,圆括号() 1.单小括号 () ①命令组.括号中的命令将会新开一个子shell顺序执行,所以括号中的变量不能够被脚本余下的部分使用.括号中多个命令之间用分号隔开,最后一个命令可以没有分号,各命令和括号之间不必有空格. ②命令替换.等同于`cmd`,shell扫描一遍命令行,发现了$(cmd)结构,便将$(cmd)中的cmd执行一次,得到其标准输出,再将此输出放到原来命令.有些shell不支持,如tcsh. ③用于初始化数组.如:array=(a b

VMware Tools的安装及其作用(redhat5.5为例)

VMware Tools是VMware虚拟机中自带的一种增强工具,相当于VirtualBox中的增强功能(Sun VirtualBox Guest Additions),是VMware提供的增强虚拟显卡和硬盘性能.以及同步虚拟机与主机时钟的驱动程序. 只有在VMware虚拟机中安装好了VMware Tools,才能实现主机与虚拟机之间的文件共享,同时可支持自由拖拽的功能,鼠标也可在虚拟机与主机之前自由移动(不用再按ctrl+alt),且虚拟机屏幕也可实现全屏化. 在vm上安装完redhat系统后

磁盘阵列RAID的功能作用介绍

RAID是一个我们经常能见到的名词.但却因为很少能在实际环境中体验,所以很难对其原理能有很清楚的认识和掌握.RAID是英文Redundant Array of Independent Disks的缩写,中文简称为独立磁盘冗余阵列.RAID就是一种由多块硬盘构成的冗余阵列.虽然RAID包含多块硬盘,但是在操作系统下是作为一个独立的大型存储设备出现.上海天盾数据恢复中心的专家告诉我们,利用RAID技术于存储系统的好处主要有以下三种: 1.通过把多个磁盘组织在一起作为一个逻辑卷提供磁盘跨越功能; 2.

Atitit.获取主板与bios序列号获取硬件设备信息&#160;&#160;Wmi&#160;wmic&#160;的作用

Atitit.获取主板与bios序列号获取硬件设备信息  Wmi wmic 的作用 1 获取硬件核心基础核心基础Wmi1 2 其他资料2 3 Wmic WMI 命令行接口2 4 Atitit.获取主板与bios序列号2 5 参考3 1 获取硬件核心基础核心基础Wmi WMI,是Windows 2K/XP管理系统的核心:对于其他的Win32操作系统,WMI是一个有用的插件.WMI以CIMOM为基础,CIMOM即公共信息模型对象管理器(Common Information Model Object 

PLM在工业4.0中的作用

1 PLM支撑个性化定制 支撑个性化定制是工业4.0的特征之一.在工业4.0时代,个性化定制不像现在买汽车,只有颜色.型号等非常有限的选项,而是涉及到关键零件,如发动机. 选零件本质上已经是一种设计了.用户不是设计师,而设计是个专业性很强的活.要解决这个矛盾,就要用软件来支撑.这个软件就是PLM.PLM提供合适的部件,能保证用户所选的部件能与其他部件一起正常运转,且保证产品质量.从这种意义上说,PLM就像傻瓜相机:自动对焦.自动调光圈,让普通人也能照出近乎专业的照片. 2 PLM支撑智能生产 生

JSP 的内置对象及方法,动作和作用,常用指令

JSP 的内置对象及方法:JSP 共有以下9 种基本内置组件:request:用户端请求,此请求会包含来自GET/POST 请求的参数:response:网页传回用户端的回应:pageContext:网页的属性是在这里管理:session:与请求有关的会话期,可以存贮用户的状态信息:application:servlet 正在执行的内容:out:用来传送回应的输出:config:servlet 的构架部件,用于存取servlet 实例的初始化参数:page:JSP 网页本身:exception: