AVX 和 AVX2 的区别

Differences between AVX and AVX2

下面是 AVX2 中矩阵乘法的实现。我使用的机器只支持 AVX,所以我试图用 AVX 实现相同的配置。

但是,我很难理解真正的区别是什么,需要改变什么!此实现中有哪些特定于 AVX2 的内容不适用于只能处理 AVX 的机器?

这是对 AVX 和 AVX2 的所有命令的 link https://software.intel.com/sites/landingpage/IntrinsicsGuide/#techs=AVX

感谢您的任何见解!

 for (uint64_t i = 0; i < M; i++)
     {
         for (uint64_t j = 0; j < N; j++)
         {
             __m256 X = _mm256_setzero_ps();
             for (uint64_t k = 0; k < L; k+= 8) {
                 const __m256 AV = _mm256_load_ps(A+i*L+k);
                 const __m256 BV = _mm256_load_ps(B+j*L+k);
                 X = _mm256_fmadd_ps(AV,BV,X);
             }
             C[i*N+j] = hsum_avx(X);
         }
     }

您的代码使用 AVX1 + FMA 指令,而不是 AVX2。例如,在 AMD 打桩机上 运行 没问题。 (假设 hsum 以合理的方式实现,提取高半部分然后使用 128 位混洗。)

如果您的 AVX-only CPU 也没有 FMA,您需要使用 _mm256_mul_ps_mm256_add_ps


对于 Intel,AVX2 和 FMA 是在同一代 Haswell 中引入的,但是那些 不同的扩展。在没有 AVX2 的 CPU 中,FMA 可用。

不幸的是even a VIA CPU with AVX2 but not FMA, otherwise AVX2 implies FMA unless you're in a VM or

(在一些 AMD CPUs 中有一个 FMA4 扩展,有 4 个操作数(3 个输入和一个单独的输出),Bulldozer 到 Zen1,英特尔在 AMD 上拉了一个 switcheroo 来不及改变他们的 Bulldozer 设计支持 FMA3。这就是为什么只有 AMD 的 FMA4,以及为什么直到 Piledriver AMD 才支持与 Intel 兼容的 FMA 扩展。但那是现在历史的一部分,所以通常我们只是说FMA 以引用技术上称为 FMA3 的扩展。请参阅 Agner Fog 2009 年的博客 停止指令集warHow do I know if I can compile with FMA instruction sets?)


  • AVX1:仅限 256 位 FP(除 vptest, although FP in this case does include bitwise instructions like vxorps ymm). Shuffles are only in-lane (e.g. vshufps ymm or the new vpermilps) or with 128-bit granularity (vperm2f128 or vinsertf128 / vextractf128 外没有整数指令)。 AVX1 还提供所有 SSE1..4 指令的 VEX 编码,包括整数,具有 3 操作数非破坏性。例如vpsubb xmm0, xmm1, [rdi]
  • AVX2:整数 SSE 指令的 256 位版本,以及像 vpermps / vpermdvpermq / pd 以及带有寄存器的 vbroadcastss/sd ymm, xmm 等新的交叉洗牌来源(AVX1 只有 vbroadcastss ymm, [mem])。也是一种高效的 vpblendd 立即整数混合指令,如 vblendps
  • FMA3: vfmadd213ps x/ymm, x/ymm, x/ymm/mem 等等。 (以及 pd 和标量 ss/sd 版本)。还有 fmsub..(减去第 3 个操作数)、fnmadd..(乘积取反),甚至 fmaddsub...ps。 _mm256_fmadd_ps 将编译为某种形式的 vfmadd...ps,具体取决于编译器要覆盖哪个输入操作数,以及要将哪个操作数用作内存操作数。

这个介绍顺序解释了内部命名的错误选择,例如_mm256_permute_ps(立即)和 _mm256_permutevar_ps(矢量控制)是 AVX1 vpermilps 通道内置换,AVX2 背负着 _mm256_permutexvar_ps。令人困惑的是,内在函数有一个 x 用于车道交叉,而 asm 助记符很简单。