【问题标题】:How do the AVX(2) gather instructions actually compute the fetch address?AVX(2) 收集指令如何实际计算提取地址?
【发布时间】:2021-06-23 13:12:15
【问题描述】:

_mm_i32gather_epi32() 的当前 Intel 内在函数指南将每个子字的计算地址描述为:

addr := base_addr + SignExtend64(vindex[m+31:m]) * ZeroExtend64(scale) * 8

最后 8 个让我感到困惑。假设 addr 和 base_addr 以字节为单位,scale 的值是 1、2、4 或 8,那么您只能从基地址开始索引 8 个字节的步长。这是文档中的错误,还是我遗漏了什么?我检查的所有收集指令的描述方式都相同。

A previous question 引用了没有 8 的文档,这表明发生了一些变化。

【问题讨论】:

  • 看起来像是英特尔指令指南中的错字。 SDM 没有为 VPGATHERDD 提及任何固定的 8 乘数。
  • 嗯,浪费了两个小时!
  • Intels [x:y] 索引总是引用比特数。

标签: c++ simd intrinsics avx avx2


【解决方案1】:

注意伪代码的下一行:

dst[i+31:i] := MEM[addr+31:addr]

显然有人认为将内存地址描述为位地址而不是字节地址是个好主意。 /掌心。这真的没有意义,不是任何人所期望的,甚至没有做对,因为他们未能将 base_addr 缩放 8。所以他们正在向字节地址添加位偏移量。

这只是糟糕的文档,并且是比链接问题中引用的先前版本更糟糕的描述方式。这只是文档更改,而不是对代码含义的更改,您可以尝试编译它并查看 asm 以查看生成的实际指令。 (我对您链接的问题的回答仍然是正确的:asm 指令允许比例因子为 1、2、4 或 8,因为 2 位移位计数的编码方式与标量指令对缩放索引寻址模式的编码方式相同。所以你可以使用字节偏移向量。)

之前更好的伪代码是:

dst[i+31:i] := MEM[base_addr + SignExtend(vindex[i+31:i])*scale]

所以MEM[](虚拟地址空间)使用计算的字节偏移量进行索引,访问宽度是dst[31:0] 位宽度所暗示的32 位。


根据经验,内在函数通常尽可能直接映射到 asm 指令。 他们不会选择以需要编译器发出 vpslld ymm0, ymm1, 3 的方式来定义它。在运行vpgatherdd之前缩放索引寄存器。

因此您可以查阅 asm 指令的文档(有时会有不同的伪代码,例如本例):https://www.felixcloutier.com/x86/vpgatherdd:vpgatherqd

...
    DATA_ADDR←BASE_ADDR + (SignExtend(VINDEX1[i+31:i])*SCALE + DISP;
    IF MASK[31+i] THEN
        DEST[i +31:i]←FETCH_32BITS(DATA_ADDR); // a fault exits the instruction
    FI;

【讨论】:

  • 是的,我对位地址与字节地址有相同的想法,但正如您所指出的,它对基地址没有意义。如此高调的文件有点令人毛骨悚然。谢谢!
  • @HenryGomersall:您可以在英特尔论坛上提交有关文档的错误报告,我认为其中有一部分用于报告此类内容(及其编译器)。 IDK 如果有关于内在函数指南的更直接反馈链接。
  • 点击“?”搜索栏旁边提供了这个链接:software.intel.com/en-us/forums/topic/363747
猜你喜欢
  • 1970-01-01
  • 2013-04-18
  • 2014-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-27
  • 2021-09-14
  • 2021-07-24
相关资源
最近更新 更多