__builtin_xxx指令学习【1】__builtin_expect

2023-05-16

__builtin_expect是GCC编译器提供的一个内置函数,用于告诉编译器一个分支的执行概率,以便编译器在生成机器码时进行优化。它的语法如下:

__builtin_expect (long exp, long c)

其中,exp是一个表达式,c是一个常量。__builtin_expect的返回值是exp的值,但是编译器会根据c的值来优化代码,使得exp的执行更加高效。

__builtin_expect的使用背景是,现代CPU的分支预测机制可以预测分支的执行概率,从而提高程序的执行效率。但是,如果分支的执行概率与预测不符,就会导致CPU的流水线被清空,从而降低程序的执行效率。因此,为了让CPU的分支预测机制更加准确,我们可以使用__builtin_expect来告诉编译器一个分支的执行概率,从而让编译器生成更加优化的机器码。

具体来说,如果一个分支的执行概率很高,编译器会将这个分支的代码放在CPU的指令缓存中,从而加速分支的执行。如果一个分支的执行概率很低,编译器会将这个分支的代码放在CPU的指令缓存之外,从而避免浪费CPU的指令缓存。

一般使用的话我们需要封装一下宏

// 引入__builtin_expect函数来增加条件分支预测的准确性
#ifdef __GNUC__
#  define SDK_LIKELY(x) __builtin_expect(!!(x), 1)          // x很可能为真  
#  define SDK_UNLIKELY(x) __builtin_expect(!!(x), 0)        // x很可能为假
#else /* __GNUC__ */
#  define SDK_LIKELY(x) (x)
#  define SDK_UNLIKELY(x) (x)
#endif /* __GNUC__ */

下面是一个demo

#include <iostream>
#include <chrono>

int main() {
    auto start = std::chrono::high_resolution_clock::now();
    int sum = 0;
    for (int i = 0; i < 100000000; ++i) {
        if (SDK_LIKELY(i % 2 == 0)) {
            sum += i;
        } else {
            sum -= i;
        }
    }
    auto end = std::chrono::high_resolution_clock::now();
    std::cout << "Sum: " << sum << "\n";
    std::cout << "Time: " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << "ms\n";
    return 0;
}

该代码耗时215ms

不加SDK_LIKELY耗时219ms,提升效果不是很明显

需要注意的是:

__builtin_expect指令只有在分支的执行概率与预测不符的情况下才能提高程序的执行效率。如果分支的执行概率与预测相符,那么__builtin_expect指令就没有任何作用。因此,如果程序中的分支都已经被CPU的分支预测机制正确预测了,那么使用__builtin_expect指令也无法提高程序的执行效率。

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

