在 Visual Studio 2019版本16.3 我们为MSVC编译器的自动矢量器添加了AVX-512支持。这篇文章将展示一些例子,并帮助您在项目中启用它。
什么是自动矢量器?
编译器的 自动矢量器 分析用户源代码中的循环,并在可行和有利的情况下为向量化目标生成向量化代码。
static const int length = 1024 * 8; static float a[length]; float scalarAverage() { float sum = 0.0; for (uint32_t j = 0; j < _countof(a); ++j) { sum += a[j]; } return sum / _countof(a); }
例如,如果我使用 cl.exe/O2/fp:快速/arch:AVX2 针对AVX2,我得到以下程序集。第11-15行是使用ymm寄存器的矢量化循环。第16-21行用于计算标量值 总和 来自向量循环的向量值。请注意,向量循环的迭代次数仅为标量循环的1/8,这通常意味着性能的提高。
?scalarAverage@@YAMXZ (float __cdecl scalarAverage(void)): 00000000: push ebp 00000001: mov ebp,esp 00000003: and esp,0FFFFFFF0h 00000006: sub esp,10h 00000009: xor eax,eax 0000000B: vxorps xmm1,xmm1,xmm1 0000000F: vxorps xmm2,xmm2,xmm2 00000013: nop dword ptr [eax] 00000017: nop word ptr [eax+eax] 00000020: vaddps ymm1,ymm1,ymmword ptr ?a@@3PAMA[eax] 00000028: vaddps ymm2,ymm2,ymmword ptr ?a@@3PAMA[eax+20h] 00000030: add eax,40h 00000033: cmp eax,8000h 00000038: jb 00000020</span> 0000003A: vaddps ymm0,ymm2,ymm1 0000003E: vhaddps ymm0,ymm0,ymm0 00000042: vhaddps ymm1,ymm0,ymm0 00000046: vextractf128 xmm0,ymm1,1 0000004C: vaddps xmm0,xmm1,xmm0 00000050: vmovaps xmmword ptr [esp],xmm0</span> 00000055: fld dword ptr [esp] 00000058: fmul dword ptr [__real@39000000] 0000005E: vzeroupper 00000061: mov esp,ebp 00000063: pop ebp 00000064: ret
什么是AVX-512?
AVX-512是Intel推出的一系列处理器扩展,可增强 矢量化 通过将向量扩展到512位,将向量寄存器的数量增加一倍,并引入元素操作屏蔽。您可以使用可用变量isau检测对AVX-512的支持,如果找到对AVX-512的支持,该变量将为6或更大。这表示支持F(基本)指令,以及来自VL、BW、DQ和CD扩展的指令,这些扩展添加了额外的整数向量操作、128位和256位操作以及额外的AVX-512寄存器和掩蔽,以及用于检测与分散存储的地址冲突的指令。这些指令与 /arch:AVX512 如下所述。这些扩展在Windows官方支持的所有AVX-512处理器上都可用。关于AVX-512的更多信息可以在我们之前发布的以下博客文章中找到。
如何启用AVX-512矢量化?
/arch:AVX512 is 启用AVX-512支持的编译器开关,包括自动矢量化。使用此开关,自动矢量器可以使用AVX-512中的F、VL、BW、DQ和CD扩展指令对循环进行矢量化。
要在启用AVX-512矢量化的情况下构建应用程序,请执行以下操作:
- 在VisualStudioIDE中,您可以添加标志/arch:AVX512 to 项目属性页> C/C++ >命令行>附加选项文本框或打开/arch:AVX512 by 选择高级向量扩展512遵循ProjtProjts>配置属性> C/C++ >代码生成>启用增强指令集>高级向量扩展512(/arch:AVX512). 第二种方法在VisualStudio2019版本16.4中提供。
- 如果使用cl.exe从命令行编译,请添加标志/arch:AVX512 before 任何/链接选项。
如果我使用 cl.exe/O2/fp:快速/arch:AVX512 ,我将获得以下针对AVX-512的程序集。类似地,第7-11行是矢量化循环。注意,循环是用zmm寄存器而不是ymm寄存器矢量化的。随着zmmx寄存器宽度的扩大,AVX-512矢量循环的迭代次数仅为AVX2版本的一半。
?scalarAverage@@YAMXZ (float __cdecl scalarAverage(void)): 00000000: push ecx 00000001: vxorps xmm0,xmm0,xmm0 00000005: vxorps xmm1,xmm1,xmm1 00000009: xor eax,eax 0000000B: nop dword ptr [eax+eax] 00000010: vaddps zmm0,zmm0,zmmword ptr ?a@@3PAMA[eax] 0000001A: vaddps zmm1,zmm1,zmmword ptr ?a@@3PAMA[eax+40h] 00000024: sub eax,0FFFFFF80h 00000027: cmp eax,8000h 0000002C: jb 00000010 0000002E: vaddps zmm1,zmm0,zmm1 00000034: vextractf32x8 ymm0,zmm1,1 0000003B: vaddps ymm1,ymm0,ymm1 0000003F: vextractf32x4 xmm0,ymm1,1 00000046: vaddps xmm1,xmm0,xmm1 0000004A: vpsrldq xmm0,xmm1,8 0000004F: vaddps xmm1,xmm0,xmm1 00000053: vpsrldq xmm0,xmm1,4 00000058: vaddss xmm0,xmm0,xmm1 0000005C: vmovss dword ptr [esp],xmm0 00000061: fld dword ptr [esp] 00000064: fmul dword ptr [__real@39000000] 0000006A: vzeroupper 0000006D: pop ecx 0000006E: ret
闭幕词
对于这个版本,我们的目标是实现与/arch:AVX2 in 矢量化能力术语。在未来的版本中,我们还计划改进很多东西。例如,我们的下一个AVX-512改进将利用新的屏蔽指令。随后的更新将支持VL扩展中的嵌入式广播、分散、128位和256位AVX-512指令。
一如既往,我们希望听到您的反馈,并鼓励您 下载 Visual Studio 2019 尝试一下。如果您遇到任何问题或对我们有任何建议,请让我们通过 帮助>发送反馈>报告问题/建议功能 在Visual Studio IDE中,或通过 开发者社区 ,或 推特@visualc .