《基本SIMD及其他的指令流与数据流的处理方式.docx》由会员分享,可在线阅读,更多相关《基本SIMD及其他的指令流与数据流的处理方式.docx(9页珍藏版)》请在第一文库网上搜索。
1、SIMDOperatic基本SIMD及其他的指令流与数据流的处理方式_、SINf1)ARMNEON是适用于ARMCortex-A和Cortex-R系列处理器的一种SIMD(Sing1eInstructionMu1tip1eData)扩展架构。SIMD采用一个控制强来控制多个处理器,同时对一组数据(又称“数据向量”)中的每个数访别执行相同操作,从而实现并行技术。SIMD特别适用于一些常见的任务,如音频图像处理。大部分现代CPU设计都包含了S1MD指令,来提高多媒体使用的性能。SIMD操作示意图如上图所示,标量运算时一次只能对一对数据执行乘法操作,而采用STMD乘法指令,则一次可以对四对数据同时执
2、行乘法操作。A.指令流与数据流费林分类法根据指令流(InStnICtiOn)和数据流(Data)的处理方式进行分类,可分成四种计算机类型:费林分类示意图1. SISD(Sing1eInstructionSing1eData)机器的硬件不支持任何形式的并行计算,所有的指令都是串行执行。单个核心执行单个指令流,操作存储在单个内存中的数据,每次一个操作。早期的计算机都是SISD机器,如冯诺.依曼架构,IBMPC机等。2. MISD(Mu1tip1eInstructionSing1eData)是采用多个指令流来处理单个数据流。由于实际情况中,采用多指令流处理多数据流才是更有效的方法,因此M1SD只是作
3、为理论模型出现,没有投入到实际应用之中。3. MIMD(Mutip1eInstructionMutip1eData)计算机具有多个异步和独立工作的处理器。在任何四周期内,不同的处理器可以在不同的数据片段上执行不同的指令,也即是同时执行多个指令流,而这些指令流分别对不同数据流进行操作。MIMD架构可以用于诸如计算机辅助设计、计算机辅助制造、仿真、建模、通信交换机的多个应用领域。除了以上模型外,由NVIDIA公司生产的GPU引入SIMT体系结构:4. SIMT(Sing1eInstructionMu1tip1eThreads)类似CPU上的多线程,所有的核心各有各的执行单元,数据不同,执行的命令是
4、相同的。多个线程各有各的处理单元,和SIMD共用一个A1U不同。SIMT并行计算好迎SIMT示意图B.SIMD特点及发展趋势1. SIMD优势与不足优势效率高-适合计算密集型Q提供专用指令不足-适用场景有限-功耗高和芯片面积大.开发难度大-数据对齐要求2. S1MD发展趋势以ARM架构下的下一代SIMD指令集SVE(Sca1ab1eVectorExtension,可扩展矢量指令)为例,其是针对高性能计算(HPC)和机器学习痢域开发的一套全新的矢量指令集。SVE指令集中有很多概念与NEON指令集类似,例如矢量、通道、数据元素等。SVE指令集也提出了一个全新的概念:可变矢量长度编程模型。Desev
5、e128bitvec1ennx128-bit财社区SVE可扩展模型传统的SIMD指令集采用固定大小的向量蚩谴,例如NEON指令集采用固定的64/128位长度的矢量寄存器。而支持V1A编程模型的SVE指令集则支持可变长度的矢量寄存器。因此允许芯片设计者根据负载和成本来选择一个合适的矢量长度。SVE指令集的矢量寄存器的长度最小支持128位,最大可以支持2048位,以128位为增量。SVE设计确保同一个应用程序可以在支持不同矢量长度的SVE指令机器上运行,而不需要重新编译代码。ARM在2019年便推出了SVE2,以最新的Armv9为基础,扩充了更多的运算类型以全面替代NEON,同时增加了矩阵相关运算
6、的支持。二、ARM的SIMD指令集1. ARM处理器的SIMD支持-NEONARMNEON单元默认包含在Corte-A7和Corte-A15处理器中,但在其他ARMv7Cortex-A系列处理器中是可选的,某些实现ARMv7-A或ARMv7-R架构配置文件的Cortex-A系列处理器可能不包含NEON单元。符合ARMv7的内核的可能组合有以下四种:NEON因此必须首先确认处理器是否支持NEON和VFPo可以在编译和运行的时候进行检查。Armv6SIMD扩展Armv7-ANEONArmv8-ANEON利用Arm通用寄存器支持8/16位整数同时计算2x16/4x8操作数 32个64位NEON寄存器
7、支持8/16/32/64位整数 支持单精度浮点 最多同时支持16个8位操作数 32个128位NEOI 支持8/16/32/64f 支持单精度浮点 支持双精度浮点,双精度浮点运算2IEEE 最多同时支持7?七NEON发展史2. ARM处理器的SIMD支持检查2.1 编译阶段检查检测NEON单元是否存在的最简单方法。在ARM编译器工具链(armcc)v4.0及更高版本或GCC中,检查预定义宏ARM_NEON或者arm_neon是否开启。armasm等效的预定义宏是TARGET_FEATURE_NEON2 .2运行阶段检查在运行时检测NEON单元需要操作系统的帮助。ARM架构有意不向用户模式应用程序
8、公开处理器功能。在1inUX下,procCPUinfO以可读的形式包含此信息,比如:在Tegra(带有FPU的双核Corte-A9处理器)$proccpuinfoswpha1fthumbfastmu1tvfpedspthumbeevfpv3vfpv3d16带有NEON单元的ARMCorte-A9处理器$proccpuinfoswpha1fthumbfastmu1tvfpedspthumbeeneonvfpv3由于procCPUinfo输出是基于文本的,因此通常首选查看辅助向量procsc1fauxv,其包含二进制格式的内核hwcap,可以轻松地在procsc1fauxv文件中搜索AT_HWCA
9、P记录,以检查HWCAPNEON位(4096)o某些1inux发行版1d.so链接器脚本被修改为通过g1ibc读取hwcap,并为启用NEON的共享库添加额外的搜索路径。3 .指令集关系在ARMv7中,NEON与VFP指令集具有以下关系:具有NEON单元但没有VFP单元的处理器无法在硬件中执行浮点运算。由于NEONSIMD操作更有效地执行向量计算,因此从ARMv7的引入开始,VFP单元中的向量模式操作已被弃用。因此,VFP单元有时也称为浮点单元(FPU)oVFP可以提供完全兼容IEEE-754的浮点运算,_ARMv7NEON单元中的单精度运算不完全符合IEEE-754.oNEoN不能取代VFP
10、0VFP提供了一些在NEON指令集中没有等效实现的专用指令。半精度指令仅适用于包含半精度扩展的NEON和VFP系统。在ARMV8中,VFP已被NEON取代,以上问题如NEON并不完全符合IEEE754标准,并且有一些指令VFP支持而NEON不支持的问题已在ARMv8中得到解决。三、NEONNEON是适用于ARMCortex-A系列处理器的一种128位SIMD扩展结构,每个处理器核心均有一个NEON单元,因此可以实现多线程并行的加速效果。1. NEON基本原理1.1 NEON指令执行流程内存向量寄存豪=:计算单元向量寄存器?上图为NEON单元完成加速计算的流程图。其中向量寄存器中的每个元素同步执
11、行计算,以此来加速计算过程。1. 2NEON计算资源NEON与ARM处理器资源关系-NEON单元作为ARM指令集的扩展,使用独立于ARM原有寄存器的64位或128位寄存器进行SIMD处理,在64位寄存器的寄存器文件上运行。-NEON和VFP单元完全集成到了处理器中,并共享处理器资源以进行整数运算、循环控制和缓存。与硬件加速器相比,这显着降低了面积和功耗成本。并且其还使用更简单的编程模型,因为NEON单元使用与应用程序相同的地址空间。NEON与VFP资源关系NEON寄存器与VFP寄存器重叠,ARMv7有32个NEOND寄存器,如下图所示。NEON寄存器2. NEoN指令2.1 自动矢量化向量化编
12、译器可以使用C或生源代码,以一种能够有效使用NEON硬件的方式对其进行矢量化。这意味着可以通过编写可移植的C代码,同时仍然可以获得NEON指令所带来的性能水平。为了帮助矢量化,将循环迭代次数设为矢量长度的倍数。GCC和ARM编译器工具链都具有为NEON技术启用自动矢量化的选项。2.2 NEON汇编对于性能要求特别高的程序,手工编写汇编代码是更适合的方式。GNU汇编器(gas)和ARMCompi1er工具链汇编器(armasm)都支持NEON指令的汇编。编写汇编函数时,需要了解ARMEABI,其定义了如何使用寄存器。ARM嵌入式应用程序二进制接口(EABI)指定哪些寄存器用于传递参数、返回结果或
13、必须保留,指定了除ARM内核寄存器之外的32个D寄存器的使用。下图对寄存器功能进行了总结。D0D7Argumentregistersandreturnregister.Ifthesubroutinedhaveargumentsorreturnva1ues,thentheva1ueintheseremightbeuninitia1ized.D8-D15ca11ee-savedregisters.D16-D31ca11er-savedregisters.寄存器功能2. 3NEONIntrinsicsNEONintrinsic函数提供了一种编写NEON代码的方法,该方法比汇编代码更易于维护,同时仍然
14、可以控制生成的NEON指令。内部函数使用与D和QNEON寄存器对应的新数据类型。数据类型支持创建直接映射到NEON寄存器的C变量。NEONintrinsic函数的编写类似于使用这些变量作为参数或返回值的函数调用。编译器做了一些通常与编写汇编语言相关的繁重工作,例如:寄存器分配代码调度或重新排序指令。intrinsic缺点无法让编译器准确输出想要的代码,因此在转向NEON汇编代码时仍有一些改进的可能性。NEON指令简类型NEON数据处理指令可以分为正常指令、长指令、宽指令、窄指令和饱和指令。以Intrinsic的长指令为例int16x8_tvadd1_s8(int8x8_t_a,int8x8_t
15、b)上面的函数将两个64位MD寄存器向量(每不向量包含8个8位数字)相加,生成一个包含8个16位数字的向量(存储在128位的Q寄存器中),从而避免相加的结果溢出。四、其他SIMD技术1 .其他平台上的SIMD技术SIMD处理不是ARM独有的,下图将其与86和A1tivec进行了比较。NEONtechno1ogyx86MMX/SSEA1tivecNumberofregisters3264-bit(aKovisib1eas16128registeroperationsRegister-based3-operandinstructionsMixofreg!MerandmemoryoperationsRegister-bast4-oPerandnv1oadsto