首页 > 其他分享 >IQMath定点数运算库性能测试

IQMath定点数运算库性能测试

时间:2024-04-03 23:11:50浏览次数:20  
标签:index 运算 VECTOR static result 定点数 IQMath iq15 SIZE

基本信息

单片机:GD32F303RC,运行主频:120MHz,SRAM:48KB,Flash:256KB,带单精度FPU
编译环境:ARMCC 5.06 update6 (build750)

由于iq数的底层数据类型是4字节的int32_t因此_iq30 ~ _iq1 尽管表示的精度不同,但是运算速度是相同的。下列测试使用_iq15作为被测数据类型,能表示的范围从-65536到65535.999969483,精度是0.000030518/LSB。

测试代码

声明数组变量用于存储两个操作数向量和一个结果向量

#define CONST_PI_VAL 3.1415926f

#define VECTOR_SIZE  1000

static _iq15 ResultVector[VECTOR_SIZE];
static _iq15 VectorA[VECTOR_SIZE];
static _iq15 VectorB[VECTOR_SIZE];

static float ResultVectorF[VECTOR_SIZE];
static float VectorAF[VECTOR_SIZE];
static float VectorBF[VECTOR_SIZE];

测试数组的初始化,_IQ15(1.0221f)这种IQ立即数在编译时就已确定,因此VectorA[index] = _IQ15(1.0221f) * index; 等效于两个32位数据相乘,数组初始化不计入测试时间。

static void BenchmarkVectorIQArrayInit(void) {
    unsigned int index = 0u;
    for(index = 0; index < VECTOR_SIZE; index++) {
        VectorA[index] = _IQ15(1.0221f) * index;
        VectorB[index] = _IQ15(2.127f) * index;
        ResultVector[index] = 0;
    }
}

static void BenchmarkVectorFloatArrayInit(void) {
    unsigned int index = 0u;
    for(index = 0; index < VECTOR_SIZE; index++) {
        VectorAF[index] = 1.0221f * index;
        VectorBF[index] = 2.127f * index;
        ResultVectorF[index] = 0.0f;
    }
}

IQ数累加和浮点数累加

static void VectorIQAdd(_iq15 *vectorA, _iq15 *vectorB, _iq15 *result) {
    unsigned int index = 0u;
    for(index = 0; index < VECTOR_SIZE; index++) {
        result[index] = vectorA[index]+ vectorB[index];
    }
}

static void VectorFloatAdd(float *vectorA, float *vectorB, float *result) {
    unsigned int index = 0u;
    for(index = 0; index < VECTOR_SIZE; index++) {
        result[index] = vectorA[index] + vectorB[index];
    }
}

IQ数相乘和浮点数相乘

static void VectorIQMultiply(_iq15 *vectorA, _iq15 *vectorB, _iq15 *result) {
    unsigned int index = 0u;
    for(index = 0; index < VECTOR_SIZE; index++) {
        result[index] = _IQ15mpy(vectorA[index], vectorB[index]);
    }
}

static void VectorFloatMultiply(float *vectorA, float *vectorB, float *result ) {
    unsigned int index = 0u;
    for(index = 0; index < VECTOR_SIZE; index++){
        result[index] = vectorA[index] * vectorB[index];
    }
}

IQ数除法和浮点数除法

static void VectorIQDiv(_iq15 *vectorA, _iq15 *vectorB, _iq15 *result) {
    unsigned int index = 0u;
    for(index = 0; index < VECTOR_SIZE; index++) {
        result[index] = _IQ15div(vectorA[index], vectorB[index]);
    }
}

static void VectorFloatDiv(float *vectorA, float *vectorB, float *result) {
    unsigned int index = 0u;
    for(index = 0; index < VECTOR_SIZE; index++) {
        result[index] = vectorA[index] / vectorB[index];
    }
}

IQ数乘加和浮点数乘加,y=kx+b

static void VectorIQScale(_iq15 *vectorA, _iq15 *vectorB, _iq15 *result) {
    unsigned int index = 0u;
    for(index = 0; index < VECTOR_SIZE; index++) {
        result[index] = _IQ15mpy(vectorA[index], _IQ15(CONST_PI_VAL));
        result[index] += vectorB[index];
    }
}

static void VectorFloatScale(float *vectorA, float *vectorB, float *result) {
    unsigned int index = 0u;
    for(index = 0; index < VECTOR_SIZE; index++) {
        result[index] = (vectorA[index] * CONST_PI_VAL) + vectorB[index];
    }
}

性能测试使用Cortex-m4自带的32位DWT计数器,计数频率和CPU主频相同。

static void hw_dwt_init(void) {
    // DWT timer enable
    CoreDebug->DEMCR = 0x1000000;
    // clear Cycle Count Register
    DWT->CYCCNT = 0x0;
    // enable  Data Watchpoint and Trace Register
    DWT->CTRL = 0x1;
}

测试代码模板,由于测试代码执行时间较短,不用考虑DWT计数器溢出问题。

    start = DWT->CYCCNT;
    // 此处运行测试代码
    end = DWT->CYCCNT;
    diff = end - start;
    rt_kprintf("elapse:%d\n", diff);

测试结果

IQ数和单精度软浮点数对比,单片机未开启FPU,代码优化等级-O3,计算次数1000。
image
image
image

DWT计数原始数据:120MHz

数据类型 加法 乘法 除法 乘加
iq15 11006 41007 155487 49006
软浮点 64454 57436 240989 116753

DWT换算时间:微秒

数据类型 加法 乘法 除法 乘加
iq15 91.716 341.725 1295.725 408.383
软浮点 537.116 478.633 2008.2416 972.9416

