Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 位范围上的减法_C_Optimization_X86_Bit Manipulation_X86 64 - Fatal编程技术网

C 位范围上的减法

C 位范围上的减法,c,optimization,x86,bit-manipulation,x86-64,C,Optimization,X86,Bit Manipulation,X86 64,我有一组22个5位值(0-31),它们作为110位压缩到两个64位无符号整数中(即最后18位始终为零)。我想设计一个函数,对于每段5位,执行一个绝对值差 我知道在单个数字上使用位运算符的减法方法,但这里我不想担心5位段之间的溢出。我正在寻找一种使用位运算符和/或x86汇编操作的解决方案,最好不使用任何循环 编辑:为了澄清,我将有一对110位的数据,我想对它们执行这个差分操作。欢迎提出任何建议 解决方案:感谢@EOF建议VPSADBW指令。我将使用8位数字来代替更快(更可读)的代码。您可以使用带有

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

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

编辑:为了澄清,我将有一对110位的数据,我想对它们执行这个差分操作。欢迎提出任何建议


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

您可以使用带有掩码的
pdep
,如
0B00011111100011111…
将5位整数分散到8位字段中,并使用上面评论中讨论的字节SIMD内容

或者,您可以将它们展开为6位字段,并将额外的位设置为
1
,然后用64位字进行减法运算,但是您需要找到某种方法以SWAR方式执行“abs”部分。不过我怀疑SIMD会更快


请记住,
pdep
在AMD CPU上的性能非常糟糕:吞吐量差18倍

您可以将
pdep
与类似
0B00011111100011111…
的掩码一起使用,将5位整数分散到8位字段中,并使用上面评论中讨论的按字节排列的SIMD内容

或者,您可以将它们展开为6位字段,并将额外的位设置为
1
,然后用64位字进行减法运算,但是您需要找到某种方法以SWAR方式执行“abs”部分。不过我怀疑SIMD会更快


请记住,
pdep
在AMD CPU上的性能非常糟糕:吞吐量差18倍

我认为您最好的选择可能是在最近的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

我认为最好的选择可能是在最近的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

你能澄清一下吗?单个值的绝对值差是多少?(我只知道两个值之间有差异。)而且它看起来像是一个“我的代码”请求。我怀疑最糟糕的部分将是横跨两个
uint64_t
s的5位数字。如果我想到了一个非常好的方案,但我正好缺了1位。我在考虑给每个人6位,用1位进位。这样,在进行减法运算之前,我们可以设置所有进位和减法运算。但这需要66位。我们只有64+1(实际进位)=65位。@WillCunningham:嗯,x86上有
[V]PSADBW
,它给出了
uint8\u t
s的两个向量之间的绝对差之和。我认为x86本身没有针对绝对差异的指令,但ARM NEON有:
VABD
。在x86上,您可能需要两条指令,
[V]PSUBB
[V]PABSB
。您能澄清一下吗?单个值的绝对值差是多少?(我只知道两个值之间有差异。)而且它看起来像是一个“我的代码”请求。我怀疑最糟糕的部分将是横跨两个
uint64_t
s的5位数字。如果我想到了一个非常好的方案,但我正好缺了1位。我在考虑给每个人6位,用1位进位。这样,在进行减法运算之前,我们可以设置所有进位和减法运算。但这需要66位。我们只有64+1(实际进位)=65位。@WillCunningham:嗯,x86上有
[V]PSADBW
,它给出了
uint8\u t
s的两个向量之间的绝对差之和。我认为x86本身没有针对绝对差异的指令,但ARM NEON有:
VABD
。在x86上,您可能需要两条指令,
[V]PSUBB
[V]PABSB
。谢谢!这将是有用的。谢谢!这将是有用的。