从汇编层看64位程序运行——likely提示编译器的优化案例和底层实现分析

我们在 《Modern C++——使用分支预测优化代码性能》一文中介绍了likely提示编译器进行编译优化,但是我们又讲了最终优化不是对分支顺序的调换,那么它到底做了什么样的优化,让整体性能提升20%呢?

代码

我们先回顾下代码

#include <chrono>
#include <cmath>
#include <iomanip>
#include <iostream>
#include <random>
#include <functional>
 
namespace with_attributes {
    constexpr double pow(double x, long long n) noexcept {
        if (n <= 0) [[unlikely]]
            return 1;
        else [[likely]]
            return x * pow(x, n - 1);
    }
} // namespace with_attributes
 
namespace no_attributes {
    constexpr double pow(double x, long long n) noexcept {
        if (n <= 0)
            return 1;
        else
            return x * pow(x, n - 1);
    }
} // namespace no_attributes

double calc(double x, std::function<double(double, long long)> f) noexcept {
    constexpr long long precision{16LL};
    double y{};
    for (auto n{0LL}; n < precision; n += 2LL)
        y += f(x, n);
    return y;
}

double gen_random() noexcept {
    static std::random_device rd;
    static std::mt19937 gen(rd());
    static std::uniform_real_distribution<double> dis(-1.0, 1.0);
    return dis(gen);
}
 
volatile double sink{}; // ensures a side effect
 
int main() {
    auto benchmark = [](auto fun, auto rem)
    {
        const auto start = std::chrono::high_resolution_clock::now();
        for (auto y{1ULL}; y != 500'000'000ULL; ++y)
            sink = calc(gen_random(), fun);
        const std::chrono::duration<double> diff =
            std::chrono::high_resolution_clock::now() - start;
        std::cout << "Time: " << std::fixed << std::setprecision(6) << diff.count()
                  << " sec " << rem << std::endl; 
    };
 
    benchmark(with_attributes::pow, "(with attributes)");
    benchmark(no_attributes::pow, "(without attributes)");
    benchmark(with_attributes::pow, "(with attributes)");
    benchmark(no_attributes::pow, "(without attributes)");
    benchmark(with_attributes::pow, "(with attributes)");
    benchmark(no_attributes::pow, "(without attributes)");
}

以及执行效果
在这里插入图片描述

分析

现在我们开始探究性能提升的本质原因。

常言道:代码之前了无秘密。但是对于C++的程序,这个“代码”指的是汇编代码。所以我们需要查看with_attributes::pow和no_attributes::pow的底层实现。

with_attributes::pow

在这里插入图片描述

no_attributes::pow

在这里插入图片描述

分析

我们看到with_attributes::pow和no_attributes::pow在汇编层的实现结构是类似的,但是它们并没有遵从C++代码的结构。因为完全按照C++代码结构进行编译,其结构应该类似于

test   %rdi,%rdi
jle XXXXX_RET_ADDRESS
sub    $0x1,%rdi
movsd  %xmm0,0x8(%rsp)
call pow
……

由于我们开启了o3等级编译优化,所以编译器对with_attributes::pow和no_attributes::pow都进行了优化。

我们分析no_attributes::pow的优化方案:

  • test %rdi,%rdi检测n
  • jle 0x555555555c20 <_ZN13no_attributes3powEdx+112>如果n小于等于0,则跳转到+112位置,即返回1。
  • movapd %xmm0,%xmm1如果n大于0,则将x值放入xmm1寄存器。
  • cmp $0x1,%rdi对比n是否等于1。
  • je 0x555555555c1c <_ZN13no_attributes3powEdx+108>如果n是1,则运行+108位置,即返回x的值。因为pow(x,1)=x* pow(x,0)= x。
  • cmp $0x2,%rdi对比x是否等于2。
  • je 0x555555555c18 <_ZN13no_attributes3powEdx+104>如果n是2,则运行+104位置。它会执行一次x*x(mulsd %xmm1,%xmm0)。这是因为pow(x,2)=x * pow(x,1)= x * x * pow(x, 0) = x * x * 1 = x * x。

后面逻辑以此类推。
在这里插入图片描述

但是当n大于等于5时,逻辑会发生变动:它会递归调用pow(x, n-5),取到结果后再与x进行5次连乘。
在这里插入图片描述

可以发现,这段代码的优化方案是:使用直接操作替代递归调用

再看likely优化后的代码,可以发现它们的结构是一致的。那么为什么likely为什么比没标记过的代码快20%呢?

