iis服务器助手广告广告
返回顶部
首页 > 资讯 > 前端开发 > JavaScript >如何理解if-else涉及到分支预测
  • 252
分享到

如何理解if-else涉及到分支预测

2024-04-02 19:04:59 252人浏览 独家记忆
摘要

这篇文章主要讲解了“如何理解if-else涉及到分支预测”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何理解if-else涉及到分支预测”吧!首先看一段经

这篇文章主要讲解了“如何理解if-else涉及到分支预测”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何理解if-else涉及到分支预测”吧!

首先看一段经典的代码,并统计它的执行时间:

// test_predict.cc #include <alGorithm> #include <ctime> #include <iOStream>  int main() {     const unsigned ARRAY_SIZE = 50000;     int data[ARRAY_SIZE];     const unsigned DATA_STRIDE = 256;      for (unsigned c = 0; c < ARRAY_SIZE; ++c) data[c] = std::rand() % DATA_STRIDE;      std::sort(data, data + ARRAY_SIZE);      {  // 测试部分         clock_t start = clock();         long long sum = 0;          for (unsigned i = 0; i < 100000; ++i) {             for (unsigned c = 0; c < ARRAY_SIZE; ++c) {                 if (data[c] >= 128) sum += data[c];             }         }          double elapsedTime = static_cast<double>(clock() - start) / CLOCKS_PER_SEC;          std::cout << elapsedTime << "\n";         std::cout << "sum = " << sum << "\n";     }     return 0; } ~/test$ g++ test_predict.cc ;./a.out 7.95312 sum = 480124300000

此程序的执行时间是7.9秒,如果把排序那一行代码注释掉,即

// std::sort(data, data + ARRAY_SIZE);

结果为:

~/test$ g++ test_predict.cc ;./a.out 24.2188 sum = 480124300000

改动后的程序执行时间变为了24秒。

其实只改动了一行代码,程序执行时间却有3倍的差距,而且看上去数组是否排序与程序执行速度貌似没什么关系,这里面其实涉及到CPU分支预测的知识点。

提到分支预测,首先要介绍一个概念:流水线。

拿理发举例,小理发店一般都是一个人工作,一个人洗剪吹一肩挑,而大理发店分工明确,洗剪吹都有特定的员工,第一个人在剪发的时候,第二个人就可以洗头了,第一个人剪发结束吹头发的时候,第二个人可以去剪发,第三个人就可以去洗头了,极大的提高了效率。

如何理解if-else涉及到分支预测

如何理解if-else涉及到分支预测

这里的洗剪吹就相当于是三级流水线,在CPU架构中也有流水线的概念,如图:

如何理解if-else涉及到分支预测

在执行指令的时候一般有以下几个过程:

  1. 鸿蒙官方战略合作共建——HarmonyOS技术社区

  2. 取指:Fetch

  3. 译指:Decode

  4. 执行:execute

  5. 回写:Write-back

流水线架构可以更好的压榨流水线上的四个员工,让他们不停的工作,使指令执行的效率更高。

再谈分支预测,举个经典的例子:

火车高速行驶的过程中遇到前方有个岔路口,假设火车内没有任何通讯手段,那火车就需要在岔路口前停下,下车询问别人应该选择哪条路走,弄清楚路线后后再重新启动火车继续行驶。高速行驶的火车慢速停下,再重新启动后加速,可以想象这个过程浪费了多少时间。

有个办法,火车在遇到岔路口前可以猜一条路线,到路口时直接选择这条路行驶,如果经过多个岔路口,每次做出选择时都能选择正确的路口行驶,这样火车一路上都不需要减速,速度自然非常快。但如果火车开过头才发现走错路了,就需要倒车回到岔路口,选择正确的路口继续行驶,速度自然下降很多。所以预测的成功率非常重要,因为预测失败的代价较高,预测成功则一帆风顺。

计算机的分支预测就如同火车行驶中遇到了岔路口,预测成功则程序的执行效率大幅提高,预测失败程序的执行效率则大幅下降。

