你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

浮点 DSP 运算效率不高

[复制链接]
涛哥2035 发布时间:2017-12-26 10:28
浮点 DSP 运算效率不高
1 A" i( z. }" w2 x  M2 @, s3 h
问题:3 F% n1 N! A: G) ~! K+ Y
该问题由某客户提出,发生在 STM32F407IGT6 器件上。据其工程师讲述:由于在其产品中,需要使用STM32进行大量的浮点数以及浮点DSP运算,所以针对STM32的浮点数运算能力及 DSP 运算能力做了相关的测试,但测试结果不理想。STM32F407 在144MHz 主频下,对于表(一)程序的运算耗时为:9105uS。没有体现出硬件浮点运算应有的运算能力。$ a) ^; z4 b7 J# V6 E2 z  S
1.jpg
调研:
6 L; T6 P3 [4 `- J/ L/ n9 N使用 Keil MDK4.21 创建工程对表(一)的程序进行测试。在工程设置中,选择支持浮点运算指令。将编译器的优化等级设置为 LEVEL1,然后编译运行。通过示波器测量主程序在调用该函数之前和在该函数返回之后在 I/O 管脚上所发出的脉冲之间的时间差,来判断 STM32 运行该函数所花费的时间。
. h" g0 Q7 r: N6 D, S2 Z1 R- d+ K, J1. 当 STM32 的主频为 168MHz,使用 SRAM2 存贮变量的条件下,测得时间消耗为:7840uS。修改工程设置,将内存的使用由 SRAM2 转成 CCM,重新编译、下载、运行,测得时间消耗为:7840uS。
- N! p- L0 l4 r& S2. 修改工程设置,将优化等级由 LEVEL1 换成 LEVEL3。为了避免编译器把整个测试函数优化掉,修改该函数如表(二)。重新编译、下载、运行,测得时间消耗为:7660uS。
, m: W1 V8 J8 Q0 I: P! @9 B7 g5 f3. 修改程序代码,将序函数 sin()和 cos()分别替换成 ARM DSP library 中的arm_sin_f32()和 arm_cos_f32(),如表(三)所示。重新编译、下载、运行,测得时间消耗为:748uS。6 Q5 I7 h: B/ h% U
4. 修改代码,将计算中所用到的小数常量,表示成单精度,如表(四)所示。重新编译、下载、运行,测得时间消耗为:130uS。/ ?+ L- `0 _8 w$ k
2.jpg
3.jpg
结论:/ V+ r4 ?* g! I6 P, O, \0 T  `
三个方面的原因导致了计算效率降低:
( ]1 K$ N) K' Y7 \1. 编译器的优化等级不够,以至生成的代码本身的效率低下;
( T5 [4 g' ~' z5 s: d5 B2. 表达式上的漏洞,造成部分计使用了双精度浮点运算;
: B8 |% ~& c% p4 l6 G1 Z3. 三角函数库的选取不当,导致在计算正弦、余弦过程中引入了大量的双精度浮点运算;
3 C2 ?" N$ G$ \% M/ y. Q
; @+ o# T  v4 m: t处理:$ r: h) v( M! p% ^- Q
1. 合理选用编译器的优化等级,提高代码的执行效率;
6 @+ V/ a' T# y* o2. 在计算表达式中,强制常量为单精度浮点数,以避免引入双精度浮点数动算;
# j, L0 s+ X, J3. 选用 ARM 公司提供的,采用单精度浮点数优化的三角函数库,以避免由普通的数学函数库引入的双精度浮点数运算;3 a2 i0 l+ I# Y; o8 W+ X

! T# e1 I0 H/ M* J建议:
3 U0 w' M+ N% o从应用角度看,Cortex-M4 可以认为是 Cortex-M3 的加强版。相对 Cortex-M3,Cortex-M4主要从两个方面进行了改进:
/ H. d7 P' g  k1. 增加了 DSP、SIMD 指令;, [+ O; P1 g# x! q; n$ \
2. 增加了单精度浮点运算单元;( Z* W* ]4 _% z) r: B1 g  P
第 1 点使得 Cortex-M4 拥有高速的定点 DSP 处理能力,第 2 点则使得 Cortex-M4 拥有强大的数**算能力。受益于 Cortex-M4 的优异的处理性能,以及高效的总线与存贮器接口,STM32F4 系列 MCU 在数据处理方面有着非凡的表现。不过,要使硬件上的性能得以充分的发挥,除了对算法本身进行优化以外,对一些相关因素也要仔细斟酌:
- p7 C1 ^' f7 j, T1. 恰当的设置 Flash 缓冲区的参数。在 STM32F4 中,为了匹配 Flash 存贮器与CPU 之间的对数据、指令的吞吐速率,设有指令缓冲区和数据缓冲区。复位后缓冲区是不工作的,需要软件予以开启,并设置恰当的等待周期数。没有缓冲区的参与,运行在 Flash 中的程序,在运效率上会大幅度的降低。2 Y$ G$ w8 e, K' B& k) l# W
2. 选择高效的存贮器来存放数据。快速的数据存取是保证 CPU 不间断的执行指令的前提。这一点上,不仅要考查存贮器本身的速率,还要看是否有其它的处理单元与 CPU 分享该存贮器。比如,在 STM32F4 中,将数据放在 CCM 存贮器中,要比放在 SRAM1 中更能保证 CPU 对数据的存取速率,因为 CCM 存贮器是 CPU独享的,而 SRAM1 还可能被 DMA 访问。
+ |6 W% v: A- U7 e7 p! I; g5 S+ k3. 根据 CPU 指令集的特点,合理的选取计算的数据类型。比如,要计算 16 位的DSP 运算,最好把变量和常量定义成 16位数据,这样有利于编译器使用 SIMD指令对代码进行优化。在单精度浮点数能够满足要求的情况下,将变量或常量定义成单精度类型,有利于编译器使用单精度浮点运算指令,对代码优化。
) K$ ]' J8 P3 A4. 选择针对 Cortex-M4 进行优化的数学函数库。ARM 公司为 Cortex_M4 的提供了一整套的 DSP、浮点数运算库,其效率远高于编译器自带的函数库。
& P2 T  `1 i# U6 |0 q$ u& l5. 编译器的优化等级是一个重要的设置选项,不同的优化等级下,所生成的代码的效率是有很大差别的。
2 @% _5 Q0 G4 z1 }# \6. 对于高频次使用的数据,要考虑放在寄存器类型的变量中。通常,CPU 存取操作数的最快捷的方式是寄存器寻址,可以做到零时钟花费。
2 N& X& x$ @7 E: z4 `7. 合理安排计算次序,考虑是否可以以乘法代替除法。在数学中,乘法和除法是一对逆运算,除以一个数与乘于这个数的倒数可以等同起来。然而在 CPU 的指令实现中,乘法和除法的计算速度上是有很大差别的,通常乘法的计算速度远高于除法的计算速度。所以,有必要在运算中,使用乘法来代替除法。比如: a÷b÷c可以使用a÷(b×c)来代替。
4 F4 h5 [) n. Q: J8 K: y2 O( }& @; q8. 找出算法中的重复计算,将其合并,只计算一次。对这样的计算,完全可以在第一次计算之后,将结果放在中间变量中,而在后面的计算中直接引用。
8 ?% B0 m9 z' h; r9. 对于复杂的计算,考虑是否能用查表来代替。查表是一种快速得出结果的好方法,它以牺牲存贮器空间来换取速度。在存贮器空间不是很紧张的情况下,用查表代替计算还是很划算的。
- K2 }1 x% I3 Q! g, B' f
转载自21ic:http://bbs.21ic.com/icview-1070644-1-1.html) f) L& s% h+ a5 n" k7 w# k1 Q
收藏 2 评论16 发布时间:2017-12-26 10:28

举报

16个回答
涛哥2035 回答时间:2017-12-26 11:32:04
本帖最后由 whtt 于 2017-12-26 12:48 编辑
. a  Z* }- U7 I9 D, A
wolfgang2015 发表于 2017-12-26 11:19
" S' y* O. n# C% y+ w9 m* t9 Q6 c干货,支持一下。3 q" g; m, ?, s  G, q. U. E
) J% E' O% k, n$ p/ J
是不是可以这样,综述一下:

2 m- i& N3 w, x- ?9 }3 n/ VF7也不是都是双精度的FPU,低端的还是搭载单精度FPU,但是比M4核的效率是高了40%,如果换做双精度的F7,估计效率会更高。
涛哥2035 回答时间:2017-12-26 10:45:42
本帖最后由 whtt 于 2017-12-26 10:49 编辑
5 K1 u, L! s6 x  Z/ @7 W, k$ V# Y( D; V* F+ ]; ~8 R; O% a; X( x
原贴总体思路是对的,部分分析可能不太准确;依照原贴的思考方向,自己也重新进行了测试
4 t0 A, w  V( W
0 H/ x: X9 e8 ]+ G! k) E/ \& w; z. z
有幸在活动中获得NUCLEO-F7的板子非常激动!这是我的第一个f7板,非常想知道有多牛逼。: \6 ^* z; j$ ]2 v+ d' |" I" x* L
一、上靓照0 J9 @+ s; W- P$ Q/ |9 ~; ~0 n) [9 h
1.jpg # ?7 @, G1 E9 t2 d
脱光了
  Z3 b( [& h* c- `