这是因为likely版本采用了"x的8连乘",这比未标记版本的"x的5连乘"要减少更多的递归调用。
在这里插入图片描述
所以,总结下:本案例中,likely标记版提示编译器做了深度更深的优化,采用直接操作,减少递归调用。

linux内核中的likely和unlikely.pdf
11-05
使用 likely() 和 unlikely() 宏可以帮助编译器更好地优化代码,但是我们需要注意的是,过度使用这些宏可能会导致代码变得难以阅读和维护。 在 GCC 的版本较低时 (_GNUC_MINOR__ ),__builtin_expect 直接返回 EXP...
likely.js:一个为node.js设计的用于协作过滤和推荐引擎的javascript库
05-18
Likely.js是用于协作过滤和提出建议的库。 它采用输入训练矩阵,其中行代表用户,列代表项目。 矩阵中的每个条目都是用户对该项目的评价。 训练后,您可以检索任何给定用户的推荐项目及其估计评分的列表。 例如,您...
Simple TCP.rar_-baijiahao_likely8dt_peace6y8_simpletcp_添加simple
09-24
标题中的“Simple TCP.rar”可能是指一个包含了简单TCP(Transmission Control Protocol)通信示例或工具的压缩文件。...通过分析和修改这个简单的实现,可以深入理解TCP协议的细节,并提升网络编程技能。
基于微信小程序的校园约拍设计与实现ssm毕业论文.doc
08-08
To ensure data security, the application likely incorporates encryption mechanisms for sensitive information like passwords and personal details. It may also implement access control measures to ...
使用 Python 和 JavaScript 的基于 Web 的 AI 助手应用程序.pdf
04-14
The document titled “使用 Python 和 JavaScript 的基于 Web 的 AI 助手应用程序” outlines the development of a web-based AI assistant that leverages both Python and JavaScript programming languages....
速通汇编(七)BX、SI、DI寄存器,BP寄存器,直接寻址和间接寻址
这个博主不懒,但Ta什么也没写~(私信互关24小时必回)
09-19 1628
(1)[idata]用一个常量来表示地址,可用于直接定位一个内存单元(2)[bx]用一个变量来表示内存地址,可用于间接定位一个内存单元(3)[bx+idata]用一个变量和常量表示地址,可在一个起始地址的基础上用变量间接定位一个内存单元(4)[bx+si/di]用两个变量表示地址(5)[bx+si/di+idata]用两个变量和一个常量表示地址(注:本图取自《王爽汇编》P165处表8.2,不商用,仅供学习参考。下图表格中第4列【常用格式举例】中出现的一些特殊表示形式。
C++】 —— string的使用
LH__1314的博客
09-16 1481
string类虽然不在STL的容器中,但string类十分重要,string类是对字符串的存储和相关操作。
标准C++(二)
m0_63127040的博客
09-18 862
在C语言中定义的全局变量、函数、结构、联合、枚举、枚举值、宏都在全局作用域下,所以当项目比较庞大时,非常容易造成命名冲突(以模块名作前缀、后缀),所以C++中选择把全局作用域进行拆分成子作用域进行管理,这些子作用域就是作名字空间。把抽象结果(利用面向对象的思维模式,思考、观察出的结果),使用用C++的语法封装出一种类似结构的自定义数据类型(复合数据类型)。使用设计好的类(结构)这种数据类型,定义出的类变量在面向对象编程语言中被称为对象(结构变量),创建类对象的行为也被称为实例化对象。int id;
C++_map_set详解
2302_77644537的博客
09-16 1064
set是按照一定次序存储元素的容器在set中,元素的value也标识它(value就是key,类型为T),并且每个value必须是唯一的。set中的元素不能在容器中修改(元素总是const),但是可以从容器中插入或删除它们。在内部,set中的元素总是按照其内部比较对象(类型比较)所指示的特定严格的排序准则(默认是小于)进行排序。set在底层是用二叉搜索树(红黑树)实现的。map是关联容器,它按照特定的次序(按照key来比较)存储由键值key和值value组合而成的元素。
TMS Scripter Crack TMS Scripter is a Delphi C++ Builder
q2315702359的博客
09-19 1039
  The integrated development environment or the IDE allows the users in process of creating script jobs during the runtime with the help of multiple cross-language scripts such as de Pascal and the Basics.  It has support for the cross-utilization of the s
C++ 解析 RDP 协议
最新发布
道亦无名
09-22 164
远程桌面协议(Remote Desktop Protocol, RDP)是微软开发的一种网络通信协议,用于提供远程桌面会话服务。它允许用户通过网络连接至远程计算机,并像使用本地计算机一样操作远程系统。本文档将详细探讨在C++环境中如何解析RDP协议,涵盖协议次解析、连接过程管理、数据加密解密、功能数据处理、错误与异常处理以及协议版本适配等方面。
在typescript浏览器端中调用C++编写的函数,WebAssembly传递指针类型的参数,以及处理指针类型的返回值。
Xeon_CC的博客
09-17 459
最后是返回一个C++结构体指针,在TypeScript中通过DataView来获取内存中的地址偏移量来取得结构体中的数据,因为em++编译器是以32位来编译.cpp文件的,所以指针占4个字节。DataResult结构体第一个属性dArr是一个指针,那么就是地址偏移量0,然后以32位无符号整型取得dArr指针,通过这个指针去读取wasm中memoryBuffer中的数据,就可以得到dArr属性对应的值了。同理,通过地址偏移量+4来得到propCount属性,以32位整数读取数据即可。
【C语言】文件操作
A Charmer 的博客
09-19 1368
本文详细介绍了C语言中文件的读写操作,包括文件指针的概念、如何使用fopen/fclose进行文件打开和关闭,以及常用的文件操作函数如fgetc/fputc、fread/fwrite等。通过实例演示了如何在二进制文件中读取和写入数据,强调了缓冲区管理和刷新的重要性。
C++之模版的进阶
2301_81857941的博客
09-22 599
一个程序由若干个源文件共同实现,而每一个源文件单独编译生成目标文件,最后将所有目标文件链接起来形成单一的可执行文件的过程称为分离编译模式。【优点】1.增强了代码的灵活性2.模版复用了代码,节省资源【缺陷】1.模版会导致代码膨胀问题2.出现模版错误时,错误原因难以定位。
【CMake】使用CMake在Visual Stdudio构建一个最简单的项目
Antonio915的博客
09-16 796
首先,确保在VisualStudio上安装了C++桌面开发,如果没有安装,打开VisualStudioInstaller就可以修改了。在想要创建项目的文件夹下,创建这两个文件:其中,CMakeLists的内容如下:相应的名字可以自己修改。
57.【C语言】字符函数和字符串函数(strerror函数)
2401_85828611的博客
09-18 458
翻译:函数错误码解释errnum的值,产生一条描述错误情况的信息的字符串,就像被库函数设置为errno一样这个返回的指针指向一个静态的已分配的且不能被程序修改的字符串,进一步调用此函数可能会覆盖内容(不需要特定的库的实施,避免数据竞争)strerror产生的错误信息的字符串可能特定于每个系统和库实现errnum:错误码一个指向用于描述错误码的错误信息字符串的指针简明扼要:strerror的作用:把错误码翻译成错误信息。
C++如何进阶? -- 整理一些学习资料
csdnzzt的博客
09-22 171
在学习完C++最基础的知识后,需要对C++有更近一步的认知。看门见山,首先贴出学习资料:侯捷老师的这几个视频是每个学习C++的人都应该仔细看几遍下来的,只看一遍是绝对记不住的具体来说必看的两本书,或者说,必看的两本书和一章节是STL源码剖析、Effective C++、深度探索C++对象模型第三章(虚函数)。而选看的两本书: More Effective C++、深度探索C++第三章以外的部分。
C++速通LeetCode中等第7题-和为K的子数组(巧用前缀和)
lyx的博客
09-19 268
子数组和问题可用前缀和解决,前缀和就是头元素到当前序号子数组元素的和
C++核心编程和桌面应用开发 第四天(构造/析构函数 浅拷贝/深拷贝 初始化列表 explicit)
m0_53349772的博客
09-17 238
函数名(const 函数名 &)①用已创建好的对象初始化新对象。②值传递的方式给函数参数传值。③以值的方式,返回局部对象。
详解Linux内核中likely()和unlikely()优化技巧
在GNU C编程中,`likely()`和`unlikely()`这两个关键字是编译器优化工具的一种高级用法,用于向编译器传达代码中的条件概率信息。它们在Linux内核开发中特别常见,旨在提高代码性能并辅助编译器进行更智能的指令调度...
写文章

热门文章

  • 使用WinHttp接口实现HTTP协议Get、Post和文件上传功能 57692
  • brpc介绍、编译与使用 47512
  • WMI技术介绍和应用——WMI概述 42904
  • 一种精确从文本中提取URL的思路及实现 42152
  • 浅析GPU计算——cuda编程 40504

分类专栏

  • 闯关leetcode 15篇
  • 0基础学习PyTorch 1篇
  • Robot Operating System 79篇
  • Windows Subsystem for Linux 6篇
  • Modern C++ 9篇
  • C++和Python混合编程 2篇
  • 从汇编层看64位程序运行 15篇
  • Java 9篇
  • 0基础学习区块链技术 6篇
  • IT项目研发过程中的利器 26篇
  • 0基础学习Mybatis系列数据库操作框架 12篇
  • Websocket在Java中的实践 7篇
  • Java版Flink使用指南 9篇
  • RabbitMQ实践 20篇
  • Mysql使用中的性能优化 5篇
  • Opentelemetry 17篇
  • PE文件和COFF文件格式分析 11篇
  • kubernetes 35篇
  • WMI技术介绍和应用 24篇
  • 0基础学习PyFlink 20篇
  • AWS实践 15篇
  • DllMain中不当操作导致死锁问题的分析 9篇
  • 开源项目解析、实现及使用 19篇
  • 网络编程模型的分析、实现和对比 6篇
  • GTest使用方法和源码解析 11篇
  • windows 1篇
  • scipy 4篇
  • numpy 13篇
  • Golang 11篇
  • clickhouse 6篇
  • C++拾趣 16篇
  • IE控件技术研究和应用 7篇
  • Apache服务搭建和插件实现 7篇
  • libev源码解析 7篇
  • 安全 11篇
  • 网络通信 6篇
  • 沙箱 7篇
  • 内嵌及定制Lua引擎技术 3篇
  • 反汇编 5篇
  • 开源项目 17篇
  • C++ 36篇
  • 界面库 3篇
  • python 13篇
  • 疑难杂症 21篇
  • PHP调试器 7篇
  • Redis 10篇
  • GPU计算 3篇
  • zookeeper 3篇
  • bug诞生记 6篇
  • ffmpeg和音频视频处理

最新评论

  • Robot Operating System——带有时间戳和坐标系信息的线速度和角速度

    CSDN-Ada助手: 恭喜你这篇博客进入【CSDN每天值得看】榜单,全部的排名请看 https://bbs.csdn.net/topics/619318263。

  • brpc介绍、编译与使用

    breaksoftware: 以官方为准。这文章已经很老了。

  • brpc介绍、编译与使用

    大袖揽清风。: 这个zlib 为什么brpc官方里面没有说要下载啊 这是什么东西呢?

  • Google Test(GTest)使用方法和源码解析——概况

    qspingv: HAO

  • Robot Operating System——深度解析监控Parameters修改的底层实现

    ha_lydms: 博主文章写的十分细致,结构严谨。感谢博主分享,期待博主持续输出好文,同时也希望可以来我博客指导我一番。

最新文章

  • 闯关leetcode——67. Add Binary
  • 0基础学习PyTorch——最小Demo
  • 闯关leetcode——66. Plus One
2024
09月 37篇
08月 60篇
07月 48篇
06月 35篇
05月 10篇
04月 31篇
03月 5篇
02月 2篇
01月 29篇
2023年78篇
2022年2篇
2021年1篇
2020年5篇
2019年6篇
2018年45篇
2017年22篇
2016年46篇
2015年12篇
2014年17篇
2013年32篇
2012年45篇
2011年7篇
2009年1篇

目录

目录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

breaksoftware

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或 充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值

玻璃钢生产厂家辽宁商场主题创意商业美陈思路芒市玻璃钢雕塑哪家好赣州特色玻璃钢雕塑优势三明玻璃钢人物雕塑厂家广西玻璃钢几何雕塑贵州玻璃钢雕塑设计北京大型商场创意商业美陈步骤玻璃钢人物雕塑口碑好温州玻璃钢雕塑摆件销售云南公园玻璃钢雕塑批发河南玻璃钢金属雕塑介绍江西玻璃钢雕塑多少钱上海超市商场美陈销售企业商场中空吊装灯饰美陈上海升美玻璃钢雕塑商场橱窗秋季美陈清迈商场美陈呈贡玻璃钢雕塑设计咨询北京常见商场美陈供应封开玻璃钢抽象雕塑批发南京玻璃钢卡通雕塑厂家推广常州玻璃钢人物雕塑厂家供应仿铜西式玻璃钢雕塑多少钱福建商场美陈制造雨花商场春季美陈佛山玻璃钢人物雕塑湖南小区玻璃钢雕塑生产厂家运城玻璃钢人物雕塑定制玻璃钢雕塑用什么牌子好崇左玻璃钢雕塑生产厂家香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万

玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化