减去比特范围

时间:2017-05-10 18:29:01

标签: c optimization x86 bit-manipulation x86-64

我有一组22个5位值(0-31),它们作为110位打包成两个64位无符号整数(即最后18位始终为零)。我想设计一个函数,对于每个5位的段,它将执行绝对值差异。

我知道在单个数字上使用按位运算符进行减法的方法,但在这里我不想担心5位段之间的溢出。我正在寻找使用按位运算符和/或x86汇编操作的解决方案,最好没有任何循环。

编辑:为了澄清,我将拥有这些110位的对,我想对此进行差异操作。欢迎任何建议。

解决方案:感谢@EOF建议VPSADBW指令。我将使用8位数字代替更快(更易读)的代码。

2 个答案:

答案 0 :(得分:2)

您可以使用带有pdep等掩码的0b000111111000111111...将5位整数分散到8位字段中,并使用上述注释中讨论的按字节顺序的SIMD内容。

或者,您可以将它们扩展为6位字段,并将额外位设置为1,并以64位字进行减法,但是您需要找到一些bit-twiddly方式做" abs"参与SWAR时尚。我怀疑SIMD会更快。

请记住,pdep在AMD CPU上表现糟糕:18 吞吐量更差!

答案 1 :(得分:1)

我认为最好的选择可能是最近的x86 CPU上的pdep(并行位存款)指令。您可以使用它将您的5位值快速扩展为8位值。一旦它们是8位值,就可以执行许多SSE指令。

以下内容采用rdx:rax中的128位值,并输出xmm1:xmm0,并将这些值拆分为字节。

以下是我认为可能适合您的一些未经测试的代码:

mov r8, abs 0x1F1F1F1F1F1F1F1F

pdep rcx, rax, r8
movq xmm0, rcx

shrd rax, rdx, 16
shr rax, 40 - 16
pdep rax, rax, r8
pinsrq xmm0, rax, 1

shr rdx, 16
pdep rdx, rdx, r8
movq xmm1, rdx

逆转换类似,pext代替pdep