2.jpg
; {0 V: C1 i% [: Q- [& e1 a: d
3.jpg
( h; _1 U( c8 W! b* G
2 P4 M. [" a1 Z/ Y& ]% J3 }4 \( `
4.jpg
1 @1 B" W% c# i& D" E' I8 w! ^7 G# s2 e
5.jpg 7 q* |7 x2 U. J; u  }3 E

: U! o. P2 T& b" l7 {4 E. K二、对比F407浮点运算
9 w. a0 F7 Q+ P; f运行于168M,三种模式运行时间对比% K6 C( K! y$ c
6.jpg + K$ |+ P9 u  W- q5 }5 }
7.jpg
4 t! @& R: O; b5 X主循环  ~) m3 a5 M$ K) [( T
8.jpg / t; S' V+ N1 s9 ^2 ]) _6 W
函数后面的时间标注是通过串口打印出来的时间测试值,测试方法是1us定时器累加,函数执行前后时间差就是执行时间。此处可看出DSP库函数的强大这里要注意!小数点后面不加f的编译器会自动转为双精度浮点数,而M4核和DSP库函数都是只支持单精度浮点数,就会导致运算速度降低,切记!!!/ }- g6 X3 J, _6 m
9.jpg
三、对比测试F722执行时间,频率首先按168M配置执行
10.jpg 8 E% f  {# Y. I$ P' x" j& p* c- Z" |
什么情况嘛,还不如M4,肯定哪里设置错了...4 X4 \+ o) Q" d
+ y9 Z8 ^9 f$ Y1 {, M9 R* U
11.jpg
3 m: `3 Z" _" }4 V& A这个选项M1和M4可没有,点开看看
) B& J+ f; w4 ~; U* n
12.jpg 9 ]% F+ W) j. `. Z
紧耦合内存技术(TCM),该功能打开,实测在这种应用中作用不大8 A( q4 e7 d/ `1 I
13.jpg # U5 j6 b/ g' h4 P6 X. h
打开CPU的ICache8 P. k) S3 k' h/ j+ s! @9 _( V' H
再次测试
" m/ k6 Y' P, H2 ~' h; _  ^! z
14.jpg 7 Z0 i/ Y0 U/ c: k  A" U  L! R
再打开CPU的DCache
: S# G' w& w  [! K( ~
15.jpg
8 l1 L# m" [9 f* K8 @! M; W6 T测试结果
# N% P$ x! d" V2 ]& H. B
16.jpg
. |$ v7 M& C: b# W7 o/ T看来TCM接口要配合Cache的使用才有作用下面还有内存管理器MPU的配置,这里没用到,大型应用(比如linux移植应用)更如鱼得水了, @$ c% z/ A5 i/ ?
对比M4的测试是不是有什么问题?# X1 _& m3 |- U# y( V
最后把频率提升到216M也没见结果有什么影响......不应该呀; L. T' b/ x5 p+ F5 H* b
17.jpg
: H8 s, Z. s) L7 D- ~( ]原来自己犯了个错误,时钟改了,定时器的1us没改,导致结果错误,重新修改编译,结果是
: `1 s1 P: K2 R) A. Q
18.jpg
提升还不小
下面玩玩超频
' k4 H- f* }/ x  j1 r先到240M试试
1 e# M3 f: B$ W  A
19-240.jpg ) N' P9 B/ r2 W* A
; b+ c! k' Z: C+ I' ]
280M7 F1 m6 i, H; O. V
20-280.jpg
+ A5 G8 z: ~2 f- x9 \6 h3 Y3 F) ~* t; U' q% T& p6 Q3 l
300M
: w: z. b6 }$ ?, J; @
300m.jpg
5 o% G1 c0 |% ?$ [# W2 U5 |
$ K+ L5 S! l2 M- k3 {310M. y& e9 S$ o+ J. H) H, {2 W/ z, z
21-300.jpg
* v: k% H  e' W几分钟后死机4 p9 e5 E2 m0 U; e8 Q) w% p# I/ O

' P1 f4 C9 V4 q4 L8 U, [% ]320M直接都没反应了。。。。。。5 I) w- a- X0 s. I1 X7 }
看来也就300M左右可以发挥一下了
, ]% ^9 t( l; `% _补充一下CUBEMX针对F7特有的配置MPU6 B$ t, G+ P5 h  q+ U* s- q

0 k+ a! S3 {# T) N
22.jpg
  @% y, J; X& \' ^' PMPU管理模式有四种- A3 a  Z, u1 S/ I5 x

  B9 F* c" T( D- K- A+ U; j
23.jpg
: [  V  h, Z' }  ]1 R. dMPU管理单元有8个2 C; C- p: Y% P( F; Z" d/ n

3 ~, W$ V( D, ?- W8 w
24.jpg
7 n$ ^9 Y" x$ |每个MPU管理单元可配置内存地址范围和管理方式
1 C# B" N" ]4 e
重新回到二楼的flash 接口选择,分别为AXI和ITCM总线,看总线图" L' F" w' p7 }: d- z; j& _; e
25.jpg * e$ r# w3 G3 u- q) ]* A) ~: G1 l7 v
AXI总线是通过转接AHB总线与flash相连,大家知道flash是低速存取设备,因此使用该总线会在调取指令时插入空指令来弥补flash读取指令时候的空白指令周期,因此也拖慢了系统执行指令的速度. {2 g  x2 V( B" c8 u
而使用ITCM总线是三种模式,第一种是不开ART直接读取flash,与AXI总线差不多,优点是不占用AHB总线
& G7 Z0 V6 r* t& g, J第二种是开ART,ART(Adaptive Real-Time Memory Accelerator 即 自适应实时存储器加速器),主要功能是弥补高速cpu与相对低速flash指令读取之间的矛盾。当指令flash读取速度足够快,cpu就可以相应提速。这句话载自网络,没太理解,大概意思就是发挥flash的读取极限,但是仍然跟不上CPU的速度。
3 E  r' Y( C. G' S, E) m  W第三种是使用ITCM内存的情况下开ART,这种模式就牛逼了,ART存取和预取的指令都存放到一片SRAM内存中,大部分指令(比如循环体和重载函数)都可以从这片RAM中取指令,就不用到flash读取了,因此执行指令就可以0等待了,这时才发挥CPU的全部能力5 [+ Q" w; `9 |) ]2 L
看看我的测试,在168M下开ITCM能提升将近一倍的速度。
9 ~9 j9 ~# ?8 @! w+ d/ Y$ `9 ]; v
26.jpg
& W' Q: H5 e! }; Y6 [3 B. b& D
! {, o, n' y  R# X
看看ITCM和DTCM在存储空间的映射,他们不再一个区域。DTCM和SRAM在一起,功能也相近;ITCM映射到了和flash一个区,根据功能确定的。但是具体使用地址是在映射接口区0x00200000----0x0027ffff) K3 }) i' h: c) ^
重新看了F722的datasheet,不是所有的F7核都支持双精度浮点运算,这款芯片只支持单精度浮点运算,所以双精度浮点运算比单精度浮点运算慢好多倍,如果支持的话应该能基本持平,回头有支持双精度的F7了去试一下。
/ }9 H9 R8 E+ F! F
dlx6969 回答时间:2018-2-4 22:01:11
void Test1(void)
9 k; B. X, J' N7 K. V+ e+ X/*用默认math.h和单精度浮点数测试*/3 V2 f2 z: W# n- {5 l6 F0 }$ |
{. g, T, a; `# ?
        uint16_t i=0;2 R6 {. g- z* G* s0 z0 J
        float Tr=0.0f;/ S2 l  s* J3 b( J6 _/ g6 |5 j$ D% g
        float Ti=0.0f;) l* Y' L% x* q  S; ?
        float Temp=0.0f;
1 F3 o4 ]1 }0 F' S& m$ [& O6 N7 ~        for(i=0;i<1000;i++); L- e" U1 Y$ N7 i/ @
        {
0 t  f) \0 f+ p7 B$ b                Tr+=1.0f;
7 U* {. d, R' A+ e3 j2 P                Ti+=10.0f;
. p  m: o/ Y4 F) d                Temp=Ti-Tr*cos(2.0f*PI*i/N)+Ti*sin(2.0f*PI*i/N);. q' {  l0 g" B4 u0 B
        }' T% q" w( M! a. d% ~
}
" j0 z, e! K. l* D' Pvoid Test2(void)) A0 W: @# p) H  P' J; ?6 z' B  `
/*用默认math.h和双精度浮点数测试*/9 Q  i# ?, a+ k% D
{
$ H- }" a9 \) J/ t- O        uint16_t i=0;6 @4 r& Q( r! H' P1 O! R( n7 s
        float Tr=0.0;$ ^$ r. L! f% [- f. J9 W
        float Ti=0.0;4 E+ J5 I1 A9 i1 P3 L
        float Temp=0.0;; E' k: ]; f1 O+ r# X% h  [
        for(i=0;i<1000;i++)4 F6 J4 `) {/ b
        {
5 i3 j- T. D; s                Tr+=1.0;
3 r  s4 ^, N' E4 V                Ti+=10.0;
8 u$ T" e: I: f# G2 ]                Temp=Ti-Tr*cos(2.0*PI*i/N)+Ti*sin(2.0*PI*i/N);6 p7 B/ B7 g9 ~6 V% i0 C- y
        }
1 ?  I2 m9 Z, L  y" ?/ `3 ]+ V}7 t( \: ]6 a3 p6 W- {
void Test3(void)
' z" X3 b- F% C9 n, [9 t9 y/*用DSP库和单精度浮点数测试*/
5 R( w$ e; O" q" K8 n{
# X6 ~& K1 T8 _4 `        uint16_t i=0;2 j7 a, |/ d/ N
        float Tr=0.0f;3 r' a7 `6 n4 o
        float Ti=0.0f;3 Q' ]+ A$ Y3 T% e) Y
        float Temp=0.0f;
) `# Z! K8 ~8 O+ j        for(i=0;i<1000;i++)7 L  ], h3 T& x5 \
        {+ K$ f+ D  _8 g& @/ H. g
                Tr+=1.0f;$ r% e; c* D9 q- Z1 s) R9 `
                Ti+=10.0f;
) l! m  r) ?# m2 b2 z' Z                Temp=Ti-Tr*arm_cos_f32(2.0f*PI*i/N)+Ti*arm_sin_f32(2.0f*PI*i/N);
4 t1 S* \: o! ^4 F# q5 m        }. q3 u3 a" D" m  b( w
}
( F  F$ v! G$ x  I2 H, Fvoid Test4(void): ?9 S+ t; L2 b/ B3 c% |) U; f
/*用DSP库和双精度浮点数测试*/
  i+ L6 c6 X+ H( q$ v5 x{) V8 U# m& g4 M) ?
        uint16_t i=0;
: R4 D8 ^. @& \& S! R8 I        float Tr=0.0;+ D% h4 s* I% f2 d5 N5 m
        float Ti=0.0;
. x6 @) @+ j! G        float Temp=0.0;
1 U8 p& ]9 j% X' v        for(i=0;i<1000;i++)
0 Q8 ?- @, G) o7 Y        {6 L4 R- r2 u3 N' a2 c' q
                Tr+=1.0;/ e8 \5 C$ N% ?1 a
                Ti+=10.0;% _! k" E( e; w. f
                Temp=Ti-Tr*arm_cos_f32(2.0*PI*i/N)+Ti*arm_sin_f32(2.0*PI*i/N);
( r$ B5 R. y. @6 _2 m( L        }  Q& J6 i8 g/ N+ A1 d
}, c0 j/ C3 l1 [. i& {" G
涛哥2035 回答时间:2017-12-26 11:07:32
STM32微控制器浮点单元演示.pdf (779.25 KB, 下载次数: 111)
wolfgang 回答时间:2017-12-26 11:19:22
干货,支持一下。, i+ K- A5 G" O' F
6 o! N$ q3 N: A7 }- |+ a
是不是可以这样,综述一下:
$ }, t; X: G7 g' c$ \虽然STM32F4的DSP单位时间内的处理能力有些吃力,但STM32F7的DSP处理能力已经能满足基本需求了。
pythonworld 回答时间:2017-12-26 12:04:44
绝对技术贴!!!!
涛哥2035 回答时间:2017-12-26 12:42:23
本帖最后由 whtt 于 2017-12-26 12:49 编辑
9 r0 `8 d9 L. ~) V4 n8 G
wolfgang2015 发表于 2017-12-26 11:195 }7 q% u) g% ^4 S5 s% |, N7 q
干货,支持一下。& v$ E) _6 g7 u: \. r. K* x- _, u( O

* j+ l2 \- G, Y) J$ ?是不是可以这样,综述一下:
回复怎么跑上面去了?
大碗刚 回答时间:2017-12-26 14:27:28
围观一下
g921002 回答时间:2017-12-26 19:02:12
使用DCache跟ICache時,如果使用DMA存取周邊要注意同步問題。
涛哥2035 回答时间:2017-12-27 10:03:12
STM32F7系列的系统架构和性能.pdf (1.31 MB, 下载次数: 42)
涛哥2035 回答时间:2017-12-27 10:03:49
g921002 发表于 2017-12-26 19:020 _5 V2 W' S5 I, Q, s( o
使用DCache跟ICache時,如果使用DMA存取周邊要注意同步問題。
% X+ ^: o; G/ m6 ]0 l
望大师指点
dlx6969 回答时间:2018-2-4 22:00:45
楼主:我按照你的测试方式,循环次数为1000次,对F767进行了测试。每运算完一次,对IO进行一次取反操作,测波形得到的计算时间。单精度DSP -O0 ,时间 960us;双精度DSP -O0 浮点数不带f 1.2ms;当数据带f和单精度时间一致,为什么我的单精度和双精度计算时间没有太大区别呢?
涛哥2035 回答时间:2018-2-5 10:18:52
本帖最后由 whtt 于 2018-2-5 10:24 编辑
$ n% h! q7 F2 z( o
dlx6969 发表于 2018-2-4 22:01* c( ]5 U5 P) C7 s: K. H
void Test1(void)
' `( T6 V# q6 D/*用默认math.h和单精度浮点数测试*/
% ^/ s6 {- o4 T9 S. K, a5 l/ n3 ]) s{

' M% O1 U/ W! o8 W3 [* W# W% K+ t因为我用的F722,是不带双浮点FPU单元的;而你用的F767是带双浮点FPU单元的;所以767在处理双浮点数上面是有优势的。
! ?# G" k* ~: ?0 S通过你的实验也反应出双浮点单元在处理数据上面,如果数据精度要求不高的话,单精度比双精度数据处理速度上还是有一点点优势的; _1 A, a( Q. ~+ {
涛哥2035 回答时间:2018-2-5 10:21:29
dlx6969 发表于 2018-2-4 22:01$ b: M+ b4 m& d! r$ `
void Test1(void)
8 |& Z! ~4 a- S/*用默认math.h和单精度浮点数测试*// K: r. t/ E! @
{

4 M) z7 X: m. D 1.png " H) }: W: h" t1 j( }
12下一页

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版