使用`int`的最高字节优化`char`的XOR

问题描述 投票:-2回答:2

让我们有int ichar c

当使用i ^= c时,编译器将使用c的最低字节XOR i,并将代码转换为单处理器指令。

当我们需要使用c的最高字节的XOR i时,我们可以这样做:

i ^= c << ((sizeof(i) - sizeof(c)) * 8)

但编译器将生成两个指令:XORBIT-SHIFT

有没有办法用char的最高字节对int进行异或,这将被转换为C ++中的单处理器指令?

c++ optimization xor
2个回答
1
投票

如果您对系统的字节顺序有信心,例如通过检查系统上的__BYTE_ORDER__或等效宏,您可以执行以下操作:

#if // Somehow determing if little endian, so biggest byte at the end
    *(&reinterpret_cast<char&>(i) + sizeof i - 1) ^= c
#else
    // Is big endian, biggest byte at the beginning
    reinterpret_cast<char&>(i) ^= c
#endif

0
投票

不要假设编译器会使用上面的代码生成一个shift。大多数现代编译器比这更聪明:

https://godbolt.org/z/b6l8qk


0
投票

编译器对这种简单的算术和按位运算非常聪明。他们不这样做只是因为他们不能,因为这些架构上没有这样的指示。对于很少使用的操作,不值得浪费宝贵的操作码空间。无论如何,大多数操作都在整个寄存器中完成,并且仅对寄存器的一部分进行操作对于CPU来说是非常低效的,因为无序执行或寄存器重命名单元将需要更加努力地工作。这就是为什么x86-64 instructions on 32-bit registers zero the upper part of the full 64-bit register或者为什么修改x86中寄存器的低部分(如AL或AX)可能比修改整个RAX要慢的原因。 INC can also be slower than ADD 1 because of the partial flag update

也就是说,有一些架构可以在像ARM这样的单个指令中组合SHIFT和XOR,因为ARM设计人员将预编码和移位部分的大部分指令编码用于少数寄存器。但同样,你的前提是错误的,因为事物可以在一条指令中执行并不意味着它会更快。现代CPU非常复杂,因为每条指令都有不同的延迟,吞吐量和执行端口数。例如,如果CPU可以并行执行4对SHIFT-then-XOR,那么显然它会比另一个可以顺序运行4个单SHIFT-XOR指令的CPU更快,前提是时钟周期相同

这是一个非常典型的XY problem,因为你认为这只是错误的做法。对于需要完成数千,数百万次或更多次的操作,那就是GPUSIMD unit的工作

例如,这是Clang编译器为一个循环发出的循环使用i在x86 CPU上使用cAVX-512的顶部字节进行异或运算

    vpslld  zmm0, zmm0, 24
    vpslld  zmm1, zmm1, 24
    vpslld  zmm2, zmm2, 24
    vpslld  zmm3, zmm3, 24
    vpxord  zmm0, zmm0, zmmword ptr [rdi + 4*rdx]
    vpxord  zmm1, zmm1, zmmword ptr [rdi + 4*rdx + 64]
    vpxord  zmm2, zmm2, zmmword ptr [rdi + 4*rdx + 128]
    vpxord  zmm3, zmm3, zmmword ptr [rdi + 4*rdx + 192]

通过这样做,它只需2条指令即可实现16次SHIFT-XOR。想象一下这有多快。这就是为什么所有高性能架构都有某种SIMD,它更容易快速完成,而不是无用的SHIFT-XOR指令。即使在具有单指令SHIFT-XOR的ARM上,编译器也会足够聪明地知道SIMD比一系列eor rX, rX, rY, lsl #24更快

    shl     v3.4s, v3.4s, 24
    shl     v2.4s, v2.4s, 24
    shl     v1.4s, v1.4s, 24
    shl     v0.4s, v0.4s, 24
    eor     v3.16b, v3.16b, v7.16b
    eor     v2.16b, v2.16b, v6.16b
    eor     v1.16b, v1.16b, v4.16b
    eor     v0.16b, v0.16b, v5.16b

Here's a demo for the above snippets

在多核中并行运行时,速度会更快。 GPU还能够执行非常高级别或并行性,因此现代密码术和强烈的数学问题通常在GPU上完成。它可以比使用SIMD的通用CPU更快地破解密码或加密文件

© www.soinside.com 2019 - 2024. All rights reserved.