在 AVX2 向量中加载 16 位整数?
Load 16 bit integers in AVX2 vector?
我是 AVX 编程新手。我想加载一个 __m256
具有 16 短整数或 16 位值的向量,但我无法这样做。
这是我的尝试。它给出以下错误:
incompatible types when initializing type ‘__m256’ using type ‘int’
__m256 result = _mm256_load_epi16((__m256*)&int_array);
#include <stdio.h>
#include <stdint.h>
#include <immintrin.h>
int main() {
int i;
short int int_array[16] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
__m256 result = _mm256_load_epi16((__m256*)&int_array);
short int* res = (short int*)&result;
printf("%d %d %d %d %d %d %d %d\n", res[0], res[1], res[2], res[3], res[4], res[5], res[6], res[7]);
return 0;
}
__m256i integer_vector = _mm256_load_si256((__m256*)int_array);
三个问题:
- 您忽略了编译器对
_mm256_load_epi16
的隐式声明警告,该警告不存在 。这就是为什么它抱怨从 int
. 初始化 __m256i
int_array
已经是指向第一个元素的指针。 &int_array
是指向指针的指针。你不想加载那个。
__m256
是一个包含 8 个浮点数的向量。你想要__m256i
。 (内在函数区分整数、浮点数和双精度向量。这与 asm 指令匹配:使用整数向量运算的结果作为 FP 向量运算的输入(反之亦然)会导致额外的旁路延迟延迟。这停止你不小心/不小心在整数数据上使用了 FP 洗牌。有时它仍然是值得的,这就是像 __m128 _mm_castsi128_ps(__m128i)
这样的函数存在的原因。)
loads/stores 没有具有不同整数元素大小的单独内在函数。这就是为什么您总是必须将那些烦人的转换写入 (__m256i*)
。 (AVX512 内在函数将采用 void*
args,这是一个更好的设计 IMO。)
Intel 的 intrinsics finder(https://software.intel.com/sites/landingpage/IntrinsicsGuide/) will help you find the functions you need. See also the sse tag wiki for guides, and the x86 tag wiki 有好东西。
第四个问题:您没有对齐数组,因此使用对齐加载内在函数是不安全的。您可以改用 loadu
内部函数。
第五题:
short int* res = (short int*)&result;
是个坏主意。不要将指针别名指向向量。将向量指针别名到数组上是可以的,因为 __m256i
是用 "may alias" 属性定义的。但是取消引用 (short int*)&result
是 C/C++ 未定义的行为,并且不会做你想做的(理论上或实践中)。
存储到临时数组,使用 _mm_extract_epi16
,或使用联合进行类型双关。
我是 AVX 编程新手。我想加载一个 __m256
具有 16 短整数或 16 位值的向量,但我无法这样做。
这是我的尝试。它给出以下错误:
incompatible types when initializing type ‘__m256’ using type ‘int’ __m256 result = _mm256_load_epi16((__m256*)&int_array);
#include <stdio.h>
#include <stdint.h>
#include <immintrin.h>
int main() {
int i;
short int int_array[16] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
__m256 result = _mm256_load_epi16((__m256*)&int_array);
short int* res = (short int*)&result;
printf("%d %d %d %d %d %d %d %d\n", res[0], res[1], res[2], res[3], res[4], res[5], res[6], res[7]);
return 0;
}
__m256i integer_vector = _mm256_load_si256((__m256*)int_array);
三个问题:
- 您忽略了编译器对
_mm256_load_epi16
的隐式声明警告,该警告不存在 。这就是为什么它抱怨从int
. 初始化 int_array
已经是指向第一个元素的指针。&int_array
是指向指针的指针。你不想加载那个。__m256
是一个包含 8 个浮点数的向量。你想要__m256i
。 (内在函数区分整数、浮点数和双精度向量。这与 asm 指令匹配:使用整数向量运算的结果作为 FP 向量运算的输入(反之亦然)会导致额外的旁路延迟延迟。这停止你不小心/不小心在整数数据上使用了 FP 洗牌。有时它仍然是值得的,这就是像__m128 _mm_castsi128_ps(__m128i)
这样的函数存在的原因。)
__m256i
loads/stores 没有具有不同整数元素大小的单独内在函数。这就是为什么您总是必须将那些烦人的转换写入 (__m256i*)
。 (AVX512 内在函数将采用 void*
args,这是一个更好的设计 IMO。)
Intel 的 intrinsics finder(https://software.intel.com/sites/landingpage/IntrinsicsGuide/) will help you find the functions you need. See also the sse tag wiki for guides, and the x86 tag wiki 有好东西。
第四个问题:您没有对齐数组,因此使用对齐加载内在函数是不安全的。您可以改用 loadu
内部函数。
第五题:
short int* res = (short int*)&result;
是个坏主意。不要将指针别名指向向量。将向量指针别名到数组上是可以的,因为 __m256i
是用 "may alias" 属性定义的。但是取消引用 (short int*)&result
是 C/C++ 未定义的行为,并且不会做你想做的(理论上或实践中)。
存储到临时数组,使用 _mm_extract_epi16
,或使用联合进行类型双关。