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

基于STM32H7芯片的矩阵运算应用示例

[复制链接]
yumeii 发布时间:2019-12-27 15:12
在STM32的应用开发过程中,我们有时可能涉及到DSP应用,需要使用到相关DSP函数。这里基于STM32H743芯片的Nucleo开发板,做个有关矩阵运算应用的演示,简单的演示下两个矩阵相乘的实现过程。
1 K: l3 ~" W( o1 j& n2 u+ r+ t! j* C5 Y5 m$ a7 i+ [! R( v$ g
开发环境选择的是ARM MDK,当然你也可以选其它的,比方IAR, STM32CubeIDE等。4 E' P' b& o5 H' E, w
0 M& J4 z5 Q  S1 [4 _6 B
2 A. G, j: l! m- o* ]2 _9 c
我们要用到ARM提供的DSP函数库,该库在STM32的Cube库或标准库里都可以找到。
5 @9 h: V, d) K, K1 Z
% U: [# w2 S- j% K- U& M

1 w9 y! W& L% `2 Z' A5 R: n以STM32CubeH7的库为例,相应的DSP函数库一般在下面位置:; S! b3 G8 d% b, f
1 ^, P  E& Q. R
: k* T$ U/ u; C0 B$ I9 x
1.png
! b( o! B5 W: N" i5 S( ^1 J  T$ B/ F$ x
# U' j7 K/ t) |
上图中绿色方框内的函数即为跟矩阵相关的函数库文件。5 h- i- k& p8 o+ E, r7 g

- X  V. ?# N. @, m# [% S/ m0 _

1 n3 h' O* s0 R( s具体使用时,我们直接添加相应的lib库进来即可,不过,添加该lib库文件时要注意两点:
5 x: o+ ?7 c  N7 y! ^1 U( H* B7 E1 y$ `
0 B. U- p6 S# _! m6 `0 E
你选择的库文件要跟你芯片类型一致,内核类型、大小端模式、是否支持浮点运算。
. _' g; n+ Q+ Z) B/ l1 P( \  i9 p: l/ {2 m4 H' _
3 Y7 m& C7 T& f- q( z) j# C
你选择的库文件还要跟你所使用的编译器匹配,即IDE是MDK还是IAR等。; z4 W& U* S' F1 K

6 }* e: p* g/ |3 @" ?' u
6 J! T: E4 n% d- u1 e, U
基于上面两点我们添加arm_cortexM7lfdp_math.lib文件【corex M7、小端模式、支持硬件浮点单元】。
+ `0 A6 I; d* c" s
6 O, t# Y: d3 n* R! w5 x  y* d% P

4 I  X1 Q4 I  I0 n0 ~: w; w8 L 2.png ( q  g; ]( y: f6 W& a4 X

8 `8 y. w% a/ G5 U' d3 j8 J

" f, O' v1 u8 I/ w! Q- U在我们的main()文件里添加arm_math.h头文件。记得在IDE环境的配置里添加相应的搜索路径。启用硬件浮点运算单元。开启有关宏定义。【宏开关不用特别去记,缺少的话编译时会报错】
; w$ Q5 n1 L5 a& @1 ]2 l- c7 L/ `6 y' m
, Q* z4 V" L3 t6 U
3.png 4 C( g. T8 H* H( i' Z
3 ^: H2 A; d/ C: X" D" u% G& J
: ^" u, _0 h; x6 ~9 u* i7 ?# H' z
下面构造三个矩阵,A矩阵的数据表示某家芯片代理商为他的8个客户分别提供四种不同规格的芯片,数据以包为单位。不同型号的包装规格不一样。A矩阵为8X4矩阵。
' U6 E+ M2 @" r5 s! o. {7 h7 e% L2 M# F% H) c) b

; r3 t# }8 a. C2 J) h( HB矩阵表示A矩阵中各类包装每包的数量、价格、运费、重量,为4X4矩阵。
, X( R6 D. R  P
- P) g- t+ u1 M, d

' E: u" q0 M; m二者的矩阵乘积表示各个收货方收到芯片的总数、应付货款、运费、以及货物总重量,将构成8X4矩阵。矩阵里的数据使用浮点数,数据随意设计的。
1 B+ A5 R( t, |0 g$ p% l
& t* H# D9 i2 ?/ D) g我们知道,两个矩阵可乘有个前提,比方A*B,矩阵A的列数应该等于矩阵B的行数,相乘后所得的乘积矩阵的行数等于矩阵A的行数,其列数等于矩阵B的列数。
( {; w: e# w% E% J, z. r* n1 J% ~6 l2 `6 C* c, \- v2 @

( P! w" V0 M* P" X1 [具体到这里,矩阵A的行数为8,列数为4,矩阵B的行数、列数均为4。A*B所得矩阵的行数为8,列数为4.
$ ?2 t; V. Y: L% \0 U
- T& y( n0 E. b8 i! ]. ^0 z/ ^4 j* w, u
, n) R- }' q, A* H
4.png # h8 t8 T7 O. |- ~* _  ^/ j

& B1 s, G  `7 a  T

4 c: S: E8 F) X5 T7 Q  L  c" J 5.png 8 Y8 i8 T+ X9 B! G
/ U6 a& O1 Q$ F6 @  E) A% a
5 m% ]8 X! t" v' @. G
下面做相关代码的准备。7 [0 ?7 L" @2 R

2 T2 w' `4 e% T  |" ^6 {9 U2 @' h( F

