设为首页收藏本站

LUPA开源社区

 找回密码
 注册
文章 帖子 博客
LUPA开源社区 首页 业界资讯 技术文摘 查看内容

为什么处理有序数组比无序数组快?

2014-6-4 11:51| 发布者: joejoe0332| 查看: 4234| 评论: 0|原作者: Jerry|来自: 伯乐在线

摘要: 由于某些怪异的原因,下面这段C++代码表现的异乎寻常—-当这段代码作用于有序数据时其速度可以提高将近6倍,这真是令人惊奇。

  GManNickG 提问:


  由于某些怪异的原因,下面这段C++代码表现的异乎寻常—-当这段代码作用于有序数据时其速度可以提高将近6倍,这真是令人惊奇。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include
#include
#include
 
int _tmain (int argc , _TCHAR * argv [])
{
        //Generate data
        const unsigned arraySize = 32768;
        int data[arraySize];
 
        for ( unsigned c = 0; c < arraySize; ++c)
              data[c] = std::rand() % 256;
 
        //!!! With this, the next loop runs faster
       std::sort(data, data + arraySize);
 
        //Test
        clock_t start = clock();
        long long sum = 0;
        for ( unsigned i = 0; i < 100000; ++i){
               //Primary loop
               for ( unsigned c = 0; c < arraySize; ++c){
                      if (data[c] >= 128)
                           sum += data[c];
              }
       }
        double eclapsedTime = static_cast<double >(clock() - start) / CLOCKS_PER_SEC;
 
       std::cout << eclapsedTime << std::endl;
       std::cout << "sum = " << sum << std::endl;
        return 0;
}
  • 如果把 std::sort(data, data+arraySize) 去掉,这段代码耗时11.54秒。
  • 对于有序数据,这段代码耗时1.93秒


  起初我以为这可能是某一种语言或某一个编译器发生的异常的事件,后来我在java语言写了个例子,如下:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import java.util.Arrays;
import java.util.Random;
 
public class Test_Sorted_UnSorted_Array {
       public static void main(String[] args) {
             //Generate data
             int arraySize = 32768;
             int data[] = new int[arraySize];
 
            Random rnd = new Random(0);
             for( int c = 0; c
                  data[c] = rnd.nextInt()%256;
 
             //!!! With this, the next loop runs faster
            Arrays. sort(data);
 
             //Test
             long start = System. nanoTime();
             long sum = 0;
 
             for( int i=0; i<100000; ++i){
                   //Primary loop
                   for( int c = 0; c
                         if(data[c] >=128)
                              sum += data[c];
                  }
            }
 
            System. out.println((System. nanoTime() - start) / 1000000000.0);
            System. out.println( "sum = " + sum);
      }
}


  上述例子运行结果和前面C++例子运行的结果差异,虽然没有C++中那么大,但是也有几分相似。


  对于上面的问题,我首先想的原因是排序可能会导致数据有缓存,但是转念一想之前原因有点不切实际,因为上面的数组都是刚刚生成的,所以我的问题是:


  • 上述代码运行时到底发生了什么?
  • 为什么运行排好序的数组会比乱序数组快?
  • 上述代码求和都是独立的,而顺序不应该会产生影响。

 

  来自 Mysticial 的最佳回复


  你是分支预测(branch prediction )失败的受害者。


  什么是分支预测?


  考虑一个铁路枢纽:


Imageby Mecanismo, via Wikimedia Commons. Used under theCC-By-SA 3.0license.

 


酷毙

雷人

鲜花

鸡蛋

漂亮
  • 快毕业了,没工作经验,
    找份工作好难啊?
    赶紧去人才芯片公司磨练吧!!

最新评论

关于LUPA|人才芯片工程|人才招聘|LUPA认证|LUPA教育|LUPA开源社区 ( 浙B2-20090187 浙公网安备 33010602006705号   

返回顶部