相比于GPU,ARM是大多数嵌入式硬件平台使用的芯片。一种典型的开发模式是,在运行Intel X86架构的服务器上,使用NVIDIA的GPU进行模型训练,最后将其部署到使用ARM芯片的嵌入式设备中。
ARM是Acorn公司提供的32位CPU,迄今已经发展到v8型号。越靠后的ARM内核,初始频率越高,架构越先进。
ARM的体系结构是一种精简指令集计算(RISC),这与基于复杂指令集计算(CISC)的X86差异很大,ARM充分考虑了实现规模、架构性能和低功耗,具有RISC的特性,包括:
(1)具有大量通用寄存器;
(2)结构采用加载/存储模型,即数据在寄存器中完成处理,无法直接处理内存数据;
(3)寻址模式简单,所有地址来自寄存器内容和指令字段。
Neon是ARM推出的压缩SIMD(单指令流多数据流)技术,它将寄存器看成相同数据类型的向量,且支持多种数据类型。
在移动设备中使用的媒体处理器经常将完整的数据寄存器划分为多个子寄存器,且并行完成多个子寄存器的计算。对于多次简单可重复的操作,使用SIMD会带来非常大的性能提升。
可通过以下几种方式使用Neon指令。
(1)使用支持Neon优化的库,比如OpenBLAS,它是一个跨平台的开源线性代数库;或者Ne10,它是ARM官方开源的一个C函数库。
(2)使用编译器的自动向量化特性,只需要在编译器开启相关选项,便会自动将一些操作转换为Neon指令。
(3)Compiler Intrinsics,即ARM编译器内联函数,每个内联函数都对应了多条汇编指令。
(4)直接编译汇编代码。
我们的开发平台往往是X86,但运行平台是ARM,因此需要在X86的环境中调用编译套件来编译出可以在ARM平台上运行的程序,这需要特殊的工具来完成,这种编译方式被称为交叉编译。
由于ARM硬件产品很多,不同硬件产品的系统内核、ABI(Application Binary Interface)和运行环境都不相同,因此往往需要针对平台编译自己的工具链,此时最好直接使用硬件厂商提供的工具链,通常有以下两种情况。
(1)移动应用程序,比如iOS和Android平台的应用程序。对于iOS,需要使用Xcode开发环境;对于Android,需要使用NDK及其工具链。
(2)开发套件,一般的ARM如树莓派等自带Linux或Android系统,可以找到厂商提供的工具链。对于一些高端开发套件如NVIDIA TX系列,则预装Linux,提供GCC或者NVCC包。
一般桌面Linux环境自带ARM工具链gcc-arm-linux-gnueabi,安装后可直接使用。