首页 > 解决方案 > 如何获得 AVX512_FP16 标志支持?

问题描述

我的 CPU 支持各种东西

  -march=CPU[,+EXTENSION...]
                          generate code for CPU and EXTENSION, CPU is one of:
                           generic32, generic64, i386, i486, i586, i686,
                           pentium, pentiumpro, pentiumii, pentiumiii, pentium4,
                           prescott, nocona, core, core2, corei7, l1om, k1om,
                           iamcu, k6, k6_2, athlon, opteron, k8, amdfam10,
                           bdver1, bdver2, bdver3, bdver4, znver1, btver1,
                           btver2
                          EXTENSION is combination of:
                           8087, 287, 387, 687, mmx, sse, sse2, sse3, ssse3,
                           sse4.1, sse4.2, sse4, avx, avx2, avx512f, avx512cd,
                           avx512er, avx512pf, avx512dq, avx512bw, avx512vl,
                           vmx, vmfunc, smx, xsave, xsaveopt, xsavec, xsaves,
                           aes, pclmul, fsgsbase, rdrnd, f16c, bmi2, fma, fma4,
                           xop, lwp, movbe, cx16, ept, lzcnt, hle, rtm, invpcid,
                           clflush, nop, syscall, rdtscp, 3dnow, 3dnowa,
                           padlock, svme, sse4a, abm, bmi, tbm, adx, rdseed,
                           prfchw, smap, mpx, sha, clflushopt, prefetchwt1, se1,
                           clwb, avx512ifma, avx512vbmi, avx512_4fmaps,
                           avx512_4vnniw, avx512_vpopcntdq, clzero, mwaitx,
                           ospke, rdpid, ptwrite, cet, no87, no287, no387,
                           no687, nommx, nosse, nosse2, nosse3, nossse3,
                           nosse4.1, nosse4.2, nosse4, noavx, noavx2, noavx512f,
                           noavx512cd, noavx512er, noavx512pf, noavx512dq,
                           noavx512bw, noavx512vl, noavx512ifma, noavx512vbmi,
                           noavx512_4fmaps, noavx512_4vnniw, noavx512_vpopcntdq

然而,像__m256h inter;产生一个error: '__m256h' was not declared in this scope. 这是有道理的CPUID Flags: AVX512_FP16 + AVX512VL,因为 CPU 要求AVX512_FP16不在列表中。

如何获得AVX512_FP16支持?它是依赖于 CPU 版本还是可以通过补丁修复?

更新: 英特尔提到 AVX512_FP16 仅与 AVX512BW [检查] 一起支持。我正在使用-march=skylake-avx512which 编译常规__m512但在这些基于 FP16 的操作上特别失败。

标签: c++intelavx512

解决方案


主要答案

因为 AVX512FP16 是 AVX512 ISA 的扩展,所以它必须:

A) 内置明确的硬件支持。

B) 通过将类型提升为另一种合适的替代品,例如具有特定舍入/一致性代码的 fp32,在软件中进行仿真。

截至您发帖时,市场上还没有支持 AVX 512 FP16 的系统。

截至本文发布时(2022 年 2 月 10 日),市场上唯一支持的是英特尔第 12 代 K 系列 AlderLake CPU* 的 AVX512 P(性能)核心解决方法。

这些基于 Golden Cove 架构的 P 核支持 AVX512FP16*。

要在 C 或 C++ 中使用该指令,必须使用最新的编译器。我自己的测试表明 GCC-12、Clang-14 和 ICX 2022.0 都能够使用该指令。

如果您想使用官方支持的平台,可以选择等待英特尔至强蓝宝石急流,它仅基于 Golden Cove 内核并启用完整的 AVX512 ISA。

一段代码将被编译以利用来自 AVX512FP16 ISA 扩展的 FMA 指令,最后附有其使用说明。

使用 Alder Lake 的注意事项

*注意:只有在具有特定 BIOS/微代码修订版的特定供应商主板上禁用 Gracemont E 内核后,才能启用此功能。这不受英特尔的认可或支持

其原因主要是与 Gracemont 和 Golden Cove 核心之间的不同 ISA 以及进程固定有关(但这超出了这个问题的范围)

代码示例

gcc-12 fp16_FMA_avx512.c -O3 -march=sapphirerapids -mavx512fp16 -o avx512example.bin 如果您的平台支持该指令,则用于生成可执行文件

使用gcc-12 fp16_FMA_avx512.c -O3 -march=sapphirerapids -mavx512fp16 -o avx512example.S -S 生成一个汇编文件,显示指令本身的用法。

    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    /*
    Simple example of FP16 arithmetic with it's declaration
 
    NB: This uses Clang/GCC convention FP16 declarations due to near universal platform support.
    Any compiler that has yet to formally adopt ISO/IEC TS 18661-3:2015 (“Floating-point extensions for C”) will not support the type.    
    Known working x86_64 compilers as of Feb 08 2022 are:
    Clang/LLVM-14+
    GCC-12+
    Intel ICX Version 2022.0.0
     
    Known working architectures:
        Intel Alder-Lake [        *under certain conditions]
        Intel Sapphire Rapids
*/

int main(){

float seed = 1;
srand((time(0)));
int count = 31;
_Float16 factor = seed;

//primaries
_Float16 a=1.436;
_Float16 b=0.83546;

//arrays to be used for FMA
_Float16 alpha[32];
_Float16 delta[32];
_Float16 omega[32];

while (count>=0)
{
//fill the arrays with differing values
alpha[count]=(_Float16) (a*factor);
delta[count]=(_Float16) (b*factor);
omega[count]=(_Float16) (factor+(a*b));

factor = factor+b;
count--;
}

printf("Print the FMA of 3  _Float16's that are cast as Float\n");

while (count < 32){

omega[count]=(omega[count]*alpha[count])+delta[count];

count++;
}
printf("\n"); //clear last line

while (count>=0)
{
printf("%i %f \n", count, (float) omega[count]);
count--;
}



// 32 entry variable can be used: 512bit/16bits per variable = 32 variables
//c d e f g h i j k l m n o p q r s t u v w x y z aa ab ac ad ae af ag ah
}

推荐阅读