& b& Z- M  m0 J: \( T定义三个数组,pDataA[32]数组对应矩阵A, pDataB[16]数组对应矩阵B,第3个数组pDataC[32]对应矩阵AB乘积所得的新矩阵。
9 k5 ^" ^) D: x9 s& O' Q. j* ?6 ]9 G0 w  r$ J
" S; D/ V* b1 F! r- ^
6.png / u5 Y- B0 B. K: Y9 A7 R, b

# a4 c9 M& {  U# e; f

7 P9 G! s  A7 X  q基于上面的3个数组定义3个如下矩阵变量:
8 k% p1 i& b0 X- s, f4 C6 H" o" I, b/ ?$ ?# K6 W
% w5 @4 N2 Q8 c' S7 b( y
7.png
$ v8 L% o9 u2 w9 y. O1 R8 }
8 j. M; L- r: t3 X% F( Y

& {( g8 w9 y6 s1 i关于结构体arm_matrix_instance_f32的定义和说明,可以在arm_math.h中看到。; V. m+ c' D, o$ |9 V" p  o9 q% g

  n& E7 d% e* A# B$ I& H
: c& c! n' B+ g5 G
8.png
5 V6 V- X  R: D8 [/ g$ U9 d- W* t
, u0 d: R( `6 P+ k6 M

# v$ ]+ A2 u0 V- V接下来对3个矩阵进行初始化,注意行、列数别给错了。
/ k% a3 y0 D  j: O
6 r5 B2 D  L1 L! J8 Q+ a
1 @; c- ?+ N# t  @# Y" Q
9.png
9 @9 A& w' a$ |1 s2 n
3 ^) \; f) H2 u+ U4 [7 l

7 \$ f6 }% Z% @6 ~3 M一切都准备好了,就可以进行矩阵乘法计算了,调用库函数中arm_mat_mult_f32()函数。
) @2 E( F( v$ `* [. D: E
0 S, ]6 F+ \% k: l3 M4 _! t( B

! G, v" Z. P  ^3 n 10.png
: l8 U' N3 P# \5 A
+ u( y& R% L: }% \' p
$ y) b4 {( c) j: R4 ~
矩阵相乘后的运算结果存放在数组pDataC[32]里面,按8*4的矩阵摆放。& V: X8 e8 J4 B

: a6 Q! `8 p7 I, o7 E) W' H: C

; [" N* p. `$ U! N- y 11.png
9 [& n% [" b) n+ e) ?0 c% `( e8 D8 Z  Y- ~8 U0 w/ M) h3 W( E2 L  j
; D' l9 c6 r7 @' ?
上述运算结果跟使用MATLAB数学工具通过矩阵乘法得到的结果整体上非常一致。数据会稍有些小出入,毕竟是基于浮点运算所得结果。
- l( u2 _9 U& B" p# b5 e6 o' T
9 d: L4 \  c% D5 }) g$ N6 S我们知道,STM32H7是带Cache和FPU的。不妨基于该矩阵乘法应用比较不同情况下的运行时间。以定时器的计数时钟为单位。根据Cache和FPU的开启与关闭的不同组合进行测试,可以做些相对比较,让我们有些直观的感受。测试时ARM MDK的优化等级为-o3。顺便提醒下,如果不开启硬件FPU,调用的DSP库函数应选择另外一个不支持硬件浮点单元的函数库。
6 j* X3 }6 [& u: f
5 Q  b. y  U3 z% m3 |7 n7 q+ ^: a) @

  L2 C: `: t5 d7 X 12.png
' I/ i9 O* l7 r* f; |$ {" n7 B" D
! D) j6 R. s$ h) u- z3 K
: z1 a; C$ x- C/ v. n, \
下面数据是基于上面测试代码所得到的,其中红色数据为十进制数据。3 P' y! s" e6 v3 {$ y* V  ]
& R5 }9 [: }! [9 \3 ?# ~# @/ p" _# R
, \7 J' S7 T  g6 n* V
13.png - I9 D0 J8 c( X# l+ Q
: K9 Q/ M! y$ o' K; V
, X% Y  e" Q; r
从这里我们可以看出,同时开启硬件FPU和Cache与同时关闭二者,运行时间相差将近40倍;开启Cache与关闭Cache运行时间上相差4倍左右;使用FPU和不用FPU,运行时间相差8倍左右。当然,或许基于不同的应用,上述数据可能存在些差异,但可以肯定,开与不开Cache、启不启用硬件FPU,运行速度上的差别还是很明显的。+ u' e- i7 f% b# @1 J/ x
0 i+ y. U. ]# ]0 X

8 g9 k) P9 O" T0 a( x. Y好,关于利用STM32及相关DSP函数库进行矩阵运算的演示就介绍到这里,请留意上文中谈到的那些提醒。其它更多细节,有兴趣的话可以进一步阅读和研究相关资料。) v: i2 L3 x9 P2 i0 l0 O: M

3 ^5 B' H" G4 R& I) V
收藏 1 评论0 发布时间:2019-12-27 15:12

举报

0个回答

所属标签

相似分享

官网相关资源

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