c++ - 如何用 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 */
}
无需编写程序集,即仅使用可用的内在函数?
解决方案
_mm256_loadu_si256
像正常人一样使用。AVX512 内在给您的唯一东西是更好的原型(const void*
而不是const __m256i*
)。
@chtz 建议您可能仍想自己编写一个包装函数来获取void*
原型。但不要这样称呼它_mm256_loadu_epi32
;某些未来的 GCC 版本可能会添加它以与 Intel 的文档兼容并破坏您的代码。
您甚至不希望编译器vmovdqu32 ymm
在您不屏蔽时发出;vmovdqu ymm
更短并且做同样的事情,与 EVEX 编码指令混合没有任何惩罚。如果编译器想要加载到 ymm16..31 中,编译器始终可以使用vmovdqu32
or ,否则您希望它使用较短的 VEX 编码的 AVX1 。64
vmovdqu
我很确定 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 位加载内在函数(对齐与未对齐除外)都没有关系。
有关的:
推荐阅读
- java - 错误的 WebTarget 实现 SseEventSource
- php - Rails 中的脏方法等效于 PHP Codeignitor
- php - 从 Laravel factory() 获得意外响应导致分段错误(核心转储)
- python - 如何在文本中查找字符串并从文本中返回字符串?
- java - 如何将 CSV 文件数据存储到 Java 中的数组中?
- ios - 如何在 Swift 的 1 个字节上编码扩展的 ASCII/macOS Roman(字符从 128 到 255)?
- python - 根据特定键合并2个字典列表
- vb.net - 如何在 ESC/POS 打印机上打印阿拉伯语
- javascript - 在 a 中添加一个属性如果属性有值
- kubernetes - 如何将 yaml configmap 文件转换为 terraform