ARM内核矩阵计算教程(STM32)

Wesley13
• 阅读 1435

我们在嵌入式上跑矩阵运算时候,会遇到这样一个问题。

假设将矩阵设置成N*N维的二维数组后,我们想求两个矩阵相乘,那就需要按照矩阵计算规则编写矩阵相乘函数,这样的话4*4矩阵得编一个,5*5矩阵又得编一个,要求逆还得编一个,求行列式还得编。

自己写的函数代码效率容易低,将导致本来要跑在单片机上的算法,难达到想象计算速度。

这篇教程将教会你如何使用arm内核库的矩阵计算函数,让你降低代码编写难度还能提高运算效率。据笔者所知,M4内核自带DSP库。

1.创建新模板工程(这里使用的是keil创建工程)

创建一个对应MCU的新模板工程(添加必要的库引用和创建.C文件,详情略)

2.引入arm内核的DSP库文件(含矩阵计算库)

ARM内核矩阵计算教程(STM32)

勾选CMSIS下的DSP,确认后将添加库引用至工程

ARM内核矩阵计算教程(STM32)

3.添加矩阵函数库

在main函数添加引用,”arm_math.h”

ARM内核矩阵计算教程(STM32)

还需在”option of target”中”C/C++”中的define栏添加“,ARM_MATH_CM4”以声明开启arm_math库

ARM内核矩阵计算教程(STM32)

再到”option of target”中”target”勾选一下”Use MicroLIB”

ARM内核矩阵计算教程(STM32)

4.矩阵计算

//声明大小为NN的浮点一维数组NN=N*N,此处将矩阵转换成一维数组

float32_t Data1[NN] = {};

float32_t Data2[NN] = {};

float32_t Data3[NN];

//声明ARM矩阵类型指针

arm_matrix_instance_f32 Matrix_data1;//再设立

arm_matrix_instance_f32 Matrix_data2;

arm_matrix_instance_f32 Matrix_data3;

//将一维数组地址赋予给ARM矩阵指针

arm_mat_init_f32(&Matrix_data1,N,N,(float32_t *)Data1);

arm_mat_init_f32(&Matrix_data2,N,N,(float32_t *)Data2);

arm_mat_init_f32(&Matrix_data3,N,N,(float32_t *)Data3);

//使用矩阵相乘函数arm_mat_mult_f32

arm_mat_mult_f32(&Matrix_data1,&Matrix_data2,&Matrix_data3);

总结分析

在ARM内核的单片机中, ARM提供了矩阵运算库”arm_math”。在设置好库引用后,需存入用一维数组表示的矩阵值,再将矩阵的一维数组传递给ARM_matrix的指针,在声明函数中将设置矩阵的行列数,再调用库中的各类运算指令就可。

Ps:在本人stm32单片机上测试,arm自带函数只能计算至16维以内(不含16维)的矩阵计算,大于等于16维矩阵单片机编译没报错,但单片机不正常运行。小编水平有限这个存在疑惑,欢迎大佬们交流。

附图

经测试80M的系统时钟下,两个15维矩阵相乘时间约430us,两个4维矩阵相乘时间仅需14us,这计算速度还是很让人满意的。

ARM内核矩阵计算教程(STM32)

附上代码(注释部分为arm官方例程,包括相乘求逆求行列式)

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "arm_math.h"
#include<stdio.h>
#include<stdlib.h>

#define N 4
#define NN 16

float32_t a = 100;
float32_t Data1[NN] = {};
float32_t Data2[NN] = {};
float32_t Data3[NN];

arm_matrix_instance_f32 Matrix_data1;
arm_matrix_instance_f32 Matrix_data2;
arm_matrix_instance_f32 Matrix_data3;

//const float32_t B_f32[4] =
//{
//  782.0, 7577.0, 470.0, 4505.0
//};

///* --------------------------------------------------------------------------------
//* Formula to fit is  C1 + C2 * numTaps + C3 * blockSize + C4 * numTaps * blockSize
//* -------------------------------------------------------------------------------- */

//const float32_t A_f32[16] =
//{
//  /* Const,   numTaps,   blockSize,   numTaps*blockSize */
//  1.0,     32.0,      4.0,     128.0,
//  1.0,     32.0,     64.0,    2048.0,
//  1.0,     16.0,      4.0,      64.0,
//  1.0,     16.0,     64.0,    1024.0,
//};


///* ----------------------------------------------------------------------
//* Temporary buffers  for storing intermediate values
//* ------------------------------------------------------------------- */
///* Transpose of A Buffer */
//float32_t AT_f32[16];
///* (Transpose of A * A) Buffer */
//float32_t ATMA_f32[16];
///* Inverse(Transpose of A * A)  Buffer */
//float32_t ATMAI_f32[16];
///* Test Output Buffer */
//float32_t X_f32[4];

///* ----------------------------------------------------------------------
//* Reference ouput buffer C1, C2, C3 and C4 taken from MATLAB
//* ------------------------------------------------------------------- */
//const float32_t xRef_f32[4] = {73.0, 8.0, 21.25, 2.875};

//float32_t snr;

int i = 0,t = 0,j = 0;

