按位 XOR 与求和之间的性能差异似乎不存在

Performance difference between bitwise XOR vs summations seems off

本文关键字:不存在 性能 XOR 求和 之间 按位      更新时间:2023-10-16

我最近看到了一个很好的编程问题解决方案。给定 2 个列表,在其中一个列表中找到缺少的数字。

我最初的解决方案是这样的:

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;
}

出于好奇,我定时了 2 个解决方案,认为第二个解决方案missing_3会更快。我得到了这些结果

missing_2:所需时间:16.21秒

missing_3:所用时间:23.39秒

列表是使用 for 循环生成的。列表 b 填充整数0-1000000000,列表 a 填充 1-1000000000,末尾附加一个随机数(因此它包含 1 个不同的(额外)值。

问题按位版本需要 23.39 秒,求和版本需要 16.21 秒。知道为什么按位版本会明显比求和版本慢吗?我本以为按位运算会比加法或至少类似运算更快。

编辑:

使用没有额外标志/选项的g++编译。

编辑2:

-O1-O2的标志进行测试,没有明显的区别。

编辑3:

这是驱动程序代码:

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 Testn";
std::cout << missing_2(a, b, smaller_size) << std::endl;
printf("Time taken: %.2fsn", (double)(clock() - tStart)/CLOCKS_PER_SEC);
tStart = clock();
std::cout << missing_3(a, b, smaller_size) << std::endl;
printf("Time taken: %.2fsn", (double)(clock() - tStart)/CLOCKS_PER_SEC);

编辑 5:时间部分更新(无时间更改)

clock_t tStart = clock();
std::cout << "Start List Testn";
double time; 
missing_2(a, b, smaller_size);
time = (double)(clock() - tStart)/CLOCKS_PER_SEC;
printf("Time taken: %.2fsn", time);
tStart = clock();
missing_3(a, b, smaller_size);
time = (double)(clock() - tStart)/CLOCKS_PER_SEC;
printf("Time taken: %.2fsn", time);

正如彼得和马特奥在问题评论中提到的。

尽管 XOR 对于单个操作与加法是相等/更快的。由于流水线,XOR 版本比求和版本慢。

一个 XOR 必须等待前一个 XOR 操作完成才能开始其操作,而求和(加法)可以并行运行,因此使用流水线。反过来,允许求和比按位 XOR 更快结束。

这个答案的灵感来自彼得斯的评论。我只是想确保这个问题有一个可用的答案,彼得选择不写一个。

编辑:

多亏了 phuclv,更改代码以对数组a求和并单独b(请参阅下面的注释)会破坏依赖关系并导致 XOR 返回比求和更快/相等。