我也说说宏定义likely()和unlikely()

作者:gfree.wind@gmail.com
博客:blog.focus-linux.net   linuxfocus.blog.chinaunix.net
 
 
本文的copyleft归gfree.wind@gmail.com所有,使用GPL发布,可以自由拷贝,转载。但转载请保持文档的完整性,注明原作者及原链接,严禁用于任何商业用途。
======================================================================================================
虽然不是内核工程师,但是也经常使用这两个宏,不过一直没有深究。刚才看了Bean_lee评论了一篇关于likely()和unlikely()的文章,于是也过去凑了个热闹。

该文章前面没有什么问题,我也不再重复,但是最后有个错误。“另外有一点要注意的是,由于likely定义时用的常量是1,unlikely用的常量是0,这正好符合c/c++语言中bool变量的实际值,而_builtin_expect()函数对exp与c进行严格相等的比较的,
因此使用likely和unlikely时,其参数应该只使用逻辑表达式,因为逻辑表达式的值只有0或1。除非真要判断某个变量的值是1或0时,才会将其它类型的参数传给likely或unlikely。这一点可能很多人会不小心用错。”,引自:http://blog.chinaunix.net/space.php?uid=24708340&do=blog&id=3047035

我看到这段文字时,吓了一跳。我使用likely和unlikely时从来没注意过参数非得是逻辑表达式的值啊,即0和1。难道都用错了。。。想了一下,就知道该博主想错了。

当使用likely和unlikely的时候,参数可以为任何表达式。不是逻辑表达式没有关系,绝不会有错。我来解释一下:
  1. #define likely(x) __builtin_expect(!!(x),1)
  2. #define unlikely(x) __builtin_expect(!!(x),0)
这是likely和unlikely的定义。看一眼定义,!!(x)这个用法就会让人觉得奇怪,为什么要!!呢?否定的否定,不就是肯定吗?干嘛多此一举呢?这就是一个技巧,学习kernel的时候,可以学到不少类似的技巧。

按照__builtin_expect的定义,要用第一个参数和第二个参数比较,它期望的值是true。第二个值是1。这里的!!(x)就是为了保证当x本身作为逻辑值为true的时候,其!!(x)值为1。举个简单的例子:
  1. if (likely(5)) {
  2.     printf("Hit!\n");
  3. }
  4. else {
  5.     printf("Not hit\n");
  6. }
本身if (5)为true,因为C标准里面规定任何非0的值均为true。Ok,!(5)为0,而!!(5)为1。这就是为啥likely和unlikely要使用!!(x),就为了其逻辑判断的值为1或者0。

关于为什么likely和unlikely可以提高程序的performance,我就不献丑了。给个官方的文献链接:http://kernelnewbies.org/FAQ/LikelyUnlikely

总的来说,它们是对编译器的一种指示,告诉编译器哪个分支更有可能发生,来最大的满足CPU的流水线作业。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/278338.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

图片懒加载与预加载

