纵观AVX2 intrinsic文档有聚集负载指令,如VPGATHERDD
:
__m128i _mm_i32gather_epi32 (int const * base, __m128i index, const int scale);
什么是不明确的,以我从文档计算负载地址是否是一个元素地址或字节地址,即在负载地址元素i
:
load_addr = base + index[i] * scale; // (1) element addressing ?
要么:
load_addr = (char *)base + index[i] * scale; // (2) byte addressing ?
从英特尔的文档 ,它看起来像它可能是(2),但是这并没有使给定的,对聚集的负荷最小元素尺寸是32位太大的意义-为什么你想从错位地址负载(即使用规模<4 )?
收集的指令没有任何对齐要求。 因此,这将是过于严格,不允许字节寻址。
另一个原因是一致性。 随着SIB解决我们显然有字节地址:
MOV eax, [rcx + rdx * 2]
由于VPGATHERDD
只是这个的矢量变型MOV
指令,我们不应该指望什么用VSIB针对不同的:
VPGATHERDD ymm0, [rcx + ymm2 * 2], ymm3
至于现实生活中的使用字节寻址,我们可以有一个24位彩色图像每个像素排列的3个字节。 我们可以加载8个像素单VPGATHERDD指令,但只有在VSIB“规模”字段为“1”和VPGATHERDD
使用字节寻址。
由英特尔在描述来看可在这里AVX编程参考文档 ,它看起来像聚集指令使用字节寻址。 具体而言,看到从的描述以下引号VPGATHERDD
指令(389页):
DISP: optional 1, 2, 4 byte displacement; DATA_ADDR = BASE_ADDR + (SignExtend(VINDEX[i+31:i])*SCALE + DISP;
既然你可以使用1/2/4字节的位移,我将认为总体内存地址是一个字节地址。 虽然它可能不是一个普通的应用,有可能是情况下,你会想从一个未对齐的地址读取32位或64位值。 这是关于x86架构更灵活的一件事相比,类似ARM的时候; 您必须执行对齐访问,如果你想要的,而不是触发CPU异常,因为有些人做的灵活性。
为什么你想从错位地址(即使用规模<4)加载?
错位负载不是唯一的用例为尺度<元件尺寸。 你可能只是被预分频的字节偏移指数。 或者考虑过指针结构数组向量化的循环:你可以为零的基地“地址”或一个小整数偏移量结构聚集。
支持这一用例是原因英特尔设计汇编指令来支持这一项,因为合应该帮助编译器自动向量化更多的代码。 它也自然地适合了VSIB字节非常接近SIB的机器代码的编码,但他们可以很容易地预偏置比例因子给你的规模= 4,8,16,32的选择(或8 ,16,32,64为qword的集)用2个位刻度字段。
规模因素除元件尺寸并不在许多情况下,显然无论是有用的,而且很容易与前聚集的单一左移指令以模拟。 不过, 就不可能解决一个烤入比例系数 ,因此允许非标度指数显然是更灵活的设计选择。
其他使用情况:收集16位元素。 使用一个32位的收集和之后的收集屏蔽掉每个元件的上半部分。 (或让它拿着垃圾)。 这将导致错位的负荷,如果你的任何指标都奇(为2的比例因子),所以,如果他们越过边界4K(不像真正的16位集)真实可能比较缓慢。
你也可以想像使用收集的解压功能,其中一些解码后,你有偏移向量到缓冲区中的一部分,并且要数据的任意4个字节或8个字节的窗口。