AVX2 Gather 指令使用细节
AVX2 Gather Instruction Usage Details
我正在尝试了解 AVX2 intel intrinsic 的收集功能。
根据官方文档Link,函数定义是,
__m256i _mm256_i32gather_epi32 (int const* base_addr, __m256i vindex, const int scale)
Gather 32-bit integers from memory using 32-bit indices. 32-bit elements are loaded from addresses starting at base_addr and offset by each 32-bit element in vindex (each index is scaled by the factor in scale). Gathered elements are merged into dst. scale should be 1, 2, 4 or 8.
因此,根据我的理解,它 returns 一个 __m256i 向量,其中填充了来自数组的 8 个整数,基索引 base_addr
来自 [= 中填充的索引 (8) 14=]。如果提到任何 scale
,那么它也会成倍增加。现在,为了测试理解我写了一个代码,
#include<stdio.h>
#include <immintrin.h>
int main()
{
__m256i var, ind_intel;
int * arr = (int *) aligned_alloc(sizeof(__m256i), sizeof(int) * 64);
int * out = (int *) aligned_alloc(sizeof(__m256i), sizeof(int) * 8);
int * ind = (int *) aligned_alloc(sizeof(__m256i), sizeof(int) * 8);
int i;
ind[0] = 0;ind[1] = 2;ind[2] = 4;ind[3] = 6;ind[4] = 8;ind[5] = 10;ind[6] = 12;ind[7] = 14;
ind_intel = _mm256_load_si256((__m256i *)&ind[0]);
for(i=0;i<64;i++)
arr[i] = i;
var = _mm256_i32gather_epi32(arr,ind_intel,1);
_mm256_store_si256((__m256i *)&out[0], var);
for(i=0;i<8;i++)
printf("%d ",out[i]);
return 0;
}
现在,__m256i
变量 ind_intel
获得索引 0,2,..,14
。主数组 arr
加载了 0,1,..,63
。因此,gather 应该将数据加载为 arr[0],arr[2],..,arr[14]
。但它正在打印值,
0 65536 1 131072 2 196608 3 262144
当然,我错过了一些重要的东西。但是我找不到任何网站或文档明确提到 gather 的用法。他们每个人都重复与官方文件相同的描述。谁能解释一下代码中的问题和理解?
N.B。该代码仅用于测试目的。
vindex
中的偏移量以字节为单位。因此,您从地址 {arr, arr+2, arr+4, ...}
收集 32 位整数值。将这些索引从 {0,2,4...}
更改为 {0,8,16,...}
,或将比例因子更新为:
var = _mm256_i32gather_epi32(arr,ind_intel, 4 ); // 1 -> 4
这会打印出预期值。
我更喜欢第二个选项,即更新比例因子。这基本上是它的目的——允许 vindex
中的索引具有相对于数据字节大小的逻辑偏移值,而不是字节偏移值。
我正在尝试了解 AVX2 intel intrinsic 的收集功能。
根据官方文档Link,函数定义是,
__m256i _mm256_i32gather_epi32 (int const* base_addr, __m256i vindex, const int scale)
Gather 32-bit integers from memory using 32-bit indices. 32-bit elements are loaded from addresses starting at base_addr and offset by each 32-bit element in vindex (each index is scaled by the factor in scale). Gathered elements are merged into dst. scale should be 1, 2, 4 or 8.
因此,根据我的理解,它 returns 一个 __m256i 向量,其中填充了来自数组的 8 个整数,基索引 base_addr
来自 [= 中填充的索引 (8) 14=]。如果提到任何 scale
,那么它也会成倍增加。现在,为了测试理解我写了一个代码,
#include<stdio.h>
#include <immintrin.h>
int main()
{
__m256i var, ind_intel;
int * arr = (int *) aligned_alloc(sizeof(__m256i), sizeof(int) * 64);
int * out = (int *) aligned_alloc(sizeof(__m256i), sizeof(int) * 8);
int * ind = (int *) aligned_alloc(sizeof(__m256i), sizeof(int) * 8);
int i;
ind[0] = 0;ind[1] = 2;ind[2] = 4;ind[3] = 6;ind[4] = 8;ind[5] = 10;ind[6] = 12;ind[7] = 14;
ind_intel = _mm256_load_si256((__m256i *)&ind[0]);
for(i=0;i<64;i++)
arr[i] = i;
var = _mm256_i32gather_epi32(arr,ind_intel,1);
_mm256_store_si256((__m256i *)&out[0], var);
for(i=0;i<8;i++)
printf("%d ",out[i]);
return 0;
}
现在,__m256i
变量 ind_intel
获得索引 0,2,..,14
。主数组 arr
加载了 0,1,..,63
。因此,gather 应该将数据加载为 arr[0],arr[2],..,arr[14]
。但它正在打印值,
0 65536 1 131072 2 196608 3 262144
当然,我错过了一些重要的东西。但是我找不到任何网站或文档明确提到 gather 的用法。他们每个人都重复与官方文件相同的描述。谁能解释一下代码中的问题和理解?
N.B。该代码仅用于测试目的。
vindex
中的偏移量以字节为单位。因此,您从地址 {arr, arr+2, arr+4, ...}
收集 32 位整数值。将这些索引从 {0,2,4...}
更改为 {0,8,16,...}
,或将比例因子更新为:
var = _mm256_i32gather_epi32(arr,ind_intel, 4 ); // 1 -> 4
这会打印出预期值。
我更喜欢第二个选项,即更新比例因子。这基本上是它的目的——允许 vindex
中的索引具有相对于数据字节大小的逻辑偏移值,而不是字节偏移值。