• SAM4E单片机之旅——24、使用DSP库求向量数量积


    DSP(Digital Signal Processing,数字信号处理)中会使用大量的数学运算。Cortex-M4中,配置了一些强大的部件,以提高DSP能力。同时CMSIS提供了一个DSP库,提供了许多数学函数的高效实现。

    这次就先做一个简单的尝试,求两个向量的数量积。

    一、 硬件

    image

    • MAC单元

      MAC(Multiply-ACcumulate,乘积累加),是DSP中常用的一种运算。Cortex-M4配置了一个32位的MAC单元,它能在1个周期里实现最高难度为32位乘32位再加64位的运算,或是两个16位乘16位的运算。Cortex-M4支持的MAC指令如下,这些指令都能在1个周期内完成:

      image

    • SIMD

      SIMD(Single Instruction Multiple Data,单指令多数据),可以提高DSP时的计算效率。这在Cortex-M3中不可用的。使用Cortex-M4的SIMD指令,可以在一个周期并行地完成4个8位数的加减,或是2个16位数的加减。

    • FPU

      FPU是Cortex-M4增加的可选的部件(SAM4E配备了FPU)。其实现了单精度的浮点数运算,包括一些MAC运算:

      image

    二、 使用CMSIS的DSP库

    CMSIS中,提供了一个DSP库。这里对DSP中常用的数学运算做了很高效的实现。而对于Cortex-M4,其实现也针对SIMD进行了优化。

    CMSISInclude文件夹中,头文件arm_math.h 声明了这些函数。而在CMSISLibGCC 中,有针对各平台编译好了的静态库文件。在CMSISDSP_LibSource 中,有DSP的实现源码。

    而在使用arm_math.h 文件的过程中,需要根据目标平台预定义宏ARM_MATH_CM4ARM_MATH_CM3 ARM_MATH_CM0 。而若需要使用FPU,则需要在设备头文件(如sam4e16e.h)中将宏__FPU_PRESENT 的值定义为1。

    在AS6中,默认已经添加了DSP的支持。

    1. 进入工程属性的toolchain选项卡,可以在ARM/GNU C Complier的Directories中选择编译时搜索头文件的路径。AS6在建立工程时,就会一些需要的头文件拷贝到工程目录下,同时做好了路径设置。比如AS6已经把arm_math.h 拷贝到下图中方框指出的路径了:

      image

    2. 在ARM/GNU Linker的Libraries选项中,可以选择链接时使用的库以及库的路径。同样,AS6已经把静态库文件拷贝到了工程目录下,且设置好了文件:

      image

    3. 在ARM/GNU C Complier的Symbols选项中,可以设置预定义的宏。可以在这里声明说明DSP的目标平台的宏ARM_MATH_CM4

      image

    4. 在设备头文件件中声明__FPU_PRESENT 的值。如果有FPU,则将该宏定义为1,否则定义为0。CMSIS已经做好了定义:

      //File: …srcASFsamutilscmsissam4eincludesam4e16e.h
      //Line: 266
      /**< SAM4E16E does provide a FPU */
      #define __FPU_PRESENT          1

      另外,如果不使用AS6提供的startup文件,或者需要在自己的代码中使用FPU的话,还需要做额外的设置。相关内容在FPU的示例中做了说明。

    三、 简单示例

    DSP库里有计算向量数量积的函数。DSP库的函数支持多种类型的定点数,且对于配备了FPU的部件,也支持浮点数。所以只需要简单地调用下所需函数即可:

    // 向量为(0.0, 1.1, 2.2, ..., 16.5)
    const int VEC_SIZE = 16;
    float32_t vec[VEC_SIZE];
    for (int i = 0; i < VEC_SIZE; ++i)
    	vec[i] = 1.1f * i;	
    	
    // 计算向量与自身的数量积
    float32_t result = 0;
    arm_dot_prod_f32(vec, vec, VEC_SIZE, &result);
    // result == 1500.4

    查看arm_dot_prod_f32() 的实现,发现其已经为了效率进行了循环展开。而查看另外一些有关定点数的运算,可以发现其实现已经使用了SIMD等特殊指令;有些甚至针对内存访问的延迟进行了优化。不难看出,这个库的实现进行了细致优化的。

    另外,除了基本的数学函数,DSP库也实现了快速数学函数(三角函数、开平方等)、实数相关、矩阵运算、统计、滤波、变换(FFT等)、马达控制等功能。arm_math.h 中,已经对各个函数的功能、参数意义等做了详细的说明。

  • 相关阅读:
    从1.5k到18k, 一个程序员的5年成长之路
    我是如何准备技术面试的
    10个惊艳的Ruby单行代码
    经典Spring面试题和答案
    数据分析应该要避免的6个错误
    代码重构的实战经验和那些坑
    勾勒物联网与大数据的数据中心路线图
    共筑Spark大数据引擎的七大工具
    es6学习总结(一)
    vue-cli搭建与vue-router(路由配置)
  • 原文地址:https://www.cnblogs.com/h46incon/p/3516593.html
Copyright © 2020-2023  润新知