您的位置 首页 观点

ARM渠道NEON指令的编译和优化

本文介绍了ARM平台基于ARMv7-A架构的ARMCortex-A系列处理器(Cortex-A5,Cortex-A7,Cortex-A8,Cortex-A9,Cortex-A15)上的NEON多…

本文介绍了ARM渠道根据ARM v7-A架构的ARM Cortex-A系列处理器(Cortex-A5, Cortex-A7, Cortex-A8, Cortex-A9, Cortex-A15)上的NEON多媒体处理硬件加快器针对C/C++言语、汇编言语和NEON intrinsics怎么编译和优化,包括怎么向量化、向量化的ARMCC和GCC编译器选项、NEON的汇编和EABI程序调用标准、怎么在bare-metal和Linux操作体系上检测NEON硬件、怎么辅导编译器进行向量化NEON指令的优化等内容。

NEON向量化

根据ARM v7-A架构的ARM Cortex-A系列处理器(Cortex-A5, Cortex-A7, Cortex-A8, Cortex-A9, Cortex-A15)都能够选用NEON多媒体处理器加快程序运转,NEON是一种SIMD(Single Instruction Multiple Data)架构的协处理器,ARM的NEON处理器还可选装备成向量浮点VFPv3(Vector Floating-Point)指令集处理器。

常用的编译器选项装备

主动向量化选项

armcc编译器运用–vectorize选项来使能向量化编译,一般挑选更高的优化等级如-O2或许-O3就能使能–vectorize选项。

gcc编译器的向量化选项-ftree-vectorize来使能向量化选项,运用-O3会主动使能-ftree-vectorize选项。

挑选处理器类型

armcc编译器使–cpu 7-A或许–cpu Cortex-A8来指定指令集架构和CPU类型。

gcc编译器的处理器选项-mfpu=neon和-mcpu来指定cpu类型。如-mcpu=cortex-a5

挑选NEON和VFP类型

gcc挑选用-mfpu=vfpv3-fp16来指定为vfp协处理,而-mfpu=neon-vfpv4等就能指定为NEON+VFP结构。

挑选浮点处理器和ABI接口类型

-mfloat-abi=soft运用软件浮点库,不是用VFP或许NEON指令;-mfloat-abi=softfp运用软件浮点的调用规矩,而能够运用VFP和NEON指令,编译的方针代码和软件浮点库链接运用;

-mfloat-abi=hard运用VFP和NEON指令,并且改动ABI调用规矩来发生更有功率的代码,如用vfp寄存器来进行浮点数据的参数传递,然后削减NEON寄存器和ARM寄存器的复制。

常用的CPU类型编译器选项

CPU类型

CPU类型选项

FP选项

FP + SIMD选项

补白

Cortex-A5

-mcpu=cortex-a5

-mfpu=vfpv3-fp16

-mfpu=vfpv3-d16-fp16

-mfpu=neon-fp16

-d16标明只要前16个浮点寄存器可用

Cortex-A7

-mcpu=cortex-a7

-mfpu=vfpv4

-mfpu=vfpv4-d16

-mfpu=neon-vfpv4

-fp16标明支撑16bit半精度浮点操作

Cortex-A8

-mcpu=cortex-a8

-mfpu=vfpv3

-mfpu=neon

Cortex-A9

-mcpu=cortex-a9

-mfpu=vfpv3-fp16

-mfpu=vfpv3-d16-fp16

-mfpu=neon-fp16

Cortex-A15

-mcpu=cortex-a15

-mfpu=vfpv4

-mfpu=neon-vfpv4

常用的gcc组合编译器选项

Cortex-A15 with a NEON unit

arm-gcc -O3 -mcpu=cortex-a15 -mfpu=neon-vfpv4 -mfloat-abi=hard -ffast-math -omyprog.exe myprog.c

Cortex-A9 with a NEON unit

arm-gcc -O3 -mcpu=cortex-a9 -mfpu=neon-vfpv3-fp16 -mfloat-abi=hard -ffast-math -omyprog.exe myprog.c

Cortex-A7 without a NEON unit

arm-gcc -O3 -mcpu=cortex-a7 -mfpu=vfpv4-d16 -mfloat-abi=softfp -ffast-math -omyprog2.exe myprog2.c

Cortex-A8 without a NEON unit

arm-gcc -O3 -mcpu=cortex-a8 -mfloat-abi=soft -c -o myfile.o myfile.c

NEON汇编和EABI程序调用标准

GNU assembler (gas) and ARM Compiler toolchain assembler (armasm)都支撑NEON指令的汇编。但有必要遵从ARM Embedded Application Binary Interface (EABI)EABI的标准,即NEON寄存器的S0-S15 (D0-D7, Q0-Q3)用于传递参数和返回值,被调用函数内能够直接运用,不必保存;D16-D31 (Q8-Q15)则有调用函数来保存,被调用函数内能够不保存的随意运用;而S16-S31 (D8-D15, Q4-Q7)则有必要由被调用函数内部保存。关于调用传参标原则有,关于软件浮点,参数有R0~R3和仓库stack传递,而硬件浮点,能够经过NEON寄存器来传递参数。

NEON硬件检测和使能

编译时指定NEON单元是否存在

ARM编译器(armcc)从4.0之后就支撑在某些处理器和FPU的选项中预界说宏__ARM_NEON__, armasm的宏TARGET_FEATURE_NEON.

