g++
正在生成额外的移动指令,我不知道为什么。 Godbolt link
这发生在 _mm512_dpbusds_epi32 附近固有的。该指令计算 8 位点积,然后将它们添加到打包的 32 位累加器(在本例中为饱和加法)。该指令有点不寻常,因为它同时读取和写入累加器。
当使用 gcc 编译时,编译器会在累加器上发出额外的移动指令 ( vmovdqa64
)。
这是一个累积一些点积的测试程序:
#include <immintrin.h>
#include <cstddef>
__m512i Slow(const __m512i *a, const __m512i b0, const __m512i b1, std::size_t count) {
__m512i c0 = _mm512_setzero_epi32();
__m512i c1 = _mm512_setzero_epi32();
for (std::size_t i = 0; i < count; ++i) {
c0 = _mm512_dpbusds_epi32(c0, a[i], b0);
c1 = _mm512_dpbusds_epi32(c1, a[i], b1);
}
// Do not optimize away
return _mm512_sub_epi32(c0, c1);
}
使用
g++ -O3 -mavx512vnni example.cc -S
编译时,这是主循环:.L3:
vmovdqa64 (%rdi), %zmm6
vmovdqa64 %zmm3, %zmm0
vmovdqa64 %zmm4, %zmm2
addq $64, %rdi
vpdpbusds %zmm5, %zmm6, %zmm0
vpdpbusds %zmm1, %zmm6, %zmm2
vmovdqa64 %zmm0, %zmm3
vmovdqa64 %zmm2, %zmm4
cmpq %rdi, %rax
jne .L3
上面的程序集正在从
zmm3
复制一个累加器至 zmm0
, 更新 zmm0
,并将其复制回 zmm3
.这是不必要的;它应该只使用 zmm0
之一或 zmm3
作为蓄能器。问题在
g++ (Gentoo 9.2.0-r2 p3) 9.2.0
上是一样的和 g++ (Ubuntu 8.4.0-1ubuntu1~18.04) 8.4.0
.clang++
9.0.1 避免了不必要的复制(它还展开了循环,但这里是最紧凑的版本。).LBB0_6: # =>This Inner Loop Header: Depth=1
vmovaps (%rdi), %zmm4
vpdpbusds %zmm0, %zmm4, %zmm3
vpdpbusds %zmm1, %zmm4, %zmm2
addq $64, %rdi
addq $-1, %rax
jne .LBB0_6
我能够解决
g++
中的问题通过使用内联汇编。#include <immintrin.h>
#include <cstddef>
__m512i Fast(const __m512i *a, const __m512i b0, const __m512i b1, std::size_t count) {
__m512i c0 = _mm512_setzero_epi32();
__m512i c1 = _mm512_setzero_epi32();
for (std::size_t i = 0; i < count; ++i) {
asm ("vpdpbusds %2, %1, %0" : "+x"(c0) : "x"(a[i]), "mx"(b0));
asm ("vpdpbusds %2, %1, %0" : "+x"(c1) : "x"(a[i]), "mx"(b1));
}
// Do not optimize away
return _mm512_sub_epi32(c0, c1);
}
循环
g++
为 Fast
生成好多了:.L3:
#APP
# 7 "asm.cc" 1
vpdpbusds (%rdi), %zmm3, %zmm0
# 0 "" 2
# 8 "asm.cc" 1
vpdpbusds (%rdi), %zmm1, %zmm2
# 0 "" 2
#NO_APP
addq $64, %rdi
cmpq %rax, %rdi
jne .L3
最佳答案
回答我自己的问题。这是一个错误 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94663可能在集成的寄存器分配器中。
关于c++ - 为什么 gcc 会用 _mm512_dpbusds_epi32 添加额外的 vmovdqa64 指令?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61308501/