这是stack overflow上一个非常火热的问题:

为什么对数组排序能提高执行效率?先看下面的代码,执行分为:

  1. 生成随机数放入数组

  1. 对数组进行排序

  1. 对数组中的数字进行累加

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倍。

为什么会这样,这就跟分支预测有关系,什么是分支预测呢?

计算机在执行某一条指令的过程中,会分为四个步骤:

每个步骤会有对应的电路组件负责。

假设现在有一段程序对应的计算机指令为:

那么计算机应该先执行指令1,然后根据指令1的结果看接下来应该执行哪条指令,假设接下来要执行的就是指令2,那指令流水线会是下图吗?

假设每个步骤要1毫秒,那执行完这两条指令就需要8毫秒,但是前面说过,指令的四个步骤是由特定的组件来执行的,所以其实可以这么执行:

在解码指令1的过程中,就可以读取指令2了,这样执行完两条指令只需要5毫秒,如果后续指令也按这个节奏执行,那么效率提升会很大,比如串行执行3条指令需要3*4=12毫秒,而并行执行3条指令只需要6毫秒,快了一倍了。

那这个跟分支预测有什么关系呢?

我们在来看

假如指令2是一条判断指令,根据判断结果,要么执行指令3,要么执行指令4。

如果不对判断结果进行预测,那么就只能等指令2执行完之后才知道接下来要执行哪条指令,那指令流水线就是下面这样:

执行这三条指令要9毫秒。

但是,如果在执行指令2之前,我们就能预测出指令2的判断结果,假如预测的是指令3,那么指令流水线就可以这样:

相当于在解码指令2的时候,就同时去读取指令3,如果执行完指令2后,发现判断结果和预测的结果是一致的,那么就可以直接把指令3的结果写回了,这样就大大提高效率,执行这3条指令只需要6毫秒。

当然如果执行完指令2后,发现预测错了,那么就不能把指令3的结果写回了,而是得读取并执行正确的指令。

以上就是分支预测,简单总结一下就是,计算机会对分支,比如判断指令的结果进行预测,从而提前去做一些事情,而不是等判断结果出来后才去做事情。

回到上面的Java代码:

for (int c = 0; c < arraySize; ++c) {if (data[c] >= 128)sum += data[c];
}

if语句就相当于是一个判断指令,根据判断结果就会有两个分支:

  1. 要么进行累加

  1. 要么取数组中的下一个数字。

所以,当执行if语句时,计算机就可以进行预测:

  1. 比如预测当前判断的数字是大于128的,那么就可以在判断结果没有出来之前提前进行累加

  1. 或者预测当前判断的数字是小于128的,那么就可以在判断结果没有出来之前提前取下一个数字

只要预测对了,就能提高执行效率,所以,我们要做的就是尽可能让计算机能预测准确,这就是数组排序的作用。

比如计算机在执行指令过程中,发现连续10个数字都是大于128的,那么就可以预测接下来的一个数字也是大于128的,所以只要数组是排好序的,那么这个预测就是正确的,从而也就提高了执行效率。

以上,就是分支预测,不知道大家看明白没...