__builtin_xxx指令学习【1】__builtin_expect 的相关文章

  • 如何返回另一个列表中 3 个最低值的列表

    如何返回另一个列表中 3 个最低值的列表 例如 我想获取此列表中的 3 个最低值 in list 1 2 3 4 5 6 input function in list 3 output 1 2 3 您可以使用heapq nsmallest
  • pexpect 相当于 Expect 的“send_user”

    作为我的延续上一个问题在 pexpect 中构建交互式选项菜单时 交互输入过滤器中的打印语句只有在交互完成后才会发送到 stdout 该文档似乎没有包含与 Expect 中的 send user 等效的方法 是否有任何解决方法可以将输出发送
  • 在 Expect 脚本中处理多个衍生进程

    这是我的预期脚本的用例 我拥有的少数几个之一 我想运行多个sed通过 ssh 命令 它就像预构建环境设置一样 我想运行这样的东西 usr bin expect set timeout 1 spawn noecho bash c ssh t
  • 有没有办法在“交互”命令后“期望”和“发送”

    因此 我需要在标准输出上输出远程进程的输出 但我还需要能够 监听 它 并在匹配我的关键字后发送命令 我需要这样的东西 我知道这段代码不正确 它的唯一目的是说明我需要什么 usr bin expect log user 0 spawn ssh
  • 使用 Expect 自动执行 2 个脚本之间的交互

    我有两个简单的脚本 我需要它们使用第三个脚本自动相互交互expect script script1 sh bin bash echo s1 started echo question1 read echo got REPLY echo qu
  • bash:expect 可以处理多个密码提示吗?

    我目前正在使用 Expect 来传递密码 这样我的脚本就可以自动运行 而无需我坐下来一遍又一遍地输入相同的密码 重要提示 请不要评论这有多大的安全风险或我应该如何使用 ssh 密钥 如果可以的话我会使用这些密钥 但我必须使用的设置不允许这样
  • 将 bash 数组传递给 Expect 脚本

    我有一个 bash 脚本 它像这样调用 Expect 脚本 SCRIPTS DIRECTORY my expect script sh my bash array 看起来我可以传递一个变量并使用它 对于这个例子 变量似乎是在 lindex
  • 正确处理土耳其语大写和小写,需要修改/覆盖内置函数吗?

    我正在处理多语言文本数据 其中包括使用西里尔字母的俄语和土耳其语 我基本上必须比较两个文件中的单词my file and check file如果这些词在my file可以找到check file 将它们写入输出文件中 保留两个输入文件中有
  • 如何使用带有可选提示的expect?

    假设我正在尝试为具有三个提示的 test sh 编写一个 Expect 脚本 prompt1 prompt2 prompt3 我的代码是这样的 spawn test sh expect prompt1 send pass1 expect p
  • 如何覆盖 javascript 本机对象的内置方法

    假设我们有窗口对象的警报方法 我想用漂亮的警报框来增强它 另外 我想保存现有的警报方法 以便我们可以在应用程序结束后切换回来 类似这样的东西 但它在 Firefox 控制台中抛出错误 window prototype alert funct
  • 将其放入 TCL 正则表达式中的转义字符串

    I use Expect作为测试框架并编写一些辅助函数来简化匹配模式的键入expect命令 因此 我寻找将任何字符串转换为字符串的函数 其中所有特殊的正则表达式语法都被转义 例如 和其他字符 这样我就可以将任何字符串放入正则表达式中 而不必
  • 在 Redhat 6.3 上安装 R 3+

    我想在我的 Red hat 集群上安装 R 其版本如下 cat etc redhat release Red Hat Enterprise Linux Server release 6 3 Santiago 当我访问 R 的主页时 这就是他
  • Tcl + 检查文件存在

    我正在尝试检查 Tcl 中是否存在文件 但我似乎无法得到真实的结果 尽管我知道它的存在 while true if file exists file name 1 exp send copy file txt destination r p
  • 与内置函数的命名冲突[重复]

    这个问题在这里已经有答案了 我犯了一个错误 如下所示 gt gt gt list a b c 但现在我想使用内置函数list 可以看到 listname之间存在命名冲突list和内置函数list 我该如何使用list作为内置函数而不是变量而
  • 在 bash 脚本中期望

    我正在尝试将 Expect 脚本实现到 bash 脚本中 请耐心等待 因为我对 bash expect 还很陌生 这是按预期工作的期望脚本 log user 0 file delete foo txt set fh open foo txt
  • android 有内置的 PDF 查看器吗?

    我最近听说 Froyo 中包含了它 我想知道这是否属实 如果有的话 这将对我的应用程序创意有很大帮助 您可能指的是Adobe阅读器 http news cnet com 8301 27076 3 20005815 248 html 可免费用
  • Lua中如何对数字表求和?

    Lua有内置的吗sum 功能 我似乎找不到一个 我几乎翻遍了文档中的所有地方 或许table sum 或类似的东西 以遵循当前的约定 但由于我找不到它 我不得不实现它 function sum t local sum 0 for k v i
  • 在 bash 中使用 ssh 内的 Expect 执行 sudo

    我想创建一个脚本来自动在多个 Linux 主机上进行安装 我使用 ssh 密钥登录到主机 在登录中我想做一个 sudo 我正在尝试使用 Expect 我在站上有它 但是我的服务器上没有运行脚本 我该怎么做 这是我的尝试 但没有运气 bin
  • 从 Bash 调用的 Expect 脚本的退出状态代码

    我制作了一个 Bash 脚本 它使用 Expect 脚本来自动进行 ssh 登录 该脚本连接到多个服务器并运行一些命令 bash 脚本会提示输入一次登录凭据 我想合并一个功能 其中如果第一个服务器登录失败 脚本将终止 以避免脚本检查下一个服
  • 当参数具有相同名称时如何恢复内置函数? [复制]

    这个问题在这里已经有答案了 我知道你是 不应该 https stackoverflow com questions 2417979 can i use variable name type as function argument in p

