SIMD
向量化SIMD是一种单指令多数据的并行执行方式。具体而言,向量化是指相同指令在硬件向量处理单元上对多个数据流进行操作。这些硬件向量处理单元也被称为SIMD单元。
补充:
CPU在单位时间内(同一时间)能一次处理的二进制数的位数称为字长。1字节是8位字长。
并行向量化
如果每个线程能够充分利用每个处理器核心的SIMD浮点寄存器进行数据并行,那么可进一步提高程序的性能。
以简单的加法运算为例:
NEON指令化并行技术
NEON技术是在ARM Cortex™上使用的,是一个实现ARMv7-A或ARMv7-R架构的系列处理器。
ARM NEON技术建立在SIMD的概念上,支持128位向量操作,也称为单指令多数据向量模式。
自动向量化:
在GCC中启用自动向量化使用命令行选项:
-ftree-vectorize
-mfpu=neon
-mcpu 来指定核心或架构。
在优化级编译-O3意味着-ftree向量化。如果没有指定-mcpu选项,那么GCC将使用其内置的默认内核。
手动向量化(主要为使用下图中的intrinsics内联函数方式):
计算实例
数据类型 | <基本类型>x<lane个数>x<向量个数>_t |
---|---|
指令名称 | <指令名>[后缀]_<数据基本类型简写> |
C代码编写流程:1->定义neon向量 2->读取数据 3->处理数据 4->回写数据
(具体使用指令参考官方文档或者在官网查询)
向量点乘实现:
void neonax(float A[][1000],float *x,int len)
{
double t2,t1;
double y[len];
float32x4_t vec1,vec2,sum_vec = vdupq_n_f32(0);
for(int i=0;i<len;i++)
{
for(int j=0;j<len;j+=4)
{
vec1 = vld1q_f32(A[i]+j);
vec2 = vld1q_f32(x+j);
sum_vec = vmlaq_f32(sum_vec,vec1,vec2);
}
y[i]=vgetq_lane_f32(sum_vec,0)+vgetq_lane_f32(sum_vec,1)+vgetq_lane_f32(sum_vec,2)+vgetq_lane_f32(sum_vec,3);
sum_vec=vdupq_n_f32(0);
}
}
向量加实现:
void add_neon1(float *c, float *a, float *b,int count)
{
int i;
float32x4_t in1,in2,out;
for(i=0;i<count;i += 4)
{
in1 = vld1q_f32(a);
a += 4;
in2 = vld1q_f32(b);
b += 4;
out = vaddq_f32(in1, in2);
vst1q_f32(c,out);
c +=4;
}
}
持续补充…