CPU都是多级流水线架构运行,如果分支预测成功,很多指令都提前进入流水线流程中,则流水线中指令运行的非常顺畅,而如果分支预测失败,则需要清空流水线中的那些预测出来的指令,重新加载正确的指令到流水线中执行,然而现代CPU的流水线级数非常长,分支预测失败会损失10-20个左右的时钟周期,因此对于复杂的流水线,好的分支预测方法非常重要。

预测方法主要分为静态分支预测和动态分支预测:

静态分支预测:听名字就知道,该策略不依赖执行环境,编译器在编译时就已经对各个分支做好了预测。

动态分支预测:即运行时预测,CPU会根据分支被选择的历史纪录进行预测,如果最近多次都走了这个路口,那CPU做出预测时会优先考虑这个路口。

tips:这里只是简单的介绍了分支预测的方法,更多的分支预测方法资料大家可关注公众号回复分支预测关键字领取。

了解了分支预测的概念,我们回到最开始的问题,为什么同一个程序,排序和不排序的执行速度相差那么多。

因为程序中有个if条件判断,对于不排序的程序,数据散乱分布,CPU进行分支预测比较困难,预测失败的频率较高,每次失败都会浪费10-20个时钟周期,影响程序运行的效率。而对于排序后的数据,CPU根据历史记录比较好判断即将走哪个分支,大概前一半的数据都不会进入if分支,后一半的数据都会进入if分支,预测的成功率非常高,所以程序运行速度很快。

如何解决此问题?总体思路肯定是在程序中尽量减少分支的判断,方法肯定是具体问题具体分析了,对于该示例程序,这里提供两个思路削减if分支。

方法一:使用位操作:

int t = (data[c] - 128) >> 31; sum += ~t & data[c];

方法二:使用表结构:

#include <algorithm> #include <ctime> #include <iostream>  int main() {     const unsigned ARRAY_SIZE = 50000;     int data[ARRAY_SIZE];     const unsigned DATA_STRIDE = 256;      for (unsigned c = 0; c < ARRAY_SIZE; ++c) data[c] = std::rand() % DATA_STRIDE;      int lookup[DATA_STRIDE];     for (unsigned c = 0; c < DATA_STRIDE; ++c) {         lookup[c] = (c >= 128) ? c : 0;     }      std::sort(data, data + ARRAY_SIZE);      {  // 测试部分         clock_t start = clock();         long long sum = 0;          for (unsigned i = 0; i < 100000; ++i) {             for (unsigned c = 0; c < ARRAY_SIZE; ++c) {                 // if (data[c] >= 128) sum += data[c];                 sum += lookup[data[c]];             }         }          double elapsedTime = static_cast<double>(clock() - start) / CLOCKS_PER_SEC;         std::cout << elapsedTime << "\n";         std::cout << "sum = " << sum << "\n";     }     return 0; }

其实linux中有一些工具可以检测出分支预测成功的次数,有valgrind和perf,使用方式如图:

如何理解if-else涉及到分支预测

感谢各位的阅读,以上就是“如何理解if-else涉及到分支预测”的内容了,经过本文的学习后,相信大家对如何理解if-else涉及到分支预测这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

--结束END--

本文标题: 如何理解if-else涉及到分支预测

