首页 > 解决方案 > 如何用 gcc 或 clang 模拟 _mm256_loadu_epi32?

问题描述

英特尔的内在指南列出了内在_mm256_loadu_epi32

_m256i _mm256_loadu_epi32 (void const* mem_addr);
/*
   Instruction: vmovdqu32 ymm, m256
   CPUID Flags: AVX512VL + AVX512F
   Description
       Load 256-bits (composed of 8 packed 32-bit integers) from memory into dst.
       mem_addr does not need to be aligned on any particular boundary.
   Operation
   a[255:0] := MEM[mem_addr+255:mem_addr]
   dst[MAX:256] := 0
*/

但是 clang 和 gcc 不提供这个内在的。相反,他们avx512vlintrin.h只提供(在文件中)被屏蔽的版本

_mm256_mask_loadu_epi32 (__m256i, __mmask8, void const *);
_mm256_maskz_loadu_epi32 (__mmask8, void const *);

归结为相同的指令vmovdqu32。我的问题:我该如何模仿_mm256_loadu_epi32

 inline _m256i _mm256_loadu_epi32(void const* mem_addr)
 {
      /* code using vmovdqu32 and compiles with gcc */
 }

无需编写程序集,即仅使用可用的内在函数?

标签: c++cintrinsicsavx512

解决方案


_mm256_loadu_si256像正常人一样使用。AVX512 内在给您的唯一东西是更好的原型(const void*而不是const __m256i*)。

@chtz 建议您可能仍想自己编写一个包装函数来获取void*原型。但不要这样称呼它_mm256_loadu_epi32;某些未来的 GCC 版本可能会添加它以与 Intel 的文档兼容并破坏您的代码。


您甚至不希望编译器vmovdqu32 ymm在您不屏蔽时发出;vmovdqu ymm更短并且做同样的事情,与 EVEX 编码指令混合没有任何惩罚。如果编译器想要加载到 ymm16..31 中,编译器始终可以使用vmovdqu32or ,否则您希望它使用较短的 VEX 编码的 AVX1 。64vmovdqu

我很确定 GCC 的处理方式与您使用的 asm_mm256_maskz_epi32(0xffu,ptr)完全相同_mm256_loadu_si256((const __m256i*)ptr)并制作相同的 asm。它可以优化0xffu掩码并简单地使用未掩码的负载,但您的源代码中不需要额外的复杂性。

但不幸的vmovdqu32 ymm0, [mem]是,-march=skylake-avx512即使您编写_mm256_loadu_si256. 这是一个错过的优化,GCC 错误 89346

只要没有掩码,您使用哪个 256 位加载内在函数(对齐与未对齐除外)都没有关系。

有关的:


推荐阅读