预加载 常用的是new Image();,设置其src来实现预载,再使用onload方法回调预载完成事件。function loadImage(url, callback) {var img new Image(); //创建一个Image对象,实现图片的预下载img.src url;if (img.complete){ // 如果图片已经存…

电脑pin重置_如果忘记了如何重置Windows PIN

电脑pin重置A good password or PIN is difficult to crack but can be difficult to remember. If you forgot or lost your Windows login PIN, you won’t be able to retrieve it, but you can change it. Here’s how. 好的密码或PIN很难破解,但很难记住。 如果…

android.support不统一的问题

今天supprt28遇到的问题,由于28还是预览版,还存在一些bug 都是因为如果程序内出现不同的,support或者其他外部引用库的多个版本,Gradle在进行合并的时候会使用本地持有的,最高版本的来进行编译,所以25的sup…

轻松查看Internet Explorer缓存文件

Sometimes you may need a quick and easy way to access Internet Explorer’s cache. Today we take a look at IECacheView which is a great application to get the job done. 有时,您可能需要一种快速简便的方法来访问Internet Explorer的缓存。 今天&#xf…

洛谷P1019 单词接龙

题目描述 单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时&…

【Java】接口(interface)VS抽象类

接口(interface)可以说成是抽象类的一种特例,接口中的所有方法都必须是抽象的。接口中的方法定义默认为public abstract类型,接口中的成员变量类型默认为public static final。另外,接口和抽象类在方法上有区别&#x…

latex插入gif_如何将照片和GIF插入Google幻灯片

latex插入gifUsing text (and only text) in your Google Slides presentation is a great way to lose the attention of your audience. Inserting photos and animated GIFs can immediately spice things up by emphasizing the important points you make. 在Google幻灯片…

子矩阵

题目描述 给出如下定义: 子矩阵:从一个矩阵当中选取某些行和某些列交叉位置所组成的新矩阵(保持行与列的相对顺序)被称为原矩阵的一个子矩阵。例如,下面左图中选取第2、4行和第2、4、5列交叉位置的元素得到一个2*3的子…

springboot入门(一)--快速搭建一个springboot框架

原文出处 前言在开始之前先简单介绍一下springboot,springboot作为一个微框架,它本身并不提供Spring框架的核心特性以及扩展功能,只是用于快速、敏捷地开发新一代基于Spring框架的应用程序,总的来说springboot不是为了要替代Sprin…

q-dir 打不开文件_Q-Dir –多窗格文件管理器

q-dir 打不开文件Sometimes when looking through a file manager, it would be nice to have more than a dual-pane view. Now you can manage your files with up to four viewing panes at once with Q-Dir. 有时,在查看文件管理器时,拥有多个双窗格…

用面向对象的方法写敲门砖

一道名为"敲门砖"的面试题: 用面向对象的方法写,点击列表内,子元素的子标签, 来删除子元素 敲门砖考点: 递归(删除标签, 需要找到列表的直属子标签, 需要通过递归层层往上找, parentNode)冒泡(只需为顶级父元素addEventListener绑定事件, 并通过e.target区分子标签, …

windows10加载动画_如何关闭动画并使Windows 10看起来更快

windows10加载动画Windows 10 fades and window animations are pure eye candy, but waiting for them to load can make your PC seem a bit slow. If you’d like an instant response, you can disable Windows 10’s animations for a snappier desktop experience. Windo…

JData大数据竞赛18年赛题-如期而至-用户购买时间预测

年前做的,也是学习别人的作品作为记录 一、赛题 表1:sku基本信息表(jdata_sku_basic_info) 表2:用户基本信息表(jdata_user_basic_info) 表3:用户行为表(jdata_user_acti…

LNMP架构(二)

2019独角兽企业重金招聘Python工程师标准>>> 一 Nginx安装 1、切换目录 # cd /usr/local/src 2、下载 # wget http://nginx.org/download/nginx-1.12.1.tar.gz 3、解压 # tar xzvf nginx-1.12.1.tar.gz 4、切换到nginx目录下 # cd nginx-1.12.1/ 5、编译 # ./confi…

edge无法上网dns_如何在Microsoft Edge中通过HTTPS启用DNS

edge无法上网dnsMicrosoft will one day enable DNS over HTTPS (DoH) for all Windows applications, but you can enable it in the new version of Microsoft Edge today with a hidden flag. DoH will improve your security and privacy online, but it isn’t yet enable…

UIButton小结

前言 本来没有打算写这篇文章的, 主要是因为在工作中遇到一些同事再用 有UIButton的时候, 有些很基本的,系统API提供的都不知道, 例如 如何让UIButton的文字居上,居左, 居右, 居下对其等一些基本点, 为此我特地写了一下UIButton小结 UIButton回顾 继承关系 NSObject -> UIRe…

Channel Allocation HDU1373

染色问题&#xff1a;相邻不能染同一种颜色 最少需要的颜色的数量最大团点的数量 #include<bits/stdc.h> using namespace std;#define N 27int n; int mp[N][N]; int ans; int alt[N][N]; int Max[N];bool dfs(int cur,int tot)//cur是s1集合的个数 {if(0cur){if(tot>…

satis原理浅析

什么是satis 我们一般是从packagist获取composer包的&#xff0c;但这些都是公开的。那如果我们想创建自己的私有库呢&#xff0c;比如企业就会有这方便的需要&#xff0c;那我们就可以用satis来创建自己的私有库。 Satis 是一个静态的 composer 资源库生成器。它像是一个超轻量…

HDU - 5686-Problem B (递推+高精)

度熊面前有一个全是由1构成的字符串&#xff0c;被称为全1序列。你可以合并任意相邻的两个1&#xff0c;从而形成一个新的序列。对于给定的一个全1序列&#xff0c;请计算根据以上方法&#xff0c;可以构成多少种不同的序列。 Input 这里包括多组测试数据&#xff0c;每组测试数…

c#写字板实现加粗功能_Windows 7中写字板和绘画中的新功能

c#写字板实现加粗功能WordPad and Paint are often overlooked accessories included in all versions of Windows since 95. They are still included in Windows 7 and now have a new look with some enhanced features. Here we will take a look at some of the new impro…