本文链接: http://www.lsjlt.com/news/83943.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 如何理解if-else涉及到分支预测
    这篇文章主要讲解了“如何理解if-else涉及到分支预测”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何理解if-else涉及到分支预测”吧!首先看一段经...
    99+
    2024-04-02
  • 如何理解用户行为的分析都涉及到的方面
    本篇内容主要讲解“如何理解用户行为的分析都涉及到的方面”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何理解用户行为的分析都涉及到的方面”吧!  我们经常都会在讲互联网产品的数据运营,而数据运营...
    99+
    2023-06-10
  • 如何理解If-Else是贫瘠的多态性问题
    这篇文章主要讲解了“如何理解If-Else是贫瘠的多态性问题”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何理解If-Else是贫瘠的多态性问题”吧!笔者...
    99+
    2024-04-02
  • 如何理解JavaScript预解析及对象
    本篇文章为大家展示了如何理解JavaScript预解析及对象,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。一、预解析1、变量预解析和函数预解析JavaScript 代码是由浏览器中的 JavaScr...
    99+
    2023-06-25
  • Python中如何实现支持向量机数据分类和回归预测
    这篇文章主要为大家展示了“Python中如何实现支持向量机数据分类和回归预测”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Python中如何实现支持向量机数据分类和回归预测”这篇文章吧。支持向量...
    99+
    2023-06-26
  • python神经网络VGG16模型复现及其如何预测详解
    目录什么是VGG16模型VGG网络部分实现代码图片预测学一些比较知名的模型对身体有好处噢! 什么是VGG16模型 VGG是由Simonyan 和Zisserman在文献《Very D...
    99+
    2024-04-02
  • gitlab创建完分支在D盘找不到了如何解决
    这篇文章主要介绍“gitlab创建完分支在D盘找不到了如何解决”,在日常操作中,相信很多人在gitlab创建完分支在D盘找不到了如何解决问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”gitlab创建完分支在D...
    99+
    2023-07-05
  • 如何使用Python中的数据分析库处理和预测时间序列数据
    如何使用Python中的数据分析库处理和预测时间序列数据时间序列数据是指按时间顺序排列的数据,其特点是具有时间上的相关性和趋势性。在许多领域中,时间序列数据分析起着重要的作用,如股市预测、天气预报、销售预测等。Python中有许多强大的数据...
    99+
    2023-10-22
    Python 时间序列数据 数据分析库
  • 电脑影子系统检测到动态分区无法安装如何解决
    这篇文章主要介绍“电脑影子系统检测到动态分区无法安装如何解决”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“电脑影子系统检测到动态分区无法安装如何解决”文章能帮助大家解决问题。解决方法如果当前的电脑上...
    99+
    2023-07-01
  • 如何理解Oracle 的“HA”和“LB”及怎样用脚本测试负载均衡
    本篇文章为大家展示了如何理解Oracle 的“HA”和“LB”及怎样用脚本测试负载均衡,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。概述今天主要介绍一下ORACLE...
    99+
    2024-04-02
  • 如何理解Mycat分片的限制和问题以及分片的原则
    如何理解Mycat分片的限制和问题以及分片的原则,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。 分片的限制和问...
    99+
    2024-04-02
  • 如何理解Fedora Core 6支持的特定系统文件及各种操作方法
    如何理解Fedora Core 6支持的特定系统文件及各种操作方法,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。Fedora Core系统在国内得到了用户充分的...
    99+
    2023-06-16
  • java分布式面试接口如何保证幂等及概念理解
    目录引言1、幂等的概念问题分析:事后问题分析:关于这个接口的幂等设计深入分析:2、工作中常见的幂等设计场景3、幂等接口常见设计方案总结引言 稳定性设计第一篇:这一小节开始讲设计系统稳...
    99+
    2024-04-02
  • 分布式监控系统之如何理解Zabbix主动、被动及web监控
    本篇内容主要讲解“分布式监控系统之如何理解Zabbix主动、被动及web监控”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“分布式监控系统之如何理解Zabbix主...
    99+
    2024-04-02
  • C#开发中如何处理分布式事务和消息传递问题及解决方法
    C#开发中如何处理分布式事务和消息传递问题及解决方法在分布式系统中,分布式事务和消息传递是常见的问题。分布式事务指的是涉及多个数据库或服务的事务,而消息传递则指的是系统中不同组件之间的异步通信。本文将介绍在C#开发中如何处理这些问题,并提供...
    99+
    2023-10-22
    分布式 传递 处理 分布式事务处理:事务 消息传递问题:消息
  • C#中如何使用异步编程模型和并发编程处理任务分发及解决方法
    C#中如何使用异步编程模型和并发编程处理任务分发及解决方法引言:在现代的软件开发中,我们经常面临处理大量任务的情况,而这些任务可能是独立的,互不干扰的。为了提高程序的性能和效率,我们希望能够并发地处理这些任务,并且在每个任务完成时能够得到相...
    99+
    2023-10-22
    并发编程 异步编程 任务分发
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作