使用
加载x64 ymm寄存器的最有效方法是什么4个均匀间隔的双倍,即一组连续的双打
0 1 2 3 4 5 6 7 8 9 10 .. 100
And i want to load for example 0, 10, 20, 30
在任何位置加倍4次
i.e. i want to load for example 1, 6, 22, 43
答案 0 :(得分:5)
最简单的方法是VGATHERQPD,它是Haswell及以上的AVX2指令。
VGATHERQPD ymm1, [rsi+xmm7*8], ymm2
使用vm32x中指定的双向索引,从ymm2指定的掩码条件下的内存中收集双精度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
包含4个双打0,10,20,30。
虽然,我还没有测试过。另外需要提及的是,这不一定是每种情况下最快的选择。这些值都是单独收集的,也就是说,每个值都需要一次内存访问,请参阅How are the gather instructions in AVX2 implemented
我最近不得不做一些需要真正聚集负载的事情。 (即数据[index [i]])。在Haswell上,
4 index loads + 2x movsd + 2x movhpd + vinsertf128
仍然明显快于ymm load + vgatherqpd
。所以即使在最好的情况下,4路聚集仍然会失败。我没有试过8路聚会。
最快的方法是使用这种方法。
OpCode方式中的“高效”将使用VGATHER
,与执行时间相关的“高效”将是最后一个(到目前为止,让我们看看未来的架构将如何执行)。
编辑:根据评论,VGATHER
指令在Broadwell和Skylake上的速度更快。
答案 1 :(得分:1)
我认为您必须寻找像VGATHERQPD这样的GATHER操作。
该指令有条件地从内存操作数(第二个操作数)指定的内存地址加载最多2或4个双精度浮点值,并使用qword索引。内存操作数使用SIB字节的VSIB形式指定通用寄存器操作数作为公共基数,相对于基数的索引数组的向量寄存器和常量比例因子。
请注意,这需要AVX2,因此不适用于具有AVX但不支持AVX2的Sandy Bridge / Ivy Bridge。