int main(void)
{
    HAL_Init();                         //初始化HAL库
    SystemClock_Config();                //初始化系统时钟为80M
    __HAL_RCC_GPIOE_CLK_ENABLE();       //开启GPIOE时钟
    uart_init(115200);        //初始化串口,速率为115200
    while(1)
    {
            for(i=0;i<NN;i++)
                Data1[i]=rand()/(double)(RAND_MAX/100);
            for(i=0;i<NN;i++)
                Data2[i]=rand()/(double)(RAND_MAX/100);
            arm_mat_init_f32(&Matrix_data1,N,N,(float32_t *)Data1);
            arm_mat_init_f32(&Matrix_data2,N,N,(float32_t *)Data2);
            arm_mat_init_f32(&Matrix_data3,N,N,(float32_t *)Data3);
            arm_mat_mult_f32(&Matrix_data1,&Matrix_data2,&Matrix_data3);
    
            for(i=0;i<N;i++)
        {
            for(j=0;j<N;j++)
                printf("%f  ",Data3[i*N+j]);
            printf("\r\n");
        }
//  arm_matrix_instance_f32 A;      /* Matrix A Instance */
//  arm_matrix_instance_f32 AT;     /* Matrix AT(A transpose) instance */
//  arm_matrix_instance_f32 ATMA;   /* Matrix ATMA( AT multiply with A) instance */
//  arm_matrix_instance_f32 ATMAI;  /* Matrix ATMAI(Inverse of ATMA) instance */
//  arm_matrix_instance_f32 B;      /* Matrix B instance */
//  arm_matrix_instance_f32 X;      /* Matrix X(Unknown Matrix) instance */

//  uint32_t srcRows, srcColumns;  /* Temporary variables */
//  arm_status status;

//  /* Initialise A Matrix Instance with numRows, numCols and data array(A_f32) */
//  srcRows = 4;
//  srcColumns = 4;
//  arm_mat_init_f32(&A, srcRows, srcColumns, (float32_t *)A_f32);
//  
//  /* Initialise Matrix Instance AT with numRows, numCols and data array(AT_f32) */
//  srcRows = 4;
//  srcColumns = 4;
//  arm_mat_init_f32(&AT, srcRows, srcColumns, AT_f32);
//    

//  /* calculation of A transpose */
//  status = arm_mat_trans_f32(&A, &AT);

////
//    for(i=0;i<16;i++)
//        printf("%f,",AT_f32[i]);
//    printf("\r\n");

//  /* Initialise ATMA Matrix Instance with numRows, numCols and data array(ATMA_f32) */
//  srcRows = 4;
//  srcColumns = 4;
//  arm_mat_init_f32(&ATMA, srcRows, srcColumns, ATMA_f32);

//  /* calculation of AT Multiply with A */
//  status = arm_mat_mult_f32(&AT, &A, &ATMA);

//  /* Initialise ATMAI Matrix Instance with numRows, numCols and data array(ATMAI_f32) */
//  srcRows = 4;
//  srcColumns = 4;
//  arm_mat_init_f32(&ATMAI, srcRows, srcColumns, ATMAI_f32);

//  /* calculation of Inverse((Transpose(A) * A) */
//  status = arm_mat_inverse_f32(&ATMA, &ATMAI);

//  /* calculation of (Inverse((Transpose(A) * A)) *  Transpose(A)) */
//  status = arm_mat_mult_f32(&ATMAI, &AT, &ATMA);

//  /* Initialise B Matrix Instance with numRows, numCols and data array(B_f32) */
//  srcRows = 4;
//  srcColumns = 1;
//  arm_mat_init_f32(&B, srcRows, srcColumns, (float32_t *)B_f32);

//  /* Initialise X Matrix Instance with numRows, numCols and data array(X_f32) */
//  srcRows = 4;
//  srcColumns = 1;
//  arm_mat_init_f32(&X, srcRows, srcColumns, X_f32);

//  /* calculation ((Inverse((Transpose(A) * A)) *  Transpose(A)) * B) */
//  status = arm_mat_mult_f32(&ATMA, &B, &X);

////  /* Comparison of reference with test output */
////  snr = arm_snr_f32((float32_t *)xRef_f32, X_f32, 4);

    }
}
点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Stella981 Stella981
2年前
Opencv中Mat矩阵相乘——点乘、dot、mul运算详解
Opencv中Mat矩阵相乘——点乘、dot、mul运算详解2016年09月02日00:00:36 \牧野(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fme.csdn.net%2Fdcrmg) 阅读数:59593
Stella981 Stella981
2年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Wesley13 Wesley13
2年前
C++矩阵处理库
项目要进行比较多的矩阵操作,特别是二维矩阵。刚开始做实验时,使用了动态二维数组,于是写了一堆Matrix函数,作矩阵的乘除加减求逆求行列式。实验做完了,开始做代码优化,发现Matrix.h文件里适用性太低,而且动态二维数组的空间分配与释放也影响效率,于是寻找其他解决方案。首先考虑的是与Matlab混合编程,折腾了半天把Matlab环境与VS2010环境之
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Wesley13 Wesley13
2年前
R语言相关关系可视化函数梳理(附代码)
当考察多个变量间的相关关系时,通常将多个变量的两两关系以矩阵的形式排列起来,R提供了散点图矩阵、相关矩阵等多种可视化方案,囊括了众多函数。本文对R语言相关关系可视化的函数进行了初步梳理(全篇框架如下),后续大家可根据个人需求及函数功能择优选择。!ca2a37780049afa7173657f022b8b242bc816d00(https://yqfi
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这