使用 SSE 进行打包 16 元素混合的最佳方法

Nic*_*ick 9 x86 assembly sse x86-64 intel

我想使用 SSE 实现以下功能。它将 a 中的元素与 b 中的压缩元素混合在一起,其中元素仅在使用时才存在。

void packedBlend16(uint8_t mask, uint16_t* dst, uint16_t const* a, uint16_t const* b) {
  for (int i = 0; b < 8; ++i) {
    int const control = mask & (1 << i);
    dst[i] = control ? a[i] : *b++;
  }
}
Run Code Online (Sandbox Code Playgroud)

对我来说棘手的部分是在向量中正确地间隔 b 的元素。

到目前为止,我的方法是:

  1. 256 个条目LUT[mask]以进行随机播放,将 b 的元素扩展到正确的位置pshufb
  2. 使用vpbroadcastw+ vpand+从蒙版构造混合向量vpcmpeqw
  3. pblendvb a 与洗牌的元素 b

我怀疑 256 个条目的 LUT 不是最好的方法。我可能有 2 16 个入口 LUT 用于高位/低位。但是您必须根据掩码的低 4 位的 popcnt 向高 LUT 添加偏移量。

我一次独立做 4 个,所以我想最大化吞吐量,但可以接受延迟。

我可以采取其他方法吗?

小智 -1

使用 pdep 指令将 b 的元素打包到连续的内存块中,使用 vpshufb 指令将 b 的元素打乱到正确的位置,使用 vpblendw 指令将 a 和 b 的元素混合在一起。