4

如果我有一个 AVX 寄存器,其中有 4 个双精度数,并且我想将其反转存储在另一个寄存器中,是否可以使用单个内部命令来执行此操作?

例如:如果我在 SSE 寄存器中有 4 个浮点数,我可以使用:

_mm_shuffle_ps(A,A,_MM_SHUFFLE(0,1,2,3));

我可以这样做_mm256_permute2f128_pd()吗?我认为您不能使用上述内在函数来解决每个单独的双重问题。

4

2 回答 2

11

您实际上需要 2 个排列来执行此操作:

  • _mm256_permute2f128_pd()仅在 128 位块中置换。
  • _mm256_permute_pd()不会跨 128 位边界置换。

所以你需要同时使用:

inline __m256d reverse(__m256d x){
    x = _mm256_permute2f128_pd(x,x,1);
    x = _mm256_permute_pd(x,5);
    return x;
}

测试:

int main(){
    __m256d x = _mm256_set_pd(13,12,11,10);

    cout << x.m256d_f64[0] << "  " << x.m256d_f64[1] << "  " << x.m256d_f64[2] << "  " << x.m256d_f64[3] << endl;
    x = reverse(x);
    cout << x.m256d_f64[0] << "  " << x.m256d_f64[1] << "  " << x.m256d_f64[2] << "  " << x.m256d_f64[3] << endl;
}

输出:

10  11  12  13
13  12  11  10
于 2012-11-16T19:42:17.350 回答
4

AVX2新增了对粒度更细的 128 位的车道交叉洗牌的支持:

_mm256_permute4x64_pd(vec, _MM_SHUFFLE(0,1,2,3));  // i.e. 0b00011011

VPERMPD ymm1, ymm2/m256, imm8VPERM2F128以与英特尔 CPU 上的其他通道交叉洗牌(如 )相同的吞吐量和延迟运行。也在内在函数查找器中。

在 AMD Zen1(和Excavator)上,vpermpd比 2-input 更快vperm2f128。它们的向量 ALU 内部只有 128 位宽;256 位向量指令被解码为至少 2 个微指令,但车道交叉操作需要更多,尤其是可以读取 4 个总车道中的任何一个的操作。(不幸的是,解码器在为 vperm2f128 选择 uops 时不仅仅查看直接位)。Manual vextractf128/vinsertf128会比vperm2f128Bulldozer-family 和 Zen1 更好,但在其他任何地方都会很糟糕。https://uops.info/。我认为vpermpd在 Excavator / Zen1 上是最佳的,3 uops 与至少 4 到车道内倒车,然后用vextracti128/交换一半vinsert128


有一些 CPU 带有 FMA3 而不是 AVX2,例如 AMD Piledriver 和 Steamroller。在 Intel 上,AVX2 和 FMA 都是 Haswell 的新功能。AMD Bulldozer 系列已过时,但仍在家用计算机中,因此即使您的功能利用 AVX1 + FMA,您的选择也是需要 AVX2 并让这少数 CPU 退回到更糟糕的东西(例如,没有 FMA 的 AVX1) ,或制作另一个版本的函数。

于 2016-03-13T09:32:54.327 回答