排序数组中的“==”不比未排序数组快吗? [重复]
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了排序数组中的“==”不比未排序数组快吗? [重复]相关的知识,希望对你有一定的参考价值。
这个问题在这里已有答案:
注意:我认为,所谓的重复问题主要与“<”和“>”比较有关,但与“==”比较无关,因此不回答我关于“==”运算符性能的问题。
很长一段时间,我相信“处理”排序数组应该比未排序数组更快。起初,我认为在排序数组中使用“==”应该比未排序数组更快,因为 - 我猜 - 分支预测如何工作:
UNSORTEDARRAY:
5 == 100 F
43 == 100 F
100 == 100 T
250 == 100 F
6 == 100 F
(other elements to check)
SORTEDARRAY:
5 == 100 F
6 == 100 F
43 == 100 F
100 == 100 T
(no need to check other elements, so all are F)
所以我猜SORTEDARRAY应该比UNSORTEDARRAY更快,但今天我用代码在标题中生成2个数组进行测试,并且分支预测似乎不像我想的那样工作。
我生成了一个未排序的数组和一个排序的数组来测试:
srand(time(NULL));
int UNSORTEDARRAY[524288];
int SORTEDARRAY[sizeof(UNSORTEDARRAY)/sizeof(int)];
for(int i=0;i<sizeof(SORTEDARRAY)/sizeof(int);i++){
SORTEDARRAY[i]=UNSORTEDARRAY[i]=rand();
}
sort(SORTEDARRAY,SORTEDARRAY+sizeof(SORTEDARRAY)/sizeof(int));
string u="const int UNSORTEDARRAY[]={";
string s="const int SORTEDARRAY[]={";
for(int i=0;i<sizeof(UNSORTEDARRAY)/sizeof(int);i++){
u+=to_string(UNSORTEDARRAY[i])+",";
s+=to_string(SORTEDARRAY[i])+",";
}
u.erase(u.end()-1);
s.erase(s.end()-1);
u+="};
";
s+="};
";
ofstream out("number.h");
string code=u+s;
out << code;
out.close();
所以要测试,只需计算值是否= = RAND_MAX / 2,如下所示:
#include "number.h"
int main(){
int count;
clock_t start = clock();
for(int i=0;i<sizeof(SORTEDARRAY)/sizeof(int);i++){
if(SORTEDARRAY[i]==RAND_MAX/2){
count++;
}
}
printf("%f
",(float)(clock()-start)/CLOCKS_PER_SEC);
}
跑3次:
UNSORTEDARRAY
0.005376
0.005239
0.005220
SORTEDARRAY
0.005334
0.005120
0.005223
它似乎是一个小的性能差异,所以我不相信它,然后试图将“SORTEDARRAY [i] == RAND_MAX / 2”改为“SORTEDARRAY [i]> RAND_MAX / 2”,看它是否有所作为:
UNSORTEDARRAY
0.008407
0.008363
0.008606
SORTEDARRAY
0.005306
0.005227
0.005146
这一次有很大的不同。
排序数组中的“==”不比未排序数组快吗?如果是,为什么排序数组中的“>”比未排序数组快,但“==”不是?
立即想到的一件事是CPU的分支预测算法。
在>
比较的情况下,在排序数组中,分支行为非常一致:首先,if
条件始终为假,然后它始终为真。即使是最简单的分支预测,这也能很好地对齐。
在未排序的数组中,>
条件的结果基本上是随机的,因此阻碍了任何分支预测。
这使得排序版本更快。
在==
比较的情况下,大多数情况下条件是错误的,并且很少这是真的。无论数组是否排序,这都适用于分支预测。时间基本相同。
注:我正在回答这个问题,因为它的评论太长了。
这里的效果正是在this question的丰富答案中已经详细解释的内容。由于分支预测,在这种情况下处理排序的数组更快。
在这里,罪魁祸首又是分支预测。 ==
测试很少是真实的,因此分支预测对两者都大致相同。当你把它改成>
时,你得到了那个问题中解释的行为,并且出于同样的原因。
道德:
我相信“处理”排序的数组应该比[未]数组更快。
你需要知道原因。这不是一些神奇的规则,并不总是如此。
比较==
与>
的排序关系较少。正确或错误地预测==
只取决于重复值的数量及其分布。
您可以使用perf stat
查看性能计数器......
jason@io /tmp $ lz4 -d ints | perf stat ./proc-eq >/dev/null
Successfully decoded 104824717 bytes
Performance counter stats for './proc-eq':
5226.932577 task-clock (msec) # 0.953 CPUs utilized
31 context-switches # 0.006 K/sec
24 cpu-migrations # 0.005 K/sec
3,479 page-faults # 0.666 K/sec
15,763,486,767 cycles # 3.016 GHz
4,238,973,549 stalled-cycles-frontend # 26.89% frontend cycles idle
<not supported> stalled-cycles-backend
31,522,072,416 instructions # 2.00 insns per cycle
# 0.13 stalled cycles per insn
8,515,545,178 branches # 1629.167 M/sec
10,261,743 branch-misses # 0.12% of all branches
5.483071045 seconds time elapsed
jason@io /tmp $ lz4 -d ints | sort -n | perf stat ./proc-eq >/dev/null
Successfully decoded 104824717 bytes
Performance counter stats for './proc-eq':
5536.031410 task-clock (msec) # 0.348 CPUs utilized
198 context-switches # 0.036 K/sec
21 cpu-migrations # 0.004 K/sec
3,604 page-faults # 0.651 K/sec
16,870,541,124 cycles # 3.047 GHz
5,300,218,855 stalled-cycles-frontend # 31.42% frontend cycles idle
<not supported> stalled-cycles-backend
31,526,006,118 instructions # 1.87 insns per cycle
# 0.17 stalled cycles per insn
8,516,336,829 branches # 1538.347 M/sec
10,980,571 branch-misses # 0.13% of all branches
jason@io /tmp $ lz4 -d ints | perf stat ./proc-gt >/dev/null
Successfully decoded 104824717 bytes
Performance counter stats for './proc-gt':
5293.065703 task-clock (msec) # 0.957 CPUs utilized
38 context-switches # 0.007 K/sec
50 cpu-migrations # 0.009 K/sec
3,466 page-faults # 0.655 K/sec
15,972,451,322 cycles # 3.018 GHz
4,350,726,606 stalled-cycles-frontend # 27.24% frontend cycles idle
<not supported> stalled-cycles-backend
31,537,365,299 instructions # 1.97 insns per cycle
# 0.14 stalled cycles per insn
8,515,606,640 branches # 1608.823 M/sec
15,241,198 branch-misses # 0.18% of all branches
5.532285374 seconds time elapsed
jason@io /tmp $ lz4 -d ints | sort -n | perf stat ./proc-gt >/dev/null
15.930144154 seconds time elapsed
Performance counter stats for './proc-gt':
5203.873321 task-clock (msec) # 0.339 CPUs utilized
7 context-switches # 0.001 K/sec
22 cpu-migrations # 0.004 K/sec
3,459 page-faults # 0.665 K/sec
15,830,273,846 cycles # 3.042 GHz
4,456,369,958 stalled-cycles-frontend # 28.15% frontend cycles idle
<not supported> stalled-cycles-backend
31,540,409,224 instructions # 1.99 insns per cycle
# 0.14 stalled cycles per insn
8,516,186,042 branches # 1636.509 M/sec
10,205,058 branch-misses # 0.12% of all branches
15.365528326 seconds time elapsed
以上是关于排序数组中的“==”不比未排序数组快吗? [重复]的主要内容,如果未能解决你的问题,请参考以下文章