我正在研究Intel 内在指南中的扩展和压缩操作。 我对这两个概念感到困惑: 对于__m128d _mm_mask_expand_pd (__m128d src, __mmask8 k, __m128d a) == vexpandpd 从 a(在掩码 k 中设置相应位的元素)加载连续的活动双 ...
提示:本站收集StackOverFlow近2千万问答,支持中英文搜索,鼠标放在语句上弹窗显示对应的参考中文或英文, 本站还提供 中文繁体 英文版本 中英对照 版本,有任何建议请联系yoyou2525@163.com。
我需要执行以下两项操作:
float x[4];
float y[16];
// 1-to-4 broadcast
for ( int i = 0; i < 16; ++i )
y[i] = x[i / 4];
// 4-to-1 reduce-add
for ( int i = 0; i < 16; ++i )
x[i / 4] += y[i];
什么是有效的AVX-512实现?
对于reduce-add,只需进行vmovshdup
改组并添加( vmovshdup
/ vaddps
/ vpermilps imm8
/ vaddps
),就像在x86上进行水平浮点矢量和的最快方法一样, 以在每个128位通道中获取水平和,然后vpermps
将所需的元素vpermps
到底部。 或使用带有恒定掩码的vcompressps
做相同的事情,还可以选择使用内存目标。
打包成单个向量后,您将拥有一个普通的SIMD 128位加法。
如果您的数组实际上大于16,则可以使用vpermt2ps
而不是vpermps
从两个源向量中的每一个获取第4个元素,从而将+=
部分用于x[]
256位向量。 (或者再次与另一个改组合并为512位向量,但这可能会成为SKX上改组吞吐量的瓶颈)。
在SKX上, vpermt2ps
仅为单个uop,吞吐量为1c /延迟为3c,因此对于其强大功能而言非常有效。 在KNL上,它的吞吐量为2c,比vpermps
差,但也许仍然值得。 (KNL没有AVX512VL,但是如果需要,您(或编译器)可以将256位向量添加到x[]
,然后使用AVX1 vaddps ymm
。)
有关说明表,请参见https://agner.org/optimize/ 。
对于负载:
这是在循环内完成还是反复进行? (即,您可以将随机控制向量保存在寄存器中吗?如果可以,则可以
VBROADCASTF32X4
(用于加载端口的单个VBROADCASTF32X4
执行128-> 512广播。 vpermilps zmm,zmm,zmm
进行车道内混洗vpermilps zmm,zmm,zmm
以在每个128位通道中广播不同的元素。 (必须与广播负载分开,因为内存源vpermilps
可以具有m512
或m32bcst
源。(指令通常具有其内存广播粒度=元素大小,不幸的是,在某些情况下,这样的情况根本没有) vpermilps
将控制向量作为内存操作数,而不是源数据。) 这是略好于vpermps zmm,zmm,zmm
因为洗牌有1周周期的延迟,而不是3(在SKYLAKE微架构-avx512)。
即使在循环之外,加载随机播放控制向量仍可能是您最好的选择。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.