按位XOR与求和之间的性能差异似乎消失了

时间:2019-04-14 22:19:53

标签: c++ performance

我最近看到了一个很好的解决编程问题的方法。给定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;
}

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

  

missing_2:耗时:16.21s

     

missing_3:耗时:23.39s

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

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

编辑:

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

Edit2:

经过标记-O1-O2的测试,没有明显区别。

Edit3:

以下是驱动程序代码:

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

编辑5:“计时”部分已更新(无时间更改)

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

1 个答案:

答案 0 :(得分:2)

正如Peter和Matteo在问题评论中提到的那样。

尽管对于单个操作与加法,异或将相等/更快。由于pipelining,XOR版本比求和版本慢。

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

这个答案是受到彼得斯评论的启发。我只是想确保问题有一个可用的答案,而Peter选择不回答。

编辑:

感谢phuclv,将代码分别更改为求和数组ab(请参见下面的注释)会破坏依赖关系,并导致XOR返回的结果比Summation更快/相等。