IQ数和单精度硬浮点数对比,单片机开启单精度FPU,代码优化等级-O3,计算次数1000。
image
image
image

DWT计数原始数据:120MHz

数据类型 加法 乘法 除法 乘加
iq15 11006 41007 155454 49006
硬浮点 17007 17007 30007 19039

DWT换算时间:微秒

数据类型 加法 乘法 除法 乘加
iq15 91.716 341.725 1,295.45 408.383
硬浮点 141.725 141.725 250.0583 158.6583

总结

IQ数相比软浮点数性能提升

加法 乘法 除法 乘加
提升百分比 82.92% 28.604% 35.47% 58.02%

IQ数相比硬浮点数性能提升(下降)

加法 乘法 除法 乘加
提升/下降百分比 35.28% -58.52% -80.697% -61.149%

在单片机有浮点数加速单元的情况下,开启浮点数协处理器CP10,并且打开编译器的硬浮点代码生成,乘法和除法直接使用float数据类型进行计算的速度是最快的;而IQ定点数只在加法和减法有优势,因此结合两者使用能带来最大的性能提升。(IQ定点数可以和浮点数相互转换)

在没有FPU的单片机,例如不带FPU的Cortex-M4,Cortex-M0,ARM9等内核,使用IQMathlib提供的定点数替代软浮点数会带来性能的提升。

即使是精心优化的软件代码也难以敌过硬件加速器带来的性能提升,有浮点数运算需求尽量选择带FPU的单片机。

标签:index,运算,VECTOR,static,result,定点数,IQMath,iq15,SIZE
From: https://www.cnblogs.com/yanye0xcc/p/18113654

相关文章

  • 运算符&选择语句
    运算符运算符和表达式概述运算符:对字面量或者变量进行操作的符号;表达式:用运算符把字面量或者变量连接起来符合java语法的式子就可以称为表达式。不同运算符连接的表达式体现的是不同类型的表达式。举例说明:inta=10;intb=20;intc=a+b;+   :是运算符,是算......
  • 浮点数转定点数(自编函数)
    方法:1、计算b=a*2^F,其中F是变量的分数长度,b是用十进制表示的。2、将所得b的值四舍五入到最接近的整数值。3、将(2)所得的b从十进制转换为二进制表示,并命名为新变量c。4、现在,假设c,需要n位来表示二进制中b的值。另一方面,通过模拟得到了W和F的值。所以W的值应该是等于或大于n。如果为......
  • 计算机组成与系统结构-第3章 运算方法和运算部件 上
    文章目录3.1高级语言和机器指令中的运算3.1.1C语言程序中涉及的运算数据的运算3.1.2MIPS指令中涉及的运算3.2基本运算部件3.2.1全加器和加法器全加器(FullAdder,简称FA)串行进位加法器/行波进位加法器(carryrippleadder,CRA)。3.2.2并行进位加法器3.2.3带标志加法器3......
  • 由浅到深认识Go语言(4):常量&运算符
    该文章Github地址:https://github.com/AntonyCheng/go-notes【有条件的情况下推荐直接访问GitHub以获取最新的代码更新】在此介绍一下作者开源的SpringBoot项目初始化模板(Github仓库地址:https://github.com/AntonyCheng/spring-boot-init-template【有条件的情况下推荐直......
  • 【系统结构】向量A和B长度为8,进行点积运算A·B
    向量A和B长度为8,进行点积运算A·B,计算(1)(2)两种结构处理完成全部结果的最少时钟拍数。设处理机中每个部件输出的结果均可直接送到任何部件的输入端或存人缓冲器中,其间的传输正时不计,指令和令源操作数均能连续提供。(1)处理机有一个乘一加双功能静态流水线,乘、加均由5个流水段构成......
  • 定点数和浮点数
    定点数和浮点数定点数定点数:表示数据时小数点的位置固定不变。定点整数:纯整数,小数点在最低有效数值位之后。定点小数:纯小数,小数点在最高有效数值位之前。浮点数浮点数:小数点位置不固定的数。浮点表示法:N=2的E次方*F其中:E位阶码,F位尾数。阶码通常为带符号的纯......
  • 运算放大器
    理论介绍运放的内部结构包括差分放大电路、多级放大电路和偏置电路,这些都是确保运放正确工作的关键要素。封装和原理图符号运放封装:运放有多种封装形式。五个引脚:正输入端(非反转输入端,V+):这个引脚用于接收输入信号,与负输入端共同定义了输入信号的差分。负输入端(反转输入......
  • Java中的运算符有哪些类型
    目录算术运算符比较(关系)运算符逻辑运算符位运算符赋值运算符特殊运算符总结在Java语言中,运算符是用于执行特定操作的符号,比如算术运算、比较或逻辑运算。Java中的运算符可以大致分为以下几类:算术运算符比较(关系)运算符逻辑运算符位运算符赋值运算符特殊运算符(如条件......
  • 4.运算符 与 流程语句
    【一】程序与用户交互1)输入(input)2)输出(print)1.简单字符串print('hello,word!')2.多个变量输出a='one'b='two'print(a,b)#onetwo3.默认end参数print('hello',end='_')print('word!')#hello_word!【二】基本运算符1)算术运算符......
  • C++:取模运算符(15)
    取模运算也就是取余数取模10%319余1 简单的取模取模运算 可以看到他的本质就是先将数进行除法运算后的余数#include<iostream>usingnamespacestd;intmain(){ inta1=10; intb1=3; cout<<a1%b1<<endl; system("pause"); return0;} 被除数......