随机推荐

  • 电路设计_阅读英文数据手册并没有想象的那么难

    说明书的正文究竟包含哪几部分 xff0c 应根据不同产品的具体情况来确定 xff08 1 xff09 Release Date 检查手册发布的日期 xff0c 是预备版还是修正版 xff1b xff08 2 xff09 General De
  • 用C语言实现卷积操作(包含单通道单卷积和多通道多卷积以及维度的转换)

    用C语言实现卷积 单通单卷积多通道多卷积维度转换 xff08 多维转一维 xff09 完整代码实现 xff1a 单通单卷积 卷积其实就是个点成相加的过程 原理图如下 xff1a 关键代码实现 xff1a span class token c
  • 基于深度学习的车牌识别项目的APP部分之图像预处理(一):C语言读取bmp图像信息

    车牌识别项目之图像预处理一 xff1a C语言读取bmp图像信息 一 什么是bmp文件二 BMP格式结构1 文件信息头2 图像描述信息块3 BMP调色板4 BMP图像数据区 像素存储 像素数据 位图像素格式 三 原理实现 xff1a 1 打
  • 基于深度学习的车牌识别项目的APP部分之图像预处理(二):C语言实现bmp的二值化处理

    基于深度学习的车牌识别项目的APP部分之图像预处理 xff08 二 xff09 xff1a C语言实现bmp的二值化处理 一 二值化概念二 代码实现三 运行结果 xff1a 1 图像是8位深度的运行结果 xff1a 2 图像是16位深度的运
  • rviz和tf树报错修改

    跟着这个博主进行多机器人仿真 xff0c 一直出错 xff0c 有点崩溃了 ROS仿真笔记之 基于gazebo的ROS多机器人仿真 gwpscut的博客 CSDN博客 TF REPEATED DATA warnings ROS Answer
  • 港科大GVINS编译与运行教程

    GVINS GVINS是香港科技大学沈劭劼团队开源的基于因子图优化的GNSS 视觉 惯导紧耦合多传感器组合导航软件 GVINS是一个基于非线性优化的系统 xff0c 它将 GNSS 原始测量与视觉和惯性信息紧密融合 xff0c 以实现实时和
  • 硬件结构——(6) 软中断

    1 中断是什么 xff1f 在计算机中 xff0c 中断是 系统用来响应硬件设备请求 的一种机制 操作系统收到 硬件的中断请求后 xff0c 会打断正在执行的进程 xff0c 然后调用内核中的 中断处理程序 来响应请求 中断是 种 异步的事
  • C++将类序列化和反序列化到共享内存

    这里用模板泛化一下 template lt typename T gt int saveToShm const T amp obj key t key 61 gen shm key int shmId 61 shmget key sizeo
  • C++使用rapidjson进行类的序列化与反序列化

    目录 序列化 amp 反序列化单个对象序列化反序列化使用示例 序列化 amp 反序列化对象列表 C 43 43 中可以使用第三方库来实现将类序列化成JSON文件 xff0c 以及读取JSON文件内容反序列化为类对象 这里使用rapidJso
  • c++用vector实现定长队列

    目录 queue实现vector实现 我们可以用queue或vector实现定长队列 xff0c 但是如果我们有遍历定长队列的需求的话 xff0c 使用queue不是一个好的选择 xff0c 因为queue本身不支持直接访问元素 queue
  • c++判断文件是否存在

    可以使用C 43 43 的文件流来判断文件是否存在 以下是一个简单的函数 xff0c 可以通过文件名判断文件是否存在 xff1a span class token macro property span class token direct
  • 相机内外参数的意义

    1 内参数 xff1a 由于相机坐标系使用的是毫米制的单位 xff0c 而图像平面使用的像素为单位 内参数的作用就是在这两个坐标系之间进行线性的变化 相机光轴中心Z轴方向与像平面交点称为投影中心 xff0c 其坐标为 xff0c 其单位为像
  • C++实现读写分离的双缓冲buffer

    目录 1 双缓冲区 读写分离2 后台线程定时更新数据3 类设计完整代码cache cppcache hmain cppmakefile 读写分离的双缓冲buffer有以下好处 xff1a 提高了并发读写的效率 xff1a 在多线程环境下 x
  • 返回引用与返回值与返回std::move(obj)

    返回引用与返回值相比 返回引用与返回值相比有以下几个好处 xff1a 减少内存开销 xff1a 返回值需要在函数内部创建一个临时对象 xff0c 然后将该对象的副本返回给调用者 这个过程需要分配内存 复制数据等操作 xff0c 会增加内存开
  • error: non-member function ‘XXX::IsValid(const T&)’ cannot have cv-qualifier

    这个错误提示表明你定义的函数 IsValid 是一个非成员函数 xff0c 并且带有 const 限定符 在 C 43 43 中 xff0c 非成员函数不能带有 const 限定符 xff0c 因为它们没有隐式的 this 指针 xff0c
  • c++使用regex报错regex_error

    原本写了个同时识别IPv4和IPv6地址的C 43 43 函数 xff1a span class token macro property span class token directive hash span span class to
  • c++实现日志类(写入logfile)

    span class token macro property span class token directive hash span span class token directive keyword include span spa
  • c++中以类对象作为key用于unordered_map、map,以及std::tie技巧使用

    我有一个类 span class token keyword class span span class token class name UserRegion span span class token punctuation span
  • std::set_difference用法

    std set difference 是 C 43 43 STL 中的一个算法 xff0c 用于计算两个有序范围之间的差集 xff0c 并将结果存储到另一个有序范围中 std set difference 的函数签名如下 xff1a spa
  • __builtin_xxx指令学习【1】__builtin_expect

    builtin expect是GCC编译器提供的一个内置函数 xff0c 用于告诉编译器一个分支的执行概率 xff0c 以便编译器在生成机器码时进行优化 它的语法如下 xff1a span class token function buil