SSE2用于64位整数的C语言中未经测试的ZigZag示例:
(注意:SSE2缺少一些64位指令...)
#include <emmintrin.h>
__m128i zigzag_encode_epi64(__m128i v) {
__m128i signmask = _mm_shuffle_epi32(v, _MM_SHUFFLE(3,3,1,1));
signmask = _mm_srai_epi32(signmask, 31);
return _mm_xor_si128(_mm_add_epi64(v, v), signmask);
}
__m128i zigzag_decode_epi64 (__m128i v) {
__m128i signmask = _mm_and_si128(_mm_set_epi32(0, 1, 0, 1), v);
signmask = _mm_sub_epi64(_mm_setzero_si128(), signmask);
return _mm_xor_si128(_mm_srli_epi64(v, 1), signmask);
}
__m128i zigzag_decodev3_epi64 (__m128i v) {
__m128i t = _mm_srli_epi64(v, 1);
__m128i signmask = _mm_sub_epi64(_mm_slli_epi64(t, 1), v);
return _mm_xor_si128(t, signmask);
}
Zigzag适合位运算变长整数编码。然而,一个按字节分组的组变长可能希望“从可变位宽进行符号扩展”。
32位示例
我更喜欢使用比较运算符而不是算术移位。假设展开后,比较运算符将具有比算术移位更短的延迟周期。
__m128i zigzag_encode_epi32 (__m128i v) {
__m128i signmask =_mm_cmpgt_epi32(_mm_setzero_si128(), v)
return _mm_xor_si128(_mm_add_epi32(v, v), signmask)
}
__m128i zigzag_decode_epi32 (__m128i v) {
const __m128i m = _mm_set1_epi32(1)
__m128i signmask =_mm_cmpeq_epi32(_mm_and_si128(m, v), m)
return _mm_xor_si128(_mm_srli_epi32(v, 1), signmask)
}
__m128i delta_encode_epi32 (__m128i v, __m128i prev) {
return _mm_sub_epi32(v, _mm_alignr_epi8(v, prev, 12))
}
// prefix sum (see many of answers around stackoverflow...)
__m128i delta_decode_epi32 (__m128i v, __m128i prev) {
prev = _mm_shuffle_epi32(prev, _MM_SHUFFLE(3,3,3,3))
v = _mm_add_epi32(v, _mm_slli_si128(v, 4))
prev = _mm_add_epi32(prev, v)
v = _mm_slli_si128(v, 8)
return _mm_add_epi32(prev, v)
}
__m128i delta_zigzag_encode_epi32 (__m128i v, __m128i prev) {
return zigzag_encode_epi32(delta_encode_epi32(v, prev))
}
__m128i delta_zigzag_decode_epi32 (__m128i v, __m128i prev) {
return delta_decode_epi32(zigzag_decode_epi32(v), prev)
}
注意:对于Delta编码而言,为了提高速度(往返/解码),在编码时转置元素,然后在解码时再将它们转置回来会更快;水平前缀和非常慢。然而,确定每个批次中需要转置的最佳元素数量似乎是一个难题。
(x < 0) ? (-2 * x - 1) : (2 * x)
。你能利用它吗? - njuffavprold zmm, zmm, 1
/vpabsd zmm, zmm
进行编码(32位元素的绝对值)。解码时...如果没有人比我更快,我想到了什么,我会发布一个答案 :P - Peter Cordes-x-1
与~x
是相同的,因此(x < 0) ? (-2 * x - 1) : (2 * x)
等同于(x>>31) ^ (x+x)
。 - chtz