微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

有没有办法用avx2自动替换avx512?

如何解决有没有办法用avx2自动替换avx512?

根据 Linus Torvalds 的建议(和跨平台性能),我不想使用 avx512。是否有我可以向编译器(gcc 和 msvc)指定的标志,以便如果我正在使用的库尝试从内在函数或编译器优化中使用 axv512,则所有 avx512 指令都被拆分为成对的 avx2 指令?

解决方法

不,首先通过告诉编译器不能使用 AVX-512 来编译您的代码;您只需使用需要 AVX-512 的内在函数对代码执行任何操作。


但是,如果您正在为支持 AVX-512 的 CPU 进行编译,通常值得使用它,尤其是使用 256 位向量以避免 turbo-frequency and other penalties that come with 512-bit vectors对于像 -mprefer-vector-width=256 这样的 CPU,GCC 的默认调整已经是 -march=skylake-avx512

如果你想制作一个可以在没有 AVX-512 的 CPU 上运行的二进制文件,那么是的,显然你需要确保它永远不会执行,并且没有它的指令会出错。例如gcc -O3 -march=znver2-march=skylake 或其他。这些目标架构选项都不包括 AVX-512。或者 -march=native,如果针对您拥有的任何 CPU 进行编译。

但是如果您确实有一个支持 AVX-512 的 CPU,并且您不想使用它,则可以使用类似 -march=native -mno-avx512f(所有其他 AVX-512 扩展依赖于“Foundation” AVX-512F,因此禁用它也会阻止 128 和 256 位向量的 AVX-512VL。)

(使用 -march=native 然后禁用某些东西的部分好处是还可以设置调整选项。如果您想要一个在 Skylake 和 Zen2 上都运行良好的二进制文件,我不知道该推荐什么;可能 { {1}} 或 -march=skylake 都可以;有默认的“tune=generic”,但它太在意那些甚至不支持 AVX2 的老式 CPU,比如 Sandybridge:Why doesn't gcc resolve _mm256_loadu_pd as single vmovupd?)>


内在函数

即使使用内部函数,GCC 也只会发出目标选项支持的指令,因此 -march=znver2 可以让您确保没有遗漏任何内容。你会得到编译时错误,而不是漏掉的 EVEX 指令。

(MSVC 是不同的,它是围绕单二进制模型设计的,其中使用新指令集是在只有 CPU 支持时才调用的函数中完成的,因此它不会阻止您使用 AVX-512。AFAIK,MSVC 仍然没有使用 AVX-512 自动矢量化的选项,只有 -mno-avx512f。但无论如何,如果你不告诉它,MSVC 不会自己发出 AVX-512 指令,如果您不使用 /arch:AVX2 之类的任何选项,如果存在这样的东西;不幸的是,AFAIK 它没有 /arch:AVX512。使用 MSVC,您必须确保您掌握了内在函数的所有用途,尽管使用 GCC 进行编译有助于确保您的代码库不会这样做。)

如果您仍然想编译使用 /arch:native_mm512_add_epi32 或其他的代码,您需要一个 immintrin.h 版本,它将 _mm256_ternlog_epi32 定义为具有两个__m512i 成员并模拟所有内在函数。 某些 AVX512 内在函数的模拟成本并不低,尤其是掩码操作, 以及比较掩码的整个概念以获得整数而不是向量。所以试图让这一切完全透明地发生可能是一个坏主意;而只是让 GCC 阻止您使用任何 AVX-512 指令,同时您制作任何尚未拥有 AVX2 版本的内在代码的仅 AVX2 版本。

上次出现这个问题时,Coding on insufficient hardware,我找到了一个 __m256i,让您可以为 AVX 进行开发,同时只为 SSE4 进行编译。但我没有找到 AVX-512 的等价物。 (通常,您会编译一个 AVX-512 二进制文件并在像 SDE 这样的模拟器上测试它,该模拟器在运行时而不是编译时进行模拟。)

Agner Fog 的 VectorClass 包装器库 (https://www.agner.org/optimize/#vectorclass) 支持基本操作,如 + - * /、随机播放和混合,并具有用一对 AVX2 向量模拟的 512 位向量版本。 (并且 VCL 类型可以隐式转换为 __m256i 或 __m512i 等等,因此对于它没有自己的函数的操作,您可以使用 Intel 内在函数。但是,您又回到了需要模拟库的同一条船上avxintrin-emu.h 仅包含 AVX2 指令。)


这不会阻止 libc 在 __m256_ternlog_epi32strcmp/log 等函数中使用手写的 AVX-512 指令,因为动态 CPU 调度发生在运行时,并且您无法阻止 CPU 报告它支持 AVX-512。 (除了虚拟机,或者告诉内核不要在启动时启用 AVX-512,如果 Linux 有一个选项。)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。