C++ 按位异或与求和之间的性能差异似乎消失了
我最近看到了一个很好的编程问题的解决方案。给定两个列表,在其中一个列表中查找缺少的数字 我最初的解决方案是这样的:C++ 按位异或与求和之间的性能差异似乎消失了,c++,performance,C++,Performance,我最近看到了一个很好的编程问题的解决方案。给定两个列表,在其中一个列表中查找缺少的数字 我最初的解决方案是这样的: long long missing_2(long long a[], long long b[], long long bsize) { long long asum = a[bsize], bsum = 0; for (long long i = 0; i < bsize; i++) { asum += a[i]; bsum
long long missing_2(long long a[], long long b[], long long bsize) {
long long asum = a[bsize], bsum = 0;
for (long long i = 0; i < bsize; i++) {
asum += a[i];
bsum += b[i];
}
return asum-bsum;
}
long long missing_3(long long a[], long long b[], long long bsize) {
long long sum = 0 ^ a[bsize];
for (long long i = 0; i < bsize; i++) {
sum ^= a[i];
sum ^= b[i];
}
return sum;
}
编辑5:定时部分已更新(无时间更改)
clock_t tStart=clock();
正如Peter和Matteo在问题评论中提到的那样
尽管对于单个操作和加法,XOR的速度相同/更快。由于以下原因,XOR版本比求和版本慢
一个XOR必须等待前一个XOR操作完成后才能开始其操作,而求和(加法)可以并行运行,因此可以使用流水线。反过来,允许求和结束时比按位异或更快
这个答案的灵感来自彼得斯的评论。我只是想确保这个问题有一个可用的答案,彼得选择不写
编辑:
多亏了phuclv,将代码分别更改为数组a
和b
(请参见下面的注释)的总和会打破依赖关系,并导致异或返回的速度比总和快/相等。不会慢很多。现在你已经知道了,有超过500的RIP的人应该知道,与定时C++应用程序相关的任何东西都应该有他们用来构建应用程序的编译器选项。然后使用-O2
或-O3
重新构建程序,然后重新运行测试。我不了解当前ALU实现的最新情况,但xor版本看起来应该会因为管道化而丢失一个刻度。也就是说,xor b必须等待xor a的结果。如前所述,这显然是一个管道问题——循环体中存在数据依赖性,这也会在下一次迭代中进行。在第一个示例中,循环体可以完全并行运行。如果确实是因为依赖关系,则通过{sumA^=a[i];sumB^=b[i];}返回sumA^sumB代码>
long long smaller_size = 1000000000;
long long* a = new long long[smaller_size+1];
long long* b = new long long[smaller_size];
for(long long i = 0; i < smaller_size; i++){
a[i] = b[i] = i;
}
a[smaller_size] = 1434;
// std::cout << missing_1(a, b, smaller_size) << std::endl;
clock_t tStart = clock();
std::cout << "Start List Test\n";
std::cout << missing_2(a, b, smaller_size) << std::endl;
printf("Time taken: %.2fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC);
tStart = clock();
std::cout << missing_3(a, b, smaller_size) << std::endl;
printf("Time taken: %.2fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC);
clock_t tStart = clock();
std::cout << "Start List Test\n";
double time;
missing_2(a, b, smaller_size);
time = (double)(clock() - tStart)/CLOCKS_PER_SEC;
printf("Time taken: %.2fs\n", time);
tStart = clock();
missing_3(a, b, smaller_size);
time = (double)(clock() - tStart)/CLOCKS_PER_SEC;
printf("Time taken: %.2fs\n", time);