2016-02-12 21 views
1

什么是加载在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双打

    1. 4双打最有效的方式

  • +0

    我们可以假设AVX2可用吗?或者您是否需要AVX专用解决方案? –

    +0

    我的应用,我应该说,拥有AVX解决方案也不错。 –

    回答

    5

    最简单的方法是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

    所以根据Mysticial's comment

    最近,我不得不做一些事情,需要一个真正的收集负载。 (即数据[索引[i]])。在Haswell上,4 index loads + 2x movsd + 2x movhpd + vinsertf128仍然明显快于ymm load + vgatherqpd。所以即使在最好的情况下,4路聚集仍然会失去。虽然我没有尝试过8路收集。

    最快的方法是使用这种方法。因此,OpCode方式中的“高效”将使用VGATHER,而与执行时间相关的“高效”将是最后一个(到目前为止,让我们看看未来架构将如何执行)。

    编辑:根据意见VGATHER说明在Broadwell和Skylake上得到更快。

    +1

    真棒回答,谢谢。 –

    +0

    'VPGATHERDD'(8路聚集)比Haswell上的一系列'movd' /'pinsrd'慢。 Broadwell收集速度更快,Skylake更快。我不确定引爆点在哪里。另外,不要加载全部的矢量。使用'vpcmpeqw ymm1,ymm1'来产生常量。 –

    1

    我认为你必须寻找像GATHER一样的操作VGATHERQPD

    该指令有条件地从内存操作数(第二个操作数)指定的内存地址和使用qword索引中加载最多2个或4个双精度浮点值。内存操作数使用SIB字节的VSIB形式来指定通用寄存器操作数作为公共基址,指定相对于基址的索引数组的向量寄存器以及恒定比例因子。

    请注意,这需要AVX2,因此不适用于拥有AVX但不包含AVX2的Sandy Bridge/Ivy Bridge。

    +0

    当然可以。我忘了提这个。 – ErmIg

    相关问题