arrays - 使用SIMD操作进行可变长度数组扩展

标签 arrays sse simd avx

我想使用 SIMD 内在函数进行以下数组扩展。 我有两个数组:

  • 聚类值 (v_i):10、20、30、40

  • 簇长度 (l_i):3, 2, 1, 2

我想创建一个包含值的结果数组:v_i 重复 l_i 次,即:

结果:1​​0、10、10、20、20、30、40、40。

如何使用 SIMD 内在函数计算此值?

最佳答案

如果输入数组大小最多为 8,输出数组大小最多为 16,并且字节为数组值,则可以通过 SIMD 对此进行优化。至少需要 SSSE3。可以将此方法扩展到更大的数组/元素,但效率会很快降低。

  1. 计算数组长度的前缀和。如果您将长度字节数组重新解释为单个 64 位 (32 位) 字,将其乘以 0x101010101010100,并将结果存储在 SIMD 寄存器中,则可以快速完成此操作。
  2. 用平均索引(前缀和数组的一半大小)填充索引数组(在单个 SIMD 寄存器中)。
  3. 对索引寄存器的每个字节执行二进制搜索以找到正确的索引(并行)。这可以通过使用 PSHUFB 指令提取前缀和寄存器的适当字节,使用 PCMPGTB(以及可选地使用 PCMPEQB)将提取的前缀值与字节数进行比较,然后添加/减去索引范围的一半来完成。
  4. (可选)用 0xff 填充索引寄存器中所有未使用的字节。
  5. 使用 PSHUFB 用索引寄存器索引的簇值数组中的值填充某些寄存器。

算法的主循环(二分查找)包含 PSHUFB、PCMPGTB 以及一些算术和逻辑运算。它被执行 log(input_array_size) 次,很可能是 2 或 3 次。

这是一个例子:

cluster value:      10 20 30 40
cluster length:      3  2  1  2
prefix sum:          0  3  5  6  8
indexes:             2  2  2  2  2  2  2  2  2  2  2  2  2  2  2  2
prefix value:        5  5  5  5  5  5  5  5  5  5  5  5  5  5  5  5
byte number:         0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
mask:               ff ff ff ff ff  0  0  0  0  0  0  0  0  0  0  0
indexes:             1  1  1  1  1  3  3  3  3  3  3  3  3  3  3  3
prefix value:        3  3  3  3  3  6  6  6  6  6  6  6  6  6  6  6
byte number:         0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
mask:               ff ff ff  0  0 ff  0  0  0  0  0  0  0  0  0  0
indexes:             0  0  0  1  1  2  3  3  3  3  3  3  3  3  3  3
length constrained:  0  0  0  1  1  2  3  3 ff ff ff ff ff ff ff ff
cluster value:      10 10 10 20 20 30 40 40  0  0  0  0  0  0  0  0

关于arrays - 使用SIMD操作进行可变长度数组扩展,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21293082/

相关文章:

javascript - 在双重嵌套 for 循环中组合变量

c++ - 使用 SIMD 对稀疏矩阵中的内部迭代器进行特征迭代

c++ - float4::set_wxy(和其他 set-swizzle 操作)的更好 SSE2 实现?

JavaScript 用空格分割字符串

c++ - 通过二叉树的数组表示的最小堆; MoveDown 函数无限循环

c - 计算大型 CRC32 的正确方法是什么

c - SSE操作可在2D数组上实现循环,其中每个输出取决于包含该数组的3x3正方形(生命游戏)

assembly - 将 64 位整数加载到 double SSE2 寄存器的最佳方法?

c++如何编写编译器可以轻松针对SIMD优化的代码?

android - c++ android ndk 使用数组