> 文档中心 > [W806捣鼓手记]FPU性能简单测试——2022.05.23

[W806捣鼓手记]FPU性能简单测试——2022.05.23

W806 是一款安全 IoT MCU 芯片。芯片集成 32 位 CPU 处理器,内置 UART、GPIO、SPI、SDIO、 I2C、I2S、PSRAM、7816、ADC、LCD、TouchSensor 等数字接口;支持 TEE 安全引擎,支持多种硬件加解密算法,内置 DSP、浮点运算单元与安全引擎,支持代码安全权限设置,内置 1MB Flash 存储器,支持固件加密存储、固件签名、安全调试、安全升级等多项安全措施,保证产品安全特性。适用用于小家电、智能家居、智能玩具、工业控制、医疗监护等广泛的物联网领域。


文章目录

  • FPU简介
  • 测试项目
    • 基本算法
    • 复合算法
  • 测试方法
  • 测试结果
    • 基本算法
      • 浮点与浮点的加减乘除
      • 三角函数和反三角函数
      • 开平方
      • e为底的X次幂
      • X的Y次幂
    • 复合算法
      • 100点一阶低通滤波
      • 100点正弦曲线
      • 32*32像素RGB转灰度
  • 总结
  • 参考资料

FPU简介

以下内容摘抄自《玄铁E804用户手册_v04》

浮点单元作为 E804 的可配置硬件单元,旨在提升 E804 面向浮点应用的处理能力。E804 浮点单元提供了一种低成本、高性能的硬件浮点实现。
浮点单元支持 IEEE-754 浮点标准中的单精度浮点运算,实现了 16 个单精度浮点寄存器。在系统软件支持下,E804可实现对双精度浮点运算的支持。

浮点单元的体系结构与编程模型的主要特点如下:

  • 完全兼容 ANSI/IEEE Std 754 浮点标准(系统软件支持下);
  • 仅支持单精度浮点运算;
  • 支持向零舍入、向正无穷舍入、向负无穷舍入和就近舍入四种舍入方式;
  • 支持浮点异常的陷入与非陷入两种处理模式;
  • 支持浮点异常的精确处理;
  • 支持浮点硬件除法与开方。

浮点单元的微体系结构的主要特点如下:

  • 16 个独立的单精度浮点寄存器;
  • 单发射结构,每个周期处理一条浮点算术指令;
  • 支持浮点算术指令的按序发射、按序执行、按序回写;
  • 包含三条独立的执行流水线,分别是浮点 ALU、浮点乘法与浮点除法开方;
  • 优化的执行延时技术,除浮点除法开方指令外,均可在 1-2 个时钟周期执行完毕;
  • 基于运算部件复用的成本优化技术;
  • 基于门控时钟与数据通路隔离的功耗优化技术。

测试项目

基本算法

  • 浮点与浮点的加减乘除
  • 三角函数和反三角函数
  • 开平方
  • e为底的X次幂
  • X的Y次幂

复合算法

  • 100点一阶低通滤波
  • 100点正弦曲线值
  • 32*32像素RGB转灰度

测试方法

分别记录关闭FPU和开启FPU时,10ms定时周期内的算法执行次数,值越高越好。
所有测试统一使用单精度浮点,代码-O3优化,为了尽量减少循环带来的额外开销,手动展开了最里层的循环。

测试结果

基本算法

浮点与浮点的加减乘除

__IO uint32_t cnt = 0;__IO float a = 1.1f;__IO float b = 0.123456f;__IO float c;while(1){c = a + b;c = a + b;c = a + b;c = a + b;cnt += 4;}

结果如下,减法、乘法、除法的测试方法和加法是一样的,所以测试代码就不放出来了。

算法 关闭FPU(次/10ms) 打开FPU(次/10ms) 次数比
c = a + b 12708 319268 25.12
c = a - b 11116 319268 28.72
c = a * b 18640 319268 17.13
c = a / b 5592 69412 12.41

三角函数和反三角函数

算法 关闭FPU(次/10ms) 打开FPU(次/10ms) 次数比
c = sinf(a) 440 14068 31.97
c = cosf(a) 480 15628 32.56
c = tanf(a) 236 9268 39.27
c = asinf(a) 6612 41112 6.22
c = acosf(a) 6668 37860 5.68
c = atanf(a) 336 3816 11.36

开平方

