SIMD:位包有符号整数

2023-12-26

可以使用“位打包”技术来压缩无符号整数:在无符号整数块中,仅存储有效位,从而当块中的所有整数都“小”时进行数据压缩。该方法被称为FOR https://www.elastic.co/blog/frame-of-reference-and-roaring-bitmaps(参照系)。

有SIMD图书馆 https://github.com/awesome-simd/awesome-simd非常有效地做到这一点。

现在我想使用类似FOR的技术来编码signed整数,例如来自未排序的无符号整数的差异序列。每个有符号整数的符号需要存储在某处,有两种选择:

  1. 将符号存储在单独的数据块中。这增加了开销。
  2. 将符号与每个有符号整数的绝对值存储在一起。

我现在正在遵循路径2。 2-s 补码在 MSB(最高有效位)中具有符号位,因此不适用于 FOR 那样的位打包。一种可能性是将符号存储在 lsb(最低有效位)中。以这种方式存储有符号整数是非常不寻常的,据我所知,没有指令支持这种方式。现在的问题是:可以使用 SIMD 指令对这些 lsb 有符号整数进行有效编码/解码吗?

我认为AVX-512_mm_testn_epi32_mask可用于从每个 uint32 中提取 lsb,后跟一个移位,然后是两个mask_extract某种?相当复杂。


未经测试ZigZag https://developers.google.com/protocol-buffers/docs/encoding#types使用 SSE2 处理 64 位整数的 C 示例:

(注意:SSE2 缺少一些 64 位指令...)

#include <emmintrin.h>


// from comment by Peter-Cordes 
__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);
}


// no constant
__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 位示例

我更喜欢比较而不是算术移位。我假设 - 当展开时 - 比较的延迟会降低 1 个周期。

__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)); // [P P P P]
    v = _mm_add_epi32(v, _mm_slli_si128(v, 4)); // [A AB BC CD]
    prev = _mm_add_epi32(prev, v); // [PA PAB PBC PCD]
    v = _mm_slli_si128(v, 8); // [0 0 A AB]
    return _mm_add_epi32(prev, v); // [PA PAB PABC PABCD]
}


__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);
}

注意:增量编码在编码时转置元素然后在解码期间再次转置它们会更快(往返/解码);水平前缀和确实很慢。然而,确定每批中要转置的最佳元素数量似乎是一个难题。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SIMD:位包有符号整数 的相关文章

