什么是加载在x64 YMM寄存器在任何位置什么有效的方式来加载x64 ymm注册与4分离双打?
i.e. i want to load for example 1, 6, 22, 43
均匀地隔开,即一组连续的双打
0 1 2 3 4 5 6 7 8 9 10 .. 100
And i want to load for example 0, 10, 20, 30
4双打
4双打最有效的方式
什么是加载在x64 YMM寄存器在任何位置什么有效的方式来加载x64 ymm注册与4分离双打?
i.e. i want to load for example 1, 6, 22, 43
均匀地隔开,即一组连续的双打
0 1 2 3 4 5 6 7 8 9 10 .. 100
And i want to load for example 0, 10, 20, 30
4双打
4双打最有效的方式
最简单的方法是VGATHERQPD,它是Haswell及其以上的AVX2指令。
VGATHERQPD ymm1, [rsi+xmm7*8], ymm2
在vm32x指定使用双字索引,从存储器空调由YMM2指定掩模收集双预cision FP值。有条件地收集的元素被合并到ymm1中。
这可以通过一条指令来实现。 这里ymm2
是具有最高位的屏蔽寄存器,指示是否应该将该值复制到ymm1
(不变)。 ymm7
包含具有比例因子的元素索引。
,使得施加于你的实施例中,它可能看起来像这样在MASM语法:
4双打即一组连续的双打的均匀间隔
0 1 2 3 4 5 6 7 8 9 10 .. 100 ---我想加载例如0,10,20,30
.data
.align 16
qqIndices dq 0,10,20,30
dpValues REAL8 0,1,2,3, ... 100
.code
lea rsi, dpValues
movapd ymm7, qqIndices
vpcmpeqw ymm1, ymm1 ; set to all ones
vgatherqpd ymm0, [rsi+xmm7*8], ymm1
现在ymm0
包含四个双打0,10,20,30 虽然,我还没有测试过。另外要提的是,这不一定是每种情况下最快的选择。值都分别聚集,这意味着,每个值需要一个内存访问,看到How are the gather instructions in AVX2 implemented
最近,我不得不做一些事情,需要一个真正的收集负载。 (即数据[索引[i]])。在Haswell上,
4 index loads + 2x movsd + 2x movhpd + vinsertf128
仍然明显快于ymm load + vgatherqpd
。所以即使在最好的情况下,4路聚集仍然会失去。虽然我没有尝试过8路收集。
最快的方法是使用这种方法。因此,OpCode方式中的“高效”将使用VGATHER
,而与执行时间相关的“高效”将是最后一个(到目前为止,让我们看看未来架构将如何执行)。
编辑:根据意见VGATHER
说明在Broadwell和Skylake上得到更快。
真棒回答,谢谢。 –
'VPGATHERDD'(8路聚集)比Haswell上的一系列'movd' /'pinsrd'慢。 Broadwell收集速度更快,Skylake更快。我不确定引爆点在哪里。另外,不要加载全部的矢量。使用'vpcmpeqw ymm1,ymm1'来产生常量。 –
我认为你必须寻找像GATHER一样的操作VGATHERQPD。
该指令有条件地从内存操作数(第二个操作数)指定的内存地址和使用qword索引中加载最多2个或4个双精度浮点值。内存操作数使用SIB字节的VSIB形式来指定通用寄存器操作数作为公共基址,指定相对于基址的索引数组的向量寄存器以及恒定比例因子。
请注意,这需要AVX2,因此不适用于拥有AVX但不包含AVX2的Sandy Bridge/Ivy Bridge。
当然可以。我忘了提这个。 – ErmIg
我们可以假设AVX2可用吗?或者您是否需要AVX专用解决方案? –
我的应用,我应该说,拥有AVX解决方案也不错。 –