为什么处理一个排好序的数组比未排序的数组要快?相关推荐

  1. /*已知一个排好序的数组,按数组原排序方式插入一个数据*/

    /*已知一个排好序的数组,按数组原排序方式插入一个数据*/std::vector<int>shuzu = {1,2,3,4,5,7,8,9};int x = 0, caru = 6;std ...

  2. C语言-数组和指针-11(已有一个排号序的数组,要求输入一个数后,按原来的排序规律将它插入数组中)

    题目: 已有一个排号序的数组,要求输入一个数后,按原来的排序规律将它插入数组中 源代码: #include <stdio.h> #define ROW 7 int main(){int a ...

  3. 给定一个未排序的数组,求如果数组排序之后,相邻数的最大差值。

    给定一个未排序的数组,求如果数组排序之后,相邻数的最大差值.要求时间复杂度为O(n),且要求不能用非基于比较的排序. 首先,这个问题明显限制了不能使用直接排序的方式求解.因为基于比较的排序时间复杂度最 ...

  4. 左神算法:未排序正数数组中累加和为给定值的最长子数组长度(Java版)

    本题来自左神<程序员代码面试指南>"未排序正数数组中累加和为给定值的最长子数组长度"题目. 题目 牛客OJ:未排序数组中累加和为给定值的最长子数组长度 题解 本文提供的 ...

  5. 已有一个排好序的数组,今输入一个数,要求按原来排序的规律将它插入数组中

    先来看看以下代码,这是其他博友的思路,这代码看似没有问题,其实存在很大的BUG,当插入的目标比str[0]更小的时候就会出错.相信仔细的人就很容易发现问题. #include<stdio.h&g ...

  6. 打乱一个排好序的列表(Python)

    目录 题目描述 输出描述 代码 代码走读 传送门 测试用例 题目描述 随机生成一个长度10的整型列表,元素随机分布在1--100内.按从小到大的顺序排序列表并打印,然后输出顺序打乱后的列表. 输出描述 ...

  7. php 数组根据字母排序,php 数组 按拼音首字母 排序 并分组

    PHP 数组 按照拼音 首字母 排序 并排序: 需要排序的数组 格式: $list = [ [ 'name' => '张三', 'py' => 'zhnagsan' ], [ 'name' ...

  8. 给定一个排好序的数组,随机输入一个数,按原顺序插入

    //本例中是已经给定了一个数组,读者可以根据自身需求,改成手动输入或者其他输入方式 #include<stdio.h> int main() { int a[9+1] = {1,3,4,6 ...

  9. 已经有一个排好序的数组,要求输入一个数后,按原来排序的规律将它插入数组中。

    #include using namespace std; int main() { int a[6] = {1,2,7,8,9,12},num,n=0;//n是用来记录num要插入的位置 cin & ...

最新文章

  1. jq定制上传按钮,选择文件就上传
  2. 上海找python工作容易吗_Python程序员去上海工作有多难?
  3. activiti web流程设计器 整合视频 教程 SSM和独立部署的方式
  4. AC Again hdoj 1582 搜索
  5. Js中Number对象
  6. Perl 字符串操作
  7. 背景图宽度自适应及背景图合并的CSS思想
  8. 游戏设计艺术 第2版 (Jesse Schell 著)
  9. python通过身份证或出生日期获取年龄
  10. android 动画 translate,Android动画之TranslateAnimation使用
  11. 【Django】第一课 基于Django图书借阅管理网站平台
  12. 和自然语言处理有关的英语_自然语言处理对非英语语言的重要性
  13. 流量回放框架jvm-sandbox-repeater的实践
  14. 华为扩大内存代码_华为畅享6内存扩大拨号代码 | 手游网游页游攻略大全
  15. Java是什么?Java的特点有哪些?
  16. Java安卓如何添加悬浮窗_Android悬浮窗的实现
  17. 天然和合成石墨的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
  18. Crystals Kyber密码算法解读(一)
  19. golang集锦——如此优雅-吴冬冬-专题视频课程
  20. java实现多线程爬取表情包

热门文章

  1. 【五音疗疾】百病始于气而止于音
  2. CompareNoCase与Compare
  3. 一些前端开发大牛【持续更新】
  4. 不能忘了看XUL Tutorial。
  5. python换硬币_Python的硬币兑换动态编程实现记录,CoinChange,最少,组合,python,规划
  6. 战略财务、共享财务、业务财务的思考-来自一个财务业务的分享
  7. Linux + 香橙派 + V4L2 + http 实现远程监控摄像头在网页端显示
  8. src\loadsave.cpp:738: error: (-215:Assertion failed) !_img.empty() in function ‘cv::imwrite‘
  9. python图片转化为素描图
  10. (02)Cartographer源码无死角解析-(48) 2D点云扫描匹配→扫描匹配基本原理讲解,代码总体框架梳理AddAccumulatedRangeData()