为什么XOR比OR快得多?

这是一个基准:

fn benchmark_or(repetitions: usize, mut increment: usize) -> usize {
    let mut batch = 0;
    for _ in 0..repetitions {
        increment |= 1;
        batch += increment | 1;
    }
    batch
}

fn benchmark_xor(repetitions: usize, mut increment: usize) -> usize {
    let mut batch = 0;
    for _ in 0..repetitions {
        increment ^= 1;
        batch += increment | 1;
    }
    batch
}

fn benchmark(c: &mut Criterion) {
    let increment = 1;
    let repetitions = 1000;

    c.bench_function("Increment Or", |b| {
        b.iter(|| black_box(benchmark_or(repetitions, increment)))
    });
    c.bench_function("Increment Xor", |b| {
        b.iter(|| black_box(benchmark_xor(repetitions, increment)))
    });
}

结果是:

Increment Or            time:   [271.02 ns 271.14 ns 271.28 ns]
Increment Xor           time:   [79.656 ns 79.761 ns 79.885 ns] 

如果我替换orand.

or工作台编译为时,这非常令人困惑

.LBB0_5:
        or      edi, 1
        add     eax, edi
        add     rcx, -1
        jne     .LBB0_5

并且xorbench 编译成基本相同的指令加上两个额外的指令:

.LBB1_6:
        xor     edx, 1
        or      edi, 1
        add     eax, edi
        mov     edi, edx
        add     rcx, -1
        jne     .LBB1_6

完整的汇编代码

为什么差别这么大?

回答

使用您引用的 XOR 的函数的这一部分:

.LBB1_6:
        xor     rdx, 1
        or      rsi, 1
        add     rax, rsi
        mov     rsi, rdx
        add     rcx, -1
        jne     .LBB1_6

只是展开循环的“尾端”。“肉”(实际上运行很多的部分)是这样的:

.LBB1_9:
        add     rax, rdx
        add     rdi, 4
        jne     .LBB1_9

rdx设置为 4 次increment- 在某种程度上,我将其描述为“只有编译器可能会如此愚蠢”,但它只发生在循环之外,因此它不是一场彻底的灾难。循环计数器在每次迭代中前进 4(从负数开始一直计数到零,这聪明,在某种程度上补偿了编译器)。

这个循环可以在每个周期执行 1 次迭代,转换为每个周期源循环的 4 次迭代。

使用 OR 的函数中的循环也展开了,这是该函数的实际“肉”:

.LBB0_8:
        or      rsi, 1
        lea     rax, [rax + 2*rsi]
        lea     rax, [rax + 2*rsi]
        lea     rax, [rax + 2*rsi]
        lea     rax, [rax + 2*rsi]
        add     rdi, 8
        jne     .LBB0_8

它展开了 8 次,这可能很好,但是lea像这样链接4 次确实需要“只有编译器才能如此愚蠢”到下一个级别。通过leas的串行依赖性每次迭代至少需要 4 个周期,转换为每个周期源循环的 2 次迭代。

这解释了 2 倍的性能差异(有利于 XOR 版本),而不是您测量的 3.4 倍差异,因此可以进行进一步分析。


以上是为什么XOR比OR快得多?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>