gpt4 book ai didi

c++ - 为什么 gcc 会用 _mm512_dpbusds_epi32 添加额外的 vmovdqa64 指令?

转载 作者:行者123 更新时间:2023-12-01 14:07:05 32 4
gpt4 key购买 nike

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/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com