【发布时间】:2021-07-09 07:15:21
【问题描述】:
可以使用“位打包”技术来压缩无符号整数:在一个无符号整数块中,仅存储有效位,当一个块中的所有整数都是“小”时,会导致数据压缩。该方法被称为FOR(参考框架)。
有 SIMD libraries 可以非常有效地执行此操作。
现在我想使用类似 FOR 的技术来编码 signed 整数,例如来自未排序的无符号整数的不同序列。每个有符号整数的符号需要存储在某个地方,有两种选择:
- 将符号存储在单独的数据块中。这会增加开销。
- 将符号与每个有符号整数的绝对值一起存储。
我现在正在遵循路径 2。 2-s 补码在 msb(最高有效位)中有符号位,因此这不适用于位打包 à la FOR。一种可能性是将符号存储在 lsb(最低有效位)中。以这种方式存储有符号整数是非常不寻常的,据我所知,没有支持这一点的指令。现在的问题是:这些 lsb-signed-integer 能否使用 SIMD 指令高效地编码/解码?
我认为 AVX-512 _mm_testn_epi32_mask 可用于从每个 uint32 中提取 lsb,然后是移位,然后是某种形式的两个 mask_extract?相当复杂。
【问题讨论】:
-
从有符号整数到无符号整数的常见且可逆的映射是:
(x < 0) ? (-2 * x - 1) : (2 * x)。你能利用它吗? -
AVX-512 具有 32 位元素的 SIMD 循环,如果有帮助的话。 (felixcloutier.com/x86/vprold:vprolvd:vprolq:vprolvq)。所以你可以把符号位放到底部。但是我想你会想要掩盖所有其他领先的负数。也许您可以对负输入进行位翻转或取反,因此以前导零结尾,并且可以在解码时将低位用作是否取反的信号。 (与
x ^ -1不同,旋转后的0-x的优势在于将低位设置为负数。)我认为这与@njuffa 建议的映射相同。 -
是的,所以使用
vprold zmm, zmm, 1/vpabsd zmm, zmm(32 位元素的绝对值)进行编码。解码...当我想到某些事情时,如果没有人击败我,我会发布答案:P -
10年前问过一个相关问题:stackoverflow.com/questions/3557599/…
-
实现@njuffa的建议,注意
-x - 1和~x一样,所以(x < 0) ? (-2 * x - 1) : (2 * x)和(x>>31) ^ (x+x)一样。