Rud*_*lug 2 c x86 simd intrinsics avx
为了并行化我的基于数组的代码,我试图弄清楚如何利用英特尔AVX内在函数在大型数组上执行并行操作.
从我已经阅读的文档中可以看出,256位AVX向量将支持多达8个并行32位整数/ 32位浮点数或最多4个并行64位双精度数.浮动部分没有给我任何问题,工作正常,但整数AVX函数让我头疼,让我用以下代码来演示:
命令行选项-mavx与符合AVX的Intel处理器一起使用.我不会使用AVX2功能.编译将在Ubuntu 16.04上使用GNU99 C完成.
AVX FP:
#include <stdio.h>
#include <stdlib.h>
#include <immintrin.h>
int main()
{
float data[8] = {1.f,2.f,3.f,4.f,5.f,6.f,7.f,8.f};
__m256 points = _mm256_loadu_ps(&data[0]);
for(int i = 0; i < 8; i++)
printf("%f\n",points[i]);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
1.000000
2.000000
3.000000
4.000000
5.000000
6.000000
7.000000
8.000000
Run Code Online (Sandbox Code Playgroud)
这完全是应该的,但是当使用整数加载AVX函数时不是这种情况:
AVX INT:
#include <stdio.h>
#include <stdlib.h>
#include <immintrin.h>
int main()
{
int data[8] = {1,2,3,4,5,6,7,8};
__m256i points = _mm256_loadu_si256((__m256i *)&data[0]);
for(int i = 0; i < 8; i++)
printf("%d\n",points[i]);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
1
3
5
7
1048576 [ out of bounds ]
0 [ out of bounds ]
1 [ out of bounds ]
3 [ out of bounds ]
Run Code Online (Sandbox Code Playgroud)
如您所见,加载仅在__m256i类型变量中生成4个元素,其中仅从原始数组加载第一个,第三个,第五个和第七个元素.超出第四个元素,引用超出范围.
如何将整个数据集加载到整数AVX数据类型中产生所需的结果,就像AVX浮点数据类型一样?
您正在使用GNU C扩展来索引向量,[]
而不是将其存储回数组.英特尔关于内在函数的文档没有什么可说的,并非所有编译器都支持它(例如MSVC没有).
GCC定义__m256i
为GNU C本机向量long long
. <immintrin.h>
没有__m256i
为SIMD矢量定义不同类型的int
或者short
,并且__m256i
不记得它来自何处或如何设置.(与FP矢量不同,其中有单独的C类型ps
和pd
,所以__m128d _mm_castps_pd(__m128)
如果你想使用shufpd
或unpcklpd
在ps
矢量上,你必须这样做)
您可以typedef
像您一样使用本机矢量类型v8si
(请参阅上一个链接到gcc文档),或使用像Agner Fog的VCL这样的库,它为您提供类似Vec8i
(8签名int
)或Vec32uc
(32未签名char
)的类型.他们有运算符重载,让你写a + b
的,而不是_mm256_add_epi32(a, b)
或_mm256_add_epi8(a,b)
根据类型.或者使用[]
而不是_mm_extract_epi32
/ epi8/epi16/epi64.
请参阅打印__m128i变量以获取便携式和安全/正确的方法来循环/打印出英特尔固有SIMD变量的元素.TL:DR:_mm_store
/ _mm256_store
到tmp数组和索引.它是可移植的,并且它可以优化(pextrd
对于整数或只是一个随机播放的FP),在简单的情况下没有实际的存储/重新加载.
归档时间: |
|
查看次数: |
961 次 |
最近记录: |