while(1){c = sqrtf(a);c = sqrtf(a);c = sqrtf(a);c = sqrtf(a);cnt += 4;}
算法 关闭FPU(次/10ms) 打开FPU(次/10ms) 次数比
sqrtf() 7364 57704 7.84

e为底的X次幂

while(1){c = expf(a);c = expf(a);c = expf(a);c = expf(a);cnt += 4;}
算法 关闭FPU(次/10ms) 打开FPU(次/10ms) 次数比
expf() 444 14404 32.44

X的Y次幂

while(1){c = powf(a, b);c = powf(a, b);c = powf(a, b);c = powf(a, b);cnt += 4;}
算法 关闭FPU(次/10ms) 打开FPU(次/10ms) 次数比
powf() 124 5308 42.8

复合算法

100点一阶低通滤波

__IO float t1[100];__IO float t2;static inline float first_oder_filter(float new_data){  static float old_data;  float a = 0.05f;  old_data = a * new_data + (1.0f - a) * old_data;  return old_data;}int main(void){SystemClock_Config(CPU_CLK_240M);for (uint32_t i = 0; i < 100; i++){t1[i] = rand() / (float)(RAND_MAX / 0xffff);}while (1){for (uint32_t i = 0; i < 100; i += 4){t2 = first_oder_filter(t1[i]);t2 = first_oder_filter(t1[i + 1]);t2 = first_oder_filter(t1[i + 2]);t2 = first_oder_filter(t1[i + 3]);}cnt++;}return 0;}
关闭FPU(次/10ms) 打开FPU(次/10ms) 次数比
37 1940 52.43

100点正弦曲线

int main(void){SystemClock_Config(CPU_CLK_240M);/* 正弦曲线公式:y=Asin(ωx+ψ)+k */__IO float W = 3.1415926f / 50.f;__IO float A = 100.0f;__IO float k = 50.0f;__IO float offset = 6.0f;__IO float wave;__IO float x[100] = { 0.0f };float temp = 0.0f;for (uint32_t i = 0; i < 100; i++){x[i] = temp + 0.05f;}while (1){for (uint32_t i = 0; i < 100; i += 4){wave = A * sinf(W * x[i] + offset) + k;wave = A * sinf(W * x[i + 1] + offset) + k;wave = A * sinf(W * x[i + 2] + offset) + k;wave = A * sinf(W * x[i + 3] + offset) + k;}cnt++;}return 0;}
关闭FPU(次/10ms) 打开FPU(次/10ms) 次数比
4 116 29.0

32*32像素RGB转灰度

int main(void){SystemClock_Config(CPU_CLK_240M);__IO uint32_t cnt = 0;__IO uint8_t color_r[32][32];__IO uint8_t color_g[32][32];__IO uint8_t color_b[32][32];__IO uint8_t color_gray[32][32];for (uint32_t i = 0; i < 32; i++){for (uint32_t j = 0; j < 32; j++){color_r[i][j] = rand() % 0xff;color_g[i][j] = rand() % 0xff;color_b[i][j] = rand() % 0xff;}}while (1){for (uint32_t i = 0; i < 32; i++){for (uint32_t j = 0; j < 32; j += 4){color_gray[i][j] = color_r[i][j] * 0.299f + color_g[i][j] * 0.587f + color_b[i][j] * 0.114f;color_gray[i][j + 1] = color_r[i][j + 1] * 0.299f + color_g[i][j + 1] * 0.587f + color_b[i][j + 1] * 0.114f;color_gray[i][j + 2] = color_r[i][j + 2] * 0.299f + color_g[i][j + 2] * 0.587f + color_b[i][j + 2] * 0.114f;color_gray[i][j + 3] = color_r[i][j + 3] * 0.299f + color_g[i][j + 3] * 0.587f + color_b[i][j + 3] * 0.114f;}}cnt++;}return 0;}
关闭FPU(次/10ms) 打开FPU(次/10ms) 次数比
2 61 30.5

总结

通过以上测试结果可以发现,W806的XT804内核在没有FPU时的浮点数计算能力是非常弱的,而FPU的加入可以大幅提高内核对于单精度浮点的计算能力,不管是基础算法还是复合算法,几乎都是几十倍的提升。W806的工程是默认开启FPU的,直接用就好。

参考资料

  1. 《W806 MCU 芯片规格书V2.0》
  2. 《玄铁E804用户手册_v04》