_mm256_loadu_epi64、_mm256_storeu_epi64 需要 avx512vl?
_mm256_loadu_epi64, _mm256_storeu_epi64 require avx512vl?
第一次使用 avx2 内在函数(在支持 avx2 的系统上,但不 avx512)。
无论是从原型还是我从 intel intrinsics 参考中获得的信息,我都认为 _mm256_loadu_epi64
和 _mm256_storeu_epi64
是 avx512 函数。
但是如果我只用 -mavx2
编译代码,我会得到编译器错误。另一方面,如果我使用 -mavx512vl
进行编译(根据编译器错误的建议),它会编译并且 似乎 可以工作。但是,如果我选择 avx512...
,我当然会担心编译器在程序的其余部分可能会做什么
按照我认为应该为我的 avx2 机器编译的方式进行编译:
clang++ -std=c++17 -O2 -mavx2 -o storeload dummy.cpp
dummy.cpp:16:21: error: always_inline function
'_mm256_loadu_epi64' requires target feature 'avx512vl',
but would be inlined into function 'main' that is
compiled without support for 'avx512vl'
__m256i avx2reg = _mm256_loadu_epi64(&input[0]);
^
dummy.cpp:17:3: error: always_inline function
'_mm256_storeu_epi64' requires target feature 'avx512vl',
but would be inlined into function 'main' that is
compiled without support for 'avx512vl'
_mm256_storeu_epi64(&output[0],avx2reg);
^
2 errors generated.
编译但让我紧张:
clang++ -std=c++17 -O2 -mavx512vl -o storeload dummy.cpp
似乎有效:
./storeload
0x1111111111111111 == 0x1111111111111111 ?
0x2222222222222222 == 0x2222222222222222 ?
0x3333333333333333 == 0x3333333333333333 ?
0x4444444444444444 == 0x4444444444444444 ?
编译器是
clang --version
Debian clang version 11.0.1-2
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
测试代码为
#include <cstdint>
#include <array>
#include <cinttypes>
#include <iostream>
#include <immintrin.h>
int main(int argc, const char* argv[]) {
std::array<uint64_t,4> input
{ UINT64_C(0x1111111111111111),
UINT64_C(0x2222222222222222),
UINT64_C(0x3333333333333333),
UINT64_C(0x4444444444444444) };
std::array<uint64_t,4> output;
output.fill(UINT64_C(0));
__m256i avx2reg = _mm256_loadu_epi64(&input[0]);
_mm256_storeu_epi64(&output[0],avx2reg);
std::cout << std::hex << std::showbase;
for (size_t i=0; i < input.size(); i++) {
std::cout << input[i] << " == " << output[i] << " ?" << std::endl;
}
return 0;
}
问题
- 是否是编译器错误,在只有 avx2 应该做的情况下要求 avx512?
- 当我启用 avx512 时,如何确保代码(还有更多代码,未在此最小示例中显示)不会在我的 avx2 系统上崩溃?
- 是否有我 could/should 使用的替代函数?
- 是否有备用
-m
标志我应该使用但尚未找到?
使用 _mm256_loadu_si256((const __m256i*) ptr)
和 _mm256_storeu_si256
,另请参阅
那些具有更好 arg 类型(void*
而不是 __m256i*
)的内在函数是与其他 AVX-512 内在函数一起引入的,但是执行 256 位加载的最有效方法是使用 AVX1 vmovdqu
或 vmovups
(或任何指令的内存源操作数)。这就是为什么 clang 最终生成的代码可以 运行 在你的 CPU 上。 (用反汇编器或clang -march=native -O3 foo.cpp -S -o - | less
检查asm输出)
不幸的是,clang 甚至不允许您在不启用 AVX-512VL 的情况下使用 void*
版本,因为它们不会做任何只能用 AVX-512 实现的事情;只有像 _mm256_mask_storeu_epi64
这样的 intrinsics for vmovdqu64
的屏蔽版本才真正有意义,其中 epi64
元素大小具有任何意义(屏蔽粒度)。
如果您的 CPU 不支持 ,那么使用 -mavx512vl
不 是安全的。 (Skylake-X、冰湖等)。 clang 可能已经决定实际使用它,例如使用 ymm15..31 避免 vzeroupper,或将一对按位布尔内在函数编译为 vpternlogd
,或将 _mm256_set1_epi32
折叠为 vpaddd
的广播内存源操作数(_mm256_add_epi32
).
或者作为错过的优化(更大的代码大小),实际使用 vmovdqu64
而不是 vmovdqu
来加载存储 ymm0..15。 GCC has/had 这个 bug 有一段时间了。
Why is the prefix _mm256 and not _mm512 on the functions I use?
AVX-512VL(VL=向量长度)的重点是 AVX-512 引入的很酷的新东西的 128 位和 256 位版本,例如屏蔽存储和屏蔽寄存器写入,矢量寄存器数量是原来的两倍,广播内存源操作数而不需要单独的 vpbroadcastd
加载等
第一次使用 avx2 内在函数(在支持 avx2 的系统上,但不 avx512)。
无论是从原型还是我从 intel intrinsics 参考中获得的信息,我都认为 _mm256_loadu_epi64
和 _mm256_storeu_epi64
是 avx512 函数。
但是如果我只用 -mavx2
编译代码,我会得到编译器错误。另一方面,如果我使用 -mavx512vl
进行编译(根据编译器错误的建议),它会编译并且 似乎 可以工作。但是,如果我选择 avx512...
按照我认为应该为我的 avx2 机器编译的方式进行编译:
clang++ -std=c++17 -O2 -mavx2 -o storeload dummy.cpp
dummy.cpp:16:21: error: always_inline function
'_mm256_loadu_epi64' requires target feature 'avx512vl',
but would be inlined into function 'main' that is
compiled without support for 'avx512vl'
__m256i avx2reg = _mm256_loadu_epi64(&input[0]);
^
dummy.cpp:17:3: error: always_inline function
'_mm256_storeu_epi64' requires target feature 'avx512vl',
but would be inlined into function 'main' that is
compiled without support for 'avx512vl'
_mm256_storeu_epi64(&output[0],avx2reg);
^
2 errors generated.
编译但让我紧张:
clang++ -std=c++17 -O2 -mavx512vl -o storeload dummy.cpp
似乎有效:
./storeload
0x1111111111111111 == 0x1111111111111111 ?
0x2222222222222222 == 0x2222222222222222 ?
0x3333333333333333 == 0x3333333333333333 ?
0x4444444444444444 == 0x4444444444444444 ?
编译器是
clang --version
Debian clang version 11.0.1-2
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
测试代码为
#include <cstdint>
#include <array>
#include <cinttypes>
#include <iostream>
#include <immintrin.h>
int main(int argc, const char* argv[]) {
std::array<uint64_t,4> input
{ UINT64_C(0x1111111111111111),
UINT64_C(0x2222222222222222),
UINT64_C(0x3333333333333333),
UINT64_C(0x4444444444444444) };
std::array<uint64_t,4> output;
output.fill(UINT64_C(0));
__m256i avx2reg = _mm256_loadu_epi64(&input[0]);
_mm256_storeu_epi64(&output[0],avx2reg);
std::cout << std::hex << std::showbase;
for (size_t i=0; i < input.size(); i++) {
std::cout << input[i] << " == " << output[i] << " ?" << std::endl;
}
return 0;
}
问题
- 是否是编译器错误,在只有 avx2 应该做的情况下要求 avx512?
- 当我启用 avx512 时,如何确保代码(还有更多代码,未在此最小示例中显示)不会在我的 avx2 系统上崩溃?
- 是否有我 could/should 使用的替代函数?
- 是否有备用
-m
标志我应该使用但尚未找到?
使用 _mm256_loadu_si256((const __m256i*) ptr)
和 _mm256_storeu_si256
,另请参阅
那些具有更好 arg 类型(void*
而不是 __m256i*
)的内在函数是与其他 AVX-512 内在函数一起引入的,但是执行 256 位加载的最有效方法是使用 AVX1 vmovdqu
或 vmovups
(或任何指令的内存源操作数)。这就是为什么 clang 最终生成的代码可以 运行 在你的 CPU 上。 (用反汇编器或clang -march=native -O3 foo.cpp -S -o - | less
检查asm输出)
不幸的是,clang 甚至不允许您在不启用 AVX-512VL 的情况下使用 void*
版本,因为它们不会做任何只能用 AVX-512 实现的事情;只有像 _mm256_mask_storeu_epi64
这样的 intrinsics for vmovdqu64
的屏蔽版本才真正有意义,其中 epi64
元素大小具有任何意义(屏蔽粒度)。
如果您的 CPU 不支持 ,那么使用 -mavx512vl
不 是安全的。 (Skylake-X、冰湖等)。 clang 可能已经决定实际使用它,例如使用 ymm15..31 避免 vzeroupper,或将一对按位布尔内在函数编译为 vpternlogd
,或将 _mm256_set1_epi32
折叠为 vpaddd
的广播内存源操作数(_mm256_add_epi32
).
或者作为错过的优化(更大的代码大小),实际使用 vmovdqu64
而不是 vmovdqu
来加载存储 ymm0..15。 GCC has/had 这个 bug 有一段时间了。
Why is the prefix _mm256 and not _mm512 on the functions I use?
AVX-512VL(VL=向量长度)的重点是 AVX-512 引入的很酷的新东西的 128 位和 256 位版本,例如屏蔽存储和屏蔽寄存器写入,矢量寄存器数量是原来的两倍,广播内存源操作数而不需要单独的 vpbroadcastd
加载等