AVX2:U8的绝对差异

时间:2017-10-27 06:34:37

标签: sse simd neon avx avx2

我是AVX的新手(来自ARM NEON),并且令人不高兴的是,AVX缺少许多U8算术,绝对差异在于他们之间缺失。

因此我不得不使用内联函数求助max(a,b)-min(a,b)

static inline __m256i _mm256_abd_epu8(__m256i a, __m256i b)
{
    return _mm256_sub_epi8(_mm256_max_epu8(a, b), _mm256_min_epu8(a, b));
}

我很好奇是否有更有效的方法来处理这个问题。

是的,我知道_mm256_sad_epu8,但我自己需要差异,而不是总和。

我很感激任何输入,AVX2没关系,无视任何向后兼容性。

提前致谢。

1 个答案:

答案 0 :(得分:5)

我只知道只有2条或更少的指令才能做到这一点。 (这个问题的SSE版本也没有更好的:Compute the absolute difference between unsigned integers using SSE)。它确实提到了我在这个答案中使用的饱和方法。

在Skylake之前

稍微更好:用无符号饱和度减去两种方式,然后对结果进行OR运算。 (每个元素的a-b或b-a饱和为零。)

_mm256_or_si256(_mm256_subs_epu8(a,b), _mm256_subs_epu8(b,a))

在Haswell上,pmin / pmaxpsub仅在端口1或端口5上运行,但por可以在三个向量执行端口中的任何一个上运行(0 ,1,5)。

Skylake添加了第3个向量整数加法器,因此该uarch没有区别。 (请参阅http://agner.org/optimize/标记维基中的和其他链接,包括英特尔优化手册。)

对于Ryzen而言,这也略胜一筹,其中VPOR可以在任何P0123上运行,但PADD / PMIN只能根据Agner Fog的测试在P013上运行。 (Ryzen将256b矢量运算分成2个uop,但它的吞吐量很有用。它只能用单uop指令填充它的6-uop宽管道。)

可以在更多端口上运行的Uops不太可能被延迟等待其分配的端口(资源冲突),因此您更有可能实际获得2个周期的总延迟(从两个输入准备到输出准备好了)。如果竞争特定端口(例如端口5在英特尔Haswell及其后的唯一的随机播放单元),它们也不太可能导致吞吐量瓶颈。