为什么处理一个排好序的数组比未排序的数组要快?
这是stack overflow上一个非常火热的问题:
![](/assets/blank.gif)
为什么对数组排序能提高执行效率?先看下面的代码,执行分为:
生成随机数放入数组
对数组进行排序
对数组中的数字进行累加
publicclassMain {publicstaticvoidmain(String[] args){// 生成随机数int arraySize = 32768;int data[] = newint[arraySize];Random rnd = new Random(0);for (int c = 0; c < arraySize; ++c)data[c] = rnd.nextInt() % 256;// 排序Arrays.sort(data);// 累加,测试执行时间long start = System.nanoTime();long sum = 0;for (int i = 0; i < 100000; ++i) {for (int c = 0; c < arraySize; ++c) {if (data[c] >= 128)sum += data[c];}}System.out.println((System.nanoTime() - start) / 1000000000.0);System.out.println("sum = " + sum);}
}
排序后的执行时间:2.2350021s 未排序后的执行时间:6.385857s
可以发现:排序后的执行时间是未排序的执行时间的3倍。
为什么会这样,这就跟分支预测有关系,什么是分支预测呢?
计算机在执行某一条指令的过程中,会分为四个步骤:
![](/assets/blank.gif)
每个步骤会有对应的电路组件负责。
假设现在有一段程序对应的计算机指令为:
![](/assets/blank.gif)
那么计算机应该先执行指令1,然后根据指令1的结果看接下来应该执行哪条指令,假设接下来要执行的就是指令2,那指令流水线会是下图吗?
![](/assets/blank.gif)
假设每个步骤要1毫秒,那执行完这两条指令就需要8毫秒,但是前面说过,指令的四个步骤是由特定的组件来执行的,所以其实可以这么执行:
![](/assets/blank.gif)
在解码指令1的过程中,就可以读取指令2了,这样执行完两条指令只需要5毫秒,如果后续指令也按这个节奏执行,那么效率提升会很大,比如串行执行3条指令需要3*4=12毫秒,而并行执行3条指令只需要6毫秒,快了一倍了。
那这个跟分支预测有什么关系呢?
我们在来看
![](/assets/blank.gif)
假如指令2是一条判断指令,根据判断结果,要么执行指令3,要么执行指令4。
如果不对判断结果进行预测,那么就只能等指令2执行完之后才知道接下来要执行哪条指令,那指令流水线就是下面这样:
![](/assets/blank.gif)
执行这三条指令要9毫秒。
但是,如果在执行指令2之前,我们就能预测出指令2的判断结果,假如预测的是指令3,那么指令流水线就可以这样:
![](/assets/blank.gif)
相当于在解码指令2的时候,就同时去读取指令3,如果执行完指令2后,发现判断结果和预测的结果是一致的,那么就可以直接把指令3的结果写回了,这样就大大提高效率,执行这3条指令只需要6毫秒。
当然如果执行完指令2后,发现预测错了,那么就不能把指令3的结果写回了,而是得读取并执行正确的指令。
以上就是分支预测,简单总结一下就是,计算机会对分支,比如判断指令的结果进行预测,从而提前去做一些事情,而不是等判断结果出来后才去做事情。
回到上面的Java代码:
for (int c = 0; c < arraySize; ++c) {if (data[c] >= 128)sum += data[c];
}
if语句就相当于是一个判断指令,根据判断结果就会有两个分支:
要么进行累加
要么取数组中的下一个数字。
所以,当执行if语句时,计算机就可以进行预测:
比如预测当前判断的数字是大于128的,那么就可以在判断结果没有出来之前提前进行累加
或者预测当前判断的数字是小于128的,那么就可以在判断结果没有出来之前提前取下一个数字
只要预测对了,就能提高执行效率,所以,我们要做的就是尽可能让计算机能预测准确,这就是数组排序的作用。
比如计算机在执行指令过程中,发现连续10个数字都是大于128的,那么就可以预测接下来的一个数字也是大于128的,所以只要数组是排好序的,那么这个预测就是正确的,从而也就提高了执行效率。
以上,就是分支预测,不知道大家看明白没...
为什么处理一个排好序的数组比未排序的数组要快?相关推荐
- /*已知一个排好序的数组,按数组原排序方式插入一个数据*/
/*已知一个排好序的数组,按数组原排序方式插入一个数据*/std::vector<int>shuzu = {1,2,3,4,5,7,8,9};int x = 0, caru = 6;std ...
- C语言-数组和指针-11(已有一个排号序的数组,要求输入一个数后,按原来的排序规律将它插入数组中)
题目: 已有一个排号序的数组,要求输入一个数后,按原来的排序规律将它插入数组中 源代码: #include <stdio.h> #define ROW 7 int main(){int a ...
- 给定一个未排序的数组,求如果数组排序之后,相邻数的最大差值。
给定一个未排序的数组,求如果数组排序之后,相邻数的最大差值.要求时间复杂度为O(n),且要求不能用非基于比较的排序. 首先,这个问题明显限制了不能使用直接排序的方式求解.因为基于比较的排序时间复杂度最 ...
- 左神算法:未排序正数数组中累加和为给定值的最长子数组长度(Java版)
本题来自左神<程序员代码面试指南>"未排序正数数组中累加和为给定值的最长子数组长度"题目. 题目 牛客OJ:未排序数组中累加和为给定值的最长子数组长度 题解 本文提供的 ...
- 已有一个排好序的数组,今输入一个数,要求按原来排序的规律将它插入数组中
先来看看以下代码,这是其他博友的思路,这代码看似没有问题,其实存在很大的BUG,当插入的目标比str[0]更小的时候就会出错.相信仔细的人就很容易发现问题. #include<stdio.h&g ...
- 打乱一个排好序的列表(Python)
目录 题目描述 输出描述 代码 代码走读 传送门 测试用例 题目描述 随机生成一个长度10的整型列表,元素随机分布在1--100内.按从小到大的顺序排序列表并打印,然后输出顺序打乱后的列表. 输出描述 ...
- php 数组根据字母排序,php 数组 按拼音首字母 排序 并分组
PHP 数组 按照拼音 首字母 排序 并排序: 需要排序的数组 格式: $list = [ [ 'name' => '张三', 'py' => 'zhnagsan' ], [ 'name' ...
- 给定一个排好序的数组,随机输入一个数,按原顺序插入
//本例中是已经给定了一个数组,读者可以根据自身需求,改成手动输入或者其他输入方式 #include<stdio.h> int main() { int a[9+1] = {1,3,4,6 ...
- 已经有一个排好序的数组,要求输入一个数后,按原来排序的规律将它插入数组中。
#include using namespace std; int main() { int a[6] = {1,2,7,8,9,12},num,n=0;//n是用来记录num要插入的位置 cin & ...
最新文章
- jq定制上传按钮,选择文件就上传
- 上海找python工作容易吗_Python程序员去上海工作有多难?
- activiti web流程设计器 整合视频 教程 SSM和独立部署的方式
- AC Again hdoj 1582 搜索
- Js中Number对象
- Perl 字符串操作
- 背景图宽度自适应及背景图合并的CSS思想
- 游戏设计艺术 第2版 (Jesse Schell 著)
- python通过身份证或出生日期获取年龄
- android 动画 translate,Android动画之TranslateAnimation使用
- 【Django】第一课 基于Django图书借阅管理网站平台
- 和自然语言处理有关的英语_自然语言处理对非英语语言的重要性
- 流量回放框架jvm-sandbox-repeater的实践
- 华为扩大内存代码_华为畅享6内存扩大拨号代码 | 手游网游页游攻略大全
- Java是什么?Java的特点有哪些?
- Java安卓如何添加悬浮窗_Android悬浮窗的实现
- 天然和合成石墨的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
- Crystals Kyber密码算法解读(一)
- golang集锦——如此优雅-吴冬冬-专题视频课程
- java实现多线程爬取表情包
热门文章
- 【五音疗疾】百病始于气而止于音
- CompareNoCase与Compare
- 一些前端开发大牛【持续更新】
- 不能忘了看XUL Tutorial。
- python换硬币_Python的硬币兑换动态编程实现记录,CoinChange,最少,组合,python,规划
- 战略财务、共享财务、业务财务的思考-来自一个财务业务的分享
- Linux + 香橙派 + V4L2 + http 实现远程监控摄像头在网页端显示
- src\loadsave.cpp:738: error: (-215:Assertion failed) !_img.empty() in function ‘cv::imwrite‘
- python图片转化为素描图
- (02)Cartographer源码无死角解析-(48) 2D点云扫描匹配→扫描匹配基本原理讲解,代码总体框架梳理AddAccumulatedRangeData()