加载带有 64 个独立双精度的 x64 ymm 寄存器有什么有效的方法



加载x64 ymm寄存器的最有效方法是什么

  1. 4 个均匀分布的双打,即一组连续的双打

    0  1  2  3  4  5  6  7  8  9 10 .. 100
    And i want to load for example 0, 10, 20, 30
    
  2. 任何位置4次双打

    i.e. i want to load for example 1, 6, 22, 43
    

最简单的方法是VGATHERQPD,它是Haswell及更高版本可用的AVX2指令。

VGATHERQPD ymm1, [rsi+xmm7*8], ymm2

使用 vm32x 中指定的 dword 索引,从以 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包含四个双打 0、10、20、30。不过,我还没有测试过这个。另一件值得一提的事情是,这不一定是每种情况下最快的选择。这些值都是单独收集的,这意味着每个值都需要一次内存访问,请参阅 AVX2 中的收集指令是如何实现

所以根据神秘客的评论

我最近不得不做一些需要真正收集负载的事情。(即数据[索引[i]](。在哈斯韦尔,4 index loads + 2x movsd + 2x movhpd + vinsertf128仍然比ymm load + vgatherqpd快得多。因此,即使在最好的情况下,4 向聚集仍然会失败。不过我还没有尝试过 8 向收集。

最快的方法是使用这种方法。

因此,OpCode方式的"高效"将使用VGATHER,而与执行时间相关的"高效"将是最后一个(到目前为止,让我们看看未来的架构将如何表现(。

编辑:根据评论,VGATHER指令在布罗德韦尔和Skylake上变得更快。

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

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

请注意,这需要 AVX2,因此不适用于具有 AVX 但不是 AVX2 的桑迪桥/常春藤桥。

相关内容

  • 没有找到相关文章

最新更新