|
浮点 DSP 运算效率不高 问题: 该问题由某客户提出,发生在 STM32F407IGT6 器件上。据其工程师讲述:由于在其产品中,需要使用STM32进行大量的浮点数以及浮点DSP运算,所以针对STM32的浮点数运算能力及 DSP 运算能力做了相关的测试,但测试结果不理想。STM32F407 在144MHz 主频下,对于表(一)程序的运算耗时为:9105uS。没有体现出硬件浮点运算应有的运算能力。
使用 Keil MDK4.21 创建工程对表(一)的程序进行测试。在工程设置中,选择支持浮点运算指令。将编译器的优化等级设置为 LEVEL1,然后编译运行。通过示波器测量主程序在调用该函数之前和在该函数返回之后在 I/O 管脚上所发出的脉冲之间的时间差,来判断 STM32 运行该函数所花费的时间。 1. 当 STM32 的主频为 168MHz,使用 SRAM2 存贮变量的条件下,测得时间消耗为:7840uS。修改工程设置,将内存的使用由 SRAM2 转成 CCM,重新编译、下载、运行,测得时间消耗为:7840uS。 2. 修改工程设置,将优化等级由 LEVEL1 换成 LEVEL3。为了避免编译器把整个测试函数优化掉,修改该函数如表(二)。重新编译、下载、运行,测得时间消耗为:7660uS。 3. 修改程序代码,将序函数 sin()和 cos()分别替换成 ARM DSP library 中的arm_sin_f32()和 arm_cos_f32(),如表(三)所示。重新编译、下载、运行,测得时间消耗为:748uS。 4. 修改代码,将计算中所用到的小数常量,表示成单精度,如表(四)所示。重新编译、下载、运行,测得时间消耗为:130uS。
三个方面的原因导致了计算效率降低: 1. 编译器的优化等级不够,以至生成的代码本身的效率低下; 2. 表达式上的漏洞,造成部分计使用了双精度浮点运算; 3. 三角函数库的选取不当,导致在计算正弦、余弦过程中引入了大量的双精度浮点运算; 处理: 1. 合理选用编译器的优化等级,提高代码的执行效率; 2. 在计算表达式中,强制常量为单精度浮点数,以避免引入双精度浮点数动算; 3. 选用 ARM 公司提供的,采用单精度浮点数优化的三角函数库,以避免由普通的数学函数库引入的双精度浮点数运算; 建议: 从应用角度看,Cortex-M4 可以认为是 Cortex-M3 的加强版。相对 Cortex-M3,Cortex-M4主要从两个方面进行了改进: 1. 增加了 DSP、SIMD 指令; 2. 增加了单精度浮点运算单元; 第 1 点使得 Cortex-M4 拥有高速的定点 DSP 处理能力,第 2 点则使得 Cortex-M4 拥有强大的数**算能力。受益于 Cortex-M4 的优异的处理性能,以及高效的总线与存贮器接口,STM32F4 系列 MCU 在数据处理方面有着非凡的表现。不过,要使硬件上的性能得以充分的发挥,除了对算法本身进行优化以外,对一些相关因素也要仔细斟酌: 1. 恰当的设置 Flash 缓冲区的参数。在 STM32F4 中,为了匹配 Flash 存贮器与CPU 之间的对数据、指令的吞吐速率,设有指令缓冲区和数据缓冲区。复位后缓冲区是不工作的,需要软件予以开启,并设置恰当的等待周期数。没有缓冲区的参与,运行在 Flash 中的程序,在运效率上会大幅度的降低。 2. 选择高效的存贮器来存放数据。快速的数据存取是保证 CPU 不间断的执行指令的前提。这一点上,不仅要考查存贮器本身的速率,还要看是否有其它的处理单元与 CPU 分享该存贮器。比如,在 STM32F4 中,将数据放在 CCM 存贮器中,要比放在 SRAM1 中更能保证 CPU 对数据的存取速率,因为 CCM 存贮器是 CPU独享的,而 SRAM1 还可能被 DMA 访问。 3. 根据 CPU 指令集的特点,合理的选取计算的数据类型。比如,要计算 16 位的DSP 运算,最好把变量和常量定义成 16位数据,这样有利于编译器使用 SIMD指令对代码进行优化。在单精度浮点数能够满足要求的情况下,将变量或常量定义成单精度类型,有利于编译器使用单精度浮点运算指令,对代码优化。 4. 选择针对 Cortex-M4 进行优化的数学函数库。ARM 公司为 Cortex_M4 的提供了一整套的 DSP、浮点数运算库,其效率远高于编译器自带的函数库。 5. 编译器的优化等级是一个重要的设置选项,不同的优化等级下,所生成的代码的效率是有很大差别的。 6. 对于高频次使用的数据,要考虑放在寄存器类型的变量中。通常,CPU 存取操作数的最快捷的方式是寄存器寻址,可以做到零时钟花费。 7. 合理安排计算次序,考虑是否可以以乘法代替除法。在数学中,乘法和除法是一对逆运算,除以一个数与乘于这个数的倒数可以等同起来。然而在 CPU 的指令实现中,乘法和除法的计算速度上是有很大差别的,通常乘法的计算速度远高于除法的计算速度。所以,有必要在运算中,使用乘法来代替除法。比如: a÷b÷c可以使用a÷(b×c)来代替。 8. 找出算法中的重复计算,将其合并,只计算一次。对这样的计算,完全可以在第一次计算之后,将结果放在中间变量中,而在后面的计算中直接引用。 9. 对于复杂的计算,考虑是否能用查表来代替。查表是一种快速得出结果的好方法,它以牺牲存贮器空间来换取速度。在存贮器空间不是很紧张的情况下,用查表代替计算还是很划算的。 转载自21ic:http://bbs.21ic.com/icview-1070644-1-1.html |
微信公众号
手机版
F7也不是都是双精度的FPU,低端的还是搭载单精度FPU,但是比M4核的效率是高了40%,如果换做双精度的F7,估计效率会更高。
原贴总体思路是对的,部分分析可能不太准确;依照原贴的思考方向,自己也重新进行了测试
一、上靓照
脱光了
二、对比F407浮点运算
运行于168M,三种模式运行时间对比
主循环
函数后面的时间标注是通过串口打印出来的时间测试值,测试方法是1us定时器累加,函数执行前后时间差就是执行时间。此处可看出DSP库函数的强大这里要注意!小数点后面不加f的编译器会自动转为双精度浮点数,而M4核和DSP库函数都是只支持单精度浮点数,就会导致运算速度降低,切记!!!
什么情况嘛,还不如M4,肯定哪里设置错了...
这个选项M1和M4可没有,点开看看
紧耦合内存技术(TCM),该功能打开,实测在这种应用中作用不大
打开CPU的ICache
再次测试
再打开CPU的DCache
测试结果
看来TCM接口要配合Cache的使用才有作用下面还有内存管理器MPU的配置,这里没用到,大型应用(比如linux移植应用)更如鱼得水了
对比M4的测试是不是有什么问题?
最后把频率提升到216M也没见结果有什么影响......不应该呀
原来自己犯了个错误,时钟改了,定时器的1us没改,导致结果错误,重新修改编译,结果是
先到240M试试
280M
300M
310M
几分钟后死机
320M直接都没反应了。。。。。。
看来也就300M左右可以发挥一下了
补充一下CUBEMX针对F7特有的配置MPU
MPU管理模式有四种
MPU管理单元有8个
每个MPU管理单元可配置内存地址范围和管理方式
重新回到二楼的flash 接口选择,分别为AXI和ITCM总线,看总线图
AXI总线是通过转接AHB总线与flash相连,大家知道flash是低速存取设备,因此使用该总线会在调取指令时插入空指令来弥补flash读取指令时候的空白指令周期,因此也拖慢了系统执行指令的速度
而使用ITCM总线是三种模式,第一种是不开ART直接读取flash,与AXI总线差不多,优点是不占用AHB总线
第二种是开ART,ART(Adaptive Real-Time Memory Accelerator 即 自适应实时存储器加速器),主要功能是弥补高速cpu与相对低速flash指令读取之间的矛盾。当指令flash读取速度足够快,cpu就可以相应提速。这句话载自网络,没太理解,大概意思就是发挥flash的读取极限,但是仍然跟不上CPU的速度。
第三种是使用ITCM内存的情况下开ART,这种模式就牛逼了,ART存取和预取的指令都存放到一片SRAM内存中,大部分指令(比如循环体和重载函数)都可以从这片RAM中取指令,就不用到flash读取了,因此执行指令就可以0等待了,这时才发挥CPU的全部能力
看看我的测试,在168M下开ITCM能提升将近一倍的速度。
看看ITCM和DTCM在存储空间的映射,他们不再一个区域。DTCM和SRAM在一起,功能也相近;ITCM映射到了和flash一个区,根据功能确定的。但是具体使用地址是在映射接口区0x00200000----0x0027ffff
是不是可以这样,综述一下:
虽然STM32F4的DSP单位时间内的处理能力有些吃力,但STM32F7的DSP处理能力已经能满足基本需求了。