随机推荐

  • 如何在 morris.js 条形图上放置文本

    我有一个 morris js 条形图 我想放置count在此图的顶部 我调查了morris js 酒吧文档 http www oesmith co uk morris js bars html 找不到任何 悬停时应该显示value但在栏顶部
  • 如何检查一个元素是否在嵌套列表中?

    如何检查元素是否在嵌套列表中 我正在尝试定义一个函数nested x ys 测试一个值是否x出现在整数的嵌套列表内部ys 结果必须具有价值True of False 循环嵌套列表并测试它们 这any 功能 http docs python
  • 实体框架 6.1.1 和 Npgsql 2.2.3:找不到兼容的实体框架数据库提供程序

    我正在 Visual Studio 2012 Update 4 中使用 EntityFramework 6 1 1 和 npgsql 2 2 3 开发一个项目 为此 我使用提供的设置安装了 npgsl 并安装了 nuget 包 Npgsql
  • 如何使用代码从电池优化中排除 Android 应用

    我是 Android 新手 现在正在开发一个基于 GPS 的项目 我从互联网 traccar 获得源代码 我的要求是应用程序应该每 1 公里或每 1 小时更新一次位置 但问题是应用程序在一段时间 10 20 分钟 后无法在后台运行 有什么解
  • Ajax 调用始终返回错误 500 客户端

    我试图将数据发布回位于 Default aspx 中的 webmethod jquery代码 data saveData testtestest ajax type POST contentType application json cha
  • 如何以固定宽度打印字符串?

    我有这段代码 打印字符串中所有排列的出现 def splitter str for i in range 1 len str start str 0 i end str i yield start end for split in spli
  • sql查询在多个列上不同

    我有这些数据 我正在尝试查找字段 1 2 3 4 中有不同 id 但有重复数据的情况 id field1 field2 field3 field4 1 A B C D 2 A B C D 3 A A C B 4 A A C B 所以 在这种
  • Angularjs 列表项边距问题将 ng-repeat 元素与静态元素相结合

    我想通过将存储在数组中的一些元素与一些将直接插入 html 中的静态元素分组来创建一个水平列表 像这样的事情 div class list container push down ul li Home li li i label li li
  • “datetime.time”没有“mktime”

    我正在尝试将日期时间对象转换为 UNIX 时间戳 最好以毫秒为单位 尽管我不介意有或没有 Mktime 似乎是通常获取它的方法 但是我不断收到错误 AttributeError 类型对象 datetime time 没有属性 mktime
  • pyqt从线程发出信号

    我正在尝试从多个线程更新 pyqt QProgressBar 据我了解 执行此操作的最佳方法是将信号发送回主 GUI 线程 我尝试将 QProgressBar 对象传递给工作线程 尽管它看起来确实如此 工作时我在口译员中收到了大量警告 在下
  • 在 Tensorflow 中将张量转换为 numpy 数组?

    使用带有 Python 绑定的 Tensorflow 时如何将张量转换为 numpy 数组 TensorFlow 2 x 热切执行 https www tensorflow org guide eager默认情况下是启用的 所以只需调用 n
  • 用于自定义 URL 的自定义 Pinterest 按钮(文本链接、图像或两者)

    我试图找到解决方案 但找不到 我需要 Pinterest 固定 按钮的自定义图像 并通过 url 固定一些自定义图像 但不是当前页面 我创建了一个自定义链接 a href class pinitbutton Pin It a 在样式中我设置
  • Liburl 未更新

    我使用的是 Ubuntu 14 04 需要curl 版本 gt 7 40 因此我按照一些步骤安装了最新的curl 版本 7 48 As root wget http curl haxx se download curl 7 48 0 tar
  • 调整窗口大小事件

    我正在创建一个简单的操作系统应用程序 但我无法在任何地方找到如何进行调整大小事件 假设我想打印新的宽度和高度并且我有这个控制器 class ViewController NSViewController override func view
  • gmock 可以用于存根 C 函数吗?

    我是 gmock 的新手 所以我想知道如何对在测试中的函数中调用的简单 C 函数进行存根以进行单元测试 Example int func int a boolean find Some code find func 1 return fin
  • 为什么我的应用程序因“多任务应用程序只能使用后台”而被拒绝?

    我通过设置闹钟并观看视频在后台测试了我的应用程序 当我观看视频时 我的闹钟正确响起 即使我从后台删除我的应用程序 警报仍然响起 现在我想知道我是否正确理解了苹果的回复 任何人都可以解码回复吗 我们发现您的应用程序使用后台模式但不包括 需要该
  • 将属性文件包含在 Jar 文件中

    我写了一个小应用程序 我已将数据库特定信息放入属性文件中 db url jdbc mysql localhost 3306 librarydb db user root db passwd pas w0rd 当我构建应用程序以获取可执行 j
  • Powershell:冻结 GUI

    只是快一点 我创建的一个简单工具有一个问题 该工具通过一个小框获取一段时间内的 CPU 使用情况 该小框似乎显示正在使用的 CPU 百分比 我已经删除了下面代码的 GUI function loop get read host for st
  • 在opencv c++上检测运动(移动相机)

    我正在为大学做一个项目 并且正在使用 OpenCV 这真的很棒 现在我的问题是 我有一个视频 avi 并且已检测到我想了解的有关突然出现在红色和黄色之间的 RGB 范围内的斑点的所有信息 在我实现了一个保存有关像素值的所有信息的矩阵之后 最
  • SIMD:位包有符号整数

    可以使用 位打包 技术来压缩无符号整数 在无符号整数块中 仅存储有效位 从而当块中的所有整数都 小 时进行数据压缩 该方法被称为FOR https www elastic co blog frame of reference and roa