我有一组22个5位值(0-31),它们作为110位打包成两个64位无符号整数(即最后18位始终为零)。我想设计一个函数,对于每个5位的段,它将执行绝对值差异。
我知道在单个数字上使用按位运算符进行减法的方法,但在这里我不想担心5位段之间的溢出。我正在寻找使用按位运算符和/或x86汇编操作的解决方案,最好没有任何循环。
编辑:为了澄清,我将拥有这些110位的对,我想对此进行差异操作。欢迎任何建议。
解决方案:感谢@EOF建议VPSADBW指令。我将使用8位数字代替更快(更易读)的代码。
答案 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
。