运转时指定检测NEON单元

OS内能够检测NEON单元是否存在,如Linux下cat /proc/cpuinfo看是否包括NEON或许VFP,如Tegra2 (双核 Cortex-A9 带 FPU), cat /proc/cpuinfo:

Features : swp half thumb fastmult vfp edsp thumbee vfpv3 vfpv3d16

四核 Cortex-A9 带NEON单元

Features : swp half thumb fastmult vfp edsp thumbee neon vfpv3

别的能够查看/proc/self/auxv,这里会包括二进制格局的hwcap,能够经过AT_HWCAP来查找到。HWCAP_NEON bit (4096).别的如Ubuntu的发布在途径/lib/neon/vfp下包括lib的NEON优化版别。

Bare-metal方式下使能NEON

#include

// Bare-minimum start-up code to run NEON code

__asm void EnableNEON(void)

{

MRC p15,0,r0,c1,c0,2 // Read CP Access register

ORR r0,r0,#0x00f00000 // Enable full access to NEON/VFP by enabling access to

// Coprocessors 10 and 11

MCR p15,0,r0,c1,c0,2 // Write CP Access register

ISB

MOV r0,#0x40000000 // Switch on the VFP and NEON hardware

MSR FPEXC,r0 // Set EN bit in FPEXC

}

下面的EnableNEON函数使能NEON协处理器;运用下面的编译挑选就能在bare-metal下使能NEON

armcc -c –cpu=Cortex-A8 –debug hello.c -o hello.o

armlink –entry=EnableNEON hello.o -o hello.axf

体系运转时使能NEON

内核在遇到第一个NEON指令时会发生一个Undefined Instruction的反常,这会让内核主动重启NEON协处理器,内核还能够在上下文切换时封闭NEON来省电。

Linux内核的NEON装备

图1. NEON的Linux内核装备

使能NEON,需求挑选

Floating point emulation→VFP-format floating point maths

和Floating point emulation→Advanced SIMD (NEON) Extension

查看Linux的装备文件来承认内核是否使能NEON

zcat /proc/config.gz | grep NEON

看是否存在

CONFIG_NEON=y

承认处理器是否支撑NEON

cat /proc/cpuinfo | grep neon

看是否有如下内容

Features : swp half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt

向量化NEON优化攻略

防止指针混叠alias

C90不要求指针方位,不同指针能够指向相同的内存区域,C99中引入了__restrict关键字来标明只要这个指针能指向它作业的区域。

告知编译器循环信息

如循环是否某个整数的整数倍,以便利向量化;如下标明循环次数是4的整数倍:

for(i=0 ; i < (len & ~3) ; i++)

{

。。。

}

for (i=0; i<(items*4); i+=1)

{

。。。

}

循环展开

#pragma unroll (n)

选用NEON Intrinsics

armcc, GCC/g++和llvm等编译器都支撑 NEON C/C++ intrinsics,并且选用相同的语法标准。因此代码能够在各个编译器间同享。NEON Intrinsics的代码简单保护并且功率高。NEON Intrinsics选用新的数据类型,这些类型对应于D和Q寄存器。NEON Intrinsics写起来像是函数调用但对应于每一条NEON指令。编程NEON Intrinsics时不必考虑详细的寄存器分配和代码的schedule,pipeline流水组织等。但NEON Intrinsics往往不能发生幻想的代码,功能上比较纯汇编要稍差一些。

削减循环内的相关性

假如当时迭代时运用的数据是前次迭代核算的成果,就发生了迭代间的相关性,能够拆分循环来削减相关。

向量化其他原则

  • 矮小的循环更简单让编译器完成主动向量化;
  • 防止在循环内运用break退出循环
  • 防止在循环内运用过多的条件句子,削减或许发生的条件跳转;
  • 让循环次数尽或许是2的幂次
  • 让编译器知晓循环次数,削减对循环次数为0等的判别;
  • 循环内调用的函数尽量inline内联
  • 运用数组+索引的方法拜访比指针方式更简单向量化;
  • 直接寻址(多重索引)不会向量化;
  • 运用restrict关键字来告知编译器没有堆叠的内存区域;

总结

本文介绍了ARM渠道根据ARM v7-A架构的ARM Cortex-A系列处理器(Cortex-A5, Cortex-A7, Cortex-A8, Cortex-A9, Cortex-A15)上的NEON多媒体处理硬件加快器针对C/C++言语、汇编言语和NEON intrinsics怎么编译和优化,包括怎么向量化、向量化的ARMCC和GCC编译器选项、NEON的汇编和EABI程序调用标准、怎么在bare-metal和Linux操作体系上检测NEON硬件、怎么辅导编译器进行向量化NEON指令的优化等内容。

参阅

http://houh-1984.blog.163.com/

本文介绍了ARM渠道根据ARM v7-A架构的ARM Cortex-A系列处理器(Cortex-A5, Cortex-A7, Cortex-A8, Cortex-A9, Cortex-A15)上的NEON多媒体处理硬件加快器针对C/C++言语、汇编言语和NEON intrinsics怎么编译和优化,包括怎么向量化、向量化的ARMCC和GCC编译器选项、NEON的汇编和EABI程序调用标准、怎么在bare-metal和Linux操作体系上检测NEON硬件、怎么辅导编译器进行向量化NEON指令的优化等内容。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/news/guandian/276081.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部