在英特尔架构指令集扩展编程参考的2.5.3节"广播"中我们学习的比AVX512(和骑士角落)有
用于编码一些加载操作指令的数据广播的位字段,即从存储器加载数据并执行一些计算或数据移动操作的指令.
例如,使用英特尔汇编语法,我们可以在存储的地址广播标量,rax然后乘以16浮点数zmm2并将结果写入zmm1这样的
vmulps zmm1, zmm2, [rax] {1to16}
Run Code Online (Sandbox Code Playgroud)
但是,没有内在的东西可以做到这一点.因此,使用内在函数,编译器应该能够折叠
__m512 bb = _mm512_set1_ps(b);
__m512 ab = _mm512_mul_ps(a,bb);
Run Code Online (Sandbox Code Playgroud)
一个指令
vmulps zmm1, zmm2, [rax] {1to16}
Run Code Online (Sandbox Code Playgroud)
但我没有观察到GCC这样做.我发现了一个GCC错误报告.
我观察到与GCC类似的FMA.例如,GCC 4.9不会崩溃_mm256_add_ps(_mm256_mul_ps(areg0,breg0) 为单个fma指令-Ofast.但是,GCC 5.1确实将它崩溃为一个单一的fma.至少有内在函数可以用FMA做到这一点,例如_mm256_fmadd_ps.但是没有例如_mm512_mulbroad_ps(vector,scalar)内在的.
海湾合作委员会可能会在某个时候解决这个问题,但在此之前,装配是唯
所以我的问题是如何在GCC中进行内联汇编?
我想我可能已经为上面的例子提出了GCC内联汇编的正确语法(但我不确定).
"vmulps (%%rax)%{1to16}, %%zmm1, %%zmm2\n\t"
Run Code Online (Sandbox Code Playgroud)
我真的在寻找这样的功能
static inline __m512 mul_broad(__m512 a, float b) {
return a*b;
}
Run Code Online (Sandbox Code Playgroud)
如果b在内存中指向rax它产生
vmulps (%rax){1to16}, %zmm0, %zmm0
ret
Run Code Online (Sandbox Code Playgroud)
如果b它在xmm1它产生
vbroadcastss …Run Code Online (Sandbox Code Playgroud) 我的问题是关于EVEX编码不四舍五入语义打包REG-REG的指令允许SAE控制(禁止所有的例外),如VMIN*,*VCVTT,VGETEXT*,VREDUCE*,VRANGE*等英特尔只全声明SAE-意识512位向量长度,例如
VMINPD xmm1 {k1}{z}, xmm2, xmm3
VMINPD ymm1 {k1}{z}, ymm2, ymm3
VMINPD zmm1 {k1}{z}, zmm2, zmm3{sae}
Run Code Online (Sandbox Code Playgroud)
但我没有看到为什么SAE不能应用于使用xmm或ymm寄存器的指令的原因.
在英特尔指令集扩展编程参考的第4.6.4章中, 表4-7表示在没有舍入语义位的指令中,EVEX.b指定应用SAE,并且位EVEX.L'L指定显式向量长度:
00b: 128bit (XMM)
01b: 256bit (YMM)
10b: 512bit (ZMM)
11b: reserved
Run Code Online (Sandbox Code Playgroud)
所以他们的组合应该是合法的.
然而,NASM汇编vminpd zmm1,zmm2,zmm3,{sae} 为62F1ED185DCB,即EVEX.L'L = 00b,EVEX.b = 1,由NDISASM 2.12反汇编为vminpd xmm1,xmm2,xmm3
NASM拒绝组装vminpd ymm1,ymm2,ymm3,{sae}
,NDISASM将62F1ED385DCB(EVEX.L'L = 01b,EVEX.b = 1)拆解为vminpd xmm1,xmm2,xmm3
我想知道Knights Landing CPU是如何执行的VMINPD ymm1, ymm2, ymm3{sae}
(组装为62F1ED385DCB,EVEX.L'L = 01b,EVEX.b = 1):
在AXV512DQ,我们发现_mm_cvttpd_epi64,例如在文件中avx512vldqintrin.h
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cvttpd_epi64 (__m128d __A) {
return (__m128i) __builtin_ia32_cvttpd2qq128_mask ((__v2df) __A,
(__v2di) _mm_setzero_si128(),
(__mmask8) -1);
}
Run Code Online (Sandbox Code Playgroud)
它将两个打包的64位浮点数(__m128d)转换为两个打包的64位整数(__m128i).还有_mm256_cvttpd_epi64用于将四个打包的64位浮点数(__m256d)转换为四个打包的64位整数(__m256i).
但是,很多机器都不支持AXV512DQ.所以我想知道一个穷人的最佳选择是什么.
我应该说我已经满意的解决方案仅适用于64位浮点数,可以无损转换为32位浮点数.
当 VM 迁移到不同的硬件时,是否可以通知在 Google Compute VM 上运行的应用程序?
我是一个应用程序 (HMMER) 的开发人员,该应用程序大量使用向量指令 (SSE/AVX/AVX-512)。我正在开发的版本在启动时探测其硬件以确定哪些向量指令可用并选择最佳集合。
我们一直在考虑在 Google Compute 和其他云引擎上运行我们的程序,一个问题是,如果 VM 在运行我们的程序时从一台物理机器迁移到另一台物理机器,新机器可能支持不同的指令,导致我们的程序要么崩溃,要么执行得比它更慢。
有没有办法在虚拟机迁移时通知在 Google 计算虚拟机上运行的应用程序?我发现的唯一相关信息是,您可以将 VM 设置为在迁移时执行关闭/重新启动序列,这会杀死任何当前正在执行的程序,但至少会让用户知道他们需要重新启动程序。
我受到了这个链接的启发 https://www.sigarch.org/simd-instructions-considered-harmful/来研究AVX512的表现.我的想法是使用AVX512掩码操作可以删除循环后的清理循环.
这是我正在使用的代码
void daxpy2(int n, double a, const double x[], double y[]) {
__m512d av = _mm512_set1_pd(a);
int r = n&7, n2 = n - r;
for(int i=-n2; i<0; i+=8) {
__m512d yv = _mm512_loadu_pd(&y[i+n2]);
__m512d xv = _mm512_loadu_pd(&x[i+n2]);
yv = _mm512_fmadd_pd(av, xv, yv);
_mm512_storeu_pd(&y[i+n2], yv);
}
__m512d yv = _mm512_loadu_pd(&y[n2]);
__m512d xv = _mm512_loadu_pd(&x[n2]);
yv = _mm512_fmadd_pd(av, xv, yv);
__mmask8 mask = (1 << r) -1;
//__mmask8 mask = _bextr_u32(-1, 0, r);
_mm512_mask_storeu_pd(&y[n2], mask, yv);
}
Run Code Online (Sandbox Code Playgroud)
我认为使用BMI1和/或BMI2指令可以生成具有更少指令的掩码.然而, …
编写ZMM寄存器可以使Skylake-X(或类似的)CPU无限期地处于最大涡流降低的状态。(SIMD指令可降低CPU频率并动态确定恶意AVX-512指令在何处执行)推测Ice Lake是类似的。
(解决方法:zmm16..31不是问题,据@ BeeOnRope的意见,我在报?是有用的,如果你的程序+库不包含SSE指令使用VZEROUPPER
所以这strlen的可以只使用vpxord xmm16,xmm16,xmm16和vpcmpeqb,与zmm16)
@BeeOnRope发布测试代码在RWT线:更换vbroadcastsd zmm15, [zero_dp]同vpcmpeqb k0, zmm0, [rdi]为“弄脏”指令,看看是否能运行后循环慢或快。
我假设执行任何512位uop都会暂时触发减少的turbo(同时关闭向量ALU uops的端口1,而512位uop实际上在后端),但问题是:CPU能否在其上恢复如果您vzeroupper仅在读取 ZMM寄存器后就从未使用过,您是否拥有?
(和/或以后的SSE或AVX指令是否会有过渡惩罚或错误的依赖关系?)
具体来说,这样的strlen使用insns vzeroupper在返回之前是否需要a ? (实际上,在任何实际的CPU上,和/或Intel记录的有关面向未来的最佳实践。)假定以后的指令可能包括非VEX SSE和/或VEX编码的AVX1 / 2,而不仅仅是GP整数,以防万一。这与使turbo减少的上256脏情况有关。
; check 64 bytes for zero, strlen building block.
vpxor xmm0,xmm0,xmm0 ; zmm0 = 0 using AVX1 implicit zero-extension
vpcmpeqb k0, zmm0, [rdi] ; 512-bit load + ALU, not micro-fused
;kortestq k0,k0 / …Run Code Online (Sandbox Code Playgroud) 我需要禁用 gcc 编译的代码中的所有 AVX512 扩展。原因是 Valgrind 在 AVX512 指令上卡住了。有没有办法用一个标志来做到这一点?
我知道如何单独禁用每个扩展(-mno-avx512f等-mno-avx512pf),但这很麻烦,因为不同的 gcc 版本支持这些扩展的不同子集。
我使用CMake。如果有一种方法可以使用 CMake 机器自动化标记,这也对我有用。
我正在将代码从 AVX2 重写为 AVX512。
我可以用来将单个浮点数广播到 _mm512 向量的等效项是什么?在 AVX2 中它是 _mm256_broadcast_ss() 但我找不到像 _mm512_broadcast_ss() 这样的东西。
如何指示 Visual C++ 编译器 (1926) 使用未初始化的__m512i寄存器。在下面的代码片段not(or(A,B))中计算了a ,内容dummy无关紧要。
__m512i dummy;
const __m512i n8 = _mm512_ternarylogic_epi64(dummy, A, B, 0x11);
Run Code Online (Sandbox Code Playgroud)
不知何故,编译器假定寄存器需要有一些内容,(它没有),并为以下生成昂贵且不必要的内存引用zmm0:
62 F1 7E 48 6F 45 00 vmovdqu32 zmm0,zmmword ptr [rbp]
62 F3 DD 48 25 C5 11 vpternlogq zmm0,zmm4,zmm5,11h
Run Code Online (Sandbox Code Playgroud)
ICC 19.0.1 了解这种情况并且不会生成vmovdqu32.
我试过什么:dummy用 0初始化替换为vmovdqu32:
C5 F1 EF C9 vpxor xmm1,xmm1,xmm1
Run Code Online (Sandbox Code Playgroud)
这仍然给出了不必要的指令和停顿。
因此问题是:如何指示 Visual C++ 编译器执行与 Intel 编译器相同的操作?只是不要初始化虚拟寄存器。
我想知道是否可以按照以下方式做一些事情:
vpcmpeqb %ymm16, %ymm17, %ymm16
Run Code Online (Sandbox Code Playgroud)
尝试使用 gcc 进行编译,我得到:
Assembler messages: Error: unsupported instruction `vpcmpeqb'
Run Code Online (Sandbox Code Playgroud)
AFAICT 这是不可能的felixcloutier说唯一的 EVEX 前缀指令cmpeq有一个掩码目的地,但可能我遗漏了一些东西,或者直接用字节编码来做到这一点。
谢谢!