网站首页

人工智能P2P分享搜索全网发布信息网站地图标签大全

当前位置:诺佳网 > 电子/半导体 > 嵌入式技术 >

嵌入式开发极致性能优化案例

时间:2023-06-08 11:06

人气:

作者:admin

标签: 性能优  嵌入式 

导读:我们之前进行了TFT刷屏测试确认了基本功能。刷屏速度是决定GUI显示帧率最根本的一环,只有优化到极致的刷屏速度,才能有基础实现更好效果的GUI。本篇就进行刷屏的优化,其实其思...

本文转自公众号,欢迎关注

嵌入式开发极致性能优化案例

前言

我们之前进行了TFT刷屏测试确认了基本功能。刷屏速度是决定GUI显示帧率最根本的一环,只有优化到极致的刷屏速度,才能有基础实现更好效果的GUI。本篇就进行刷屏的优化,其实其思想是通用的,对于其他代码也可以参考。

1. 减少if条件判断

if等条件判断会导致分支处理,一方面会增加指令,尤其是跳转指令一般执行时间比一般指令长,另外也会影响流水线和cache。

if(Data&0x80)


  LCD_SDA_SET; //输出数据


else LCD_SDA_CLR;

改为串行操作

#define LCD_SDA_SET_VAL(val) LCD_CTRLB- >BSRR=val;LCD_CTRLB- >BRR=val^LCD_SDA

2. 使用寄存器变量

频繁操作的局部变量尽量使用寄存器进行缓存,避免反复从内存去加载,寄存器直接操作速度快很多。

register unsigned int data;

3. 空间换时间 8次for循环改为 直接8次操作

其实在memcpy等处理中也是类似操作,比如连续8次读写组合一起,再循环。以减少for判断次数,也利于内部cache流水线处理,有一些cpu还有burst处理,这也是有利的。

inline void SPI_WriteDataF(unsigned char Data)


{


#if 0


unsigned char i=0;


for(i=8;i >0;i--)


{


if(Data&0x80)


  LCD_SDA_SET; //输出数据


else LCD_SDA_CLR;





LCD_SCL_CLR;       


LCD_SCL_SET;


Data< <=1;


}


#else


//LCD_SDA_LOCK;


register unsigned int data = (Data & 0x80) < < 0;


LCD_SDA_SET_VAL(data);


LCD_SCL_CLR;       


LCD_SCL_SET;




data = (Data & 0x40) < < 1;


LCD_SDA_SET_VAL(data);


LCD_SCL_CLR;       


LCD_SCL_SET;




data = (Data & 0x20) < < 2;


LCD_SDA_SET_VAL(data);


LCD_SCL_CLR;       


LCD_SCL_SET;




data = (Data & 0x10) < < 3;


LCD_SDA_SET_VAL(data);


LCD_SCL_CLR;       


LCD_SCL_SET;




data = (Data & 0x08) < < 4;


LCD_SDA_SET_VAL(data);


LCD_SCL_CLR;       


LCD_SCL_SET;




data = (Data & 0x04) < < 5;


LCD_SDA_SET_VAL(data);


LCD_SCL_CLR;       


LCD_SCL_SET;




data = (Data & 0x02) < < 6;


LCD_SDA_SET_VAL(data);


LCD_SCL_CLR;       


LCD_SCL_SET;




data = (Data & 0x01) < < 7;


LCD_SDA_SET_VAL(data);


LCD_SCL_CLR;       


LCD_SCL_SET;


//LCD_SDA_UNLOCK;


#endif


}

4. 使用内联函数减少函数跳转时间

inline void SPI_WriteDataF(unsigned char Data)

函数跳转需要时间,减少函数调用即可节约时间,尤其频繁调用的函数效果明显,但是可能增加存储空间。

5. 减少for循环嵌套 双重for嵌套改为一层for

For嵌套导致多重循环嵌套判断,浪费时间,顺序执行一般是优于分支处理的。

void Lcd_ClearF(unsigned int Color) //刷新全屏           
{


unsigned int i,m;


Lcd_SetRegion(0,0,X_MAX_PIXEL-1,Y_MAX_PIXEL-1);


Lcd_WriteIndex(0x2C);


for(i=0;i< X_MAX_PIXEL*Y_MAX_PIXEL;i++)


{


 LCD_CS_CLR;


 LCD_RS_SET;


 SPI_WriteDataF(Color >>8); //写入高8位数据


 SPI_WriteDataF(Color); //写入低8位数据


 LCD_CS_SET;


 }


}

6. 减少函数调用层级

函数调用影响流水线,并且需要额外的上下文处理时间

Lcd_ClearF中直接调用SPI_WriteDataF不再调用函数LCD_WriteData_16Bit

7. 使用汇编进行优化

这个实际看情况建议先用其他方式进行优化,因为人工编写汇编代码不一定比编译器编写的好,除非非常熟悉汇编并且有明确的优化方向。

8. 速度测试

循环刷屏使用定时器记录执行多次刷屏的时间,代码见附件。

9. 编译器速度优化选项

编译器-Ofast优化

图片

执行时间分别是

660ms,782ms

我们优化后的代码快15.6%

编译器-O2优化

图片

执行时间分别是661ms,908ms

我们优化后的代码快快27.2%

  • 从上可以看出不管用什么编译器优化,经过上面方式人工优化后的代码都不差不多,660和661,说明编译器已经无法对我们优化后的代码再进行优化
  • 说明我们人工优化的代码不使用编译器优化也有很好的速度性能。
  • 不同的编译器优化对原来的代码影响较大-ofast执行时间从908变为了782。
  • 哪怕是采用-ofsat编译器优化,我们人工优化的代码依然还有比编译器优化的代码快15.6%,所以编译器优化无法替代人工优化。
  • 只有从设计角度去优化,避免依赖编译器优化才是根本方案。

总结

1.优化应该从设计上去优化而不是依赖编译器,应该先找大头,优先设计原理,算法上去优化,最后采取进行汇编等底层的优化,后者成本大效果不明显不具备可移植性等,前者成本小效果明显,不依赖于编译器。

2.建议寄存器名字和手册对应比如gpio的io锁定寄存器,头文件中是LOCK 手册里是LCKR

2.对于IO操作最好设置LOCK ODR寄存器,这样可以指定bit直接写值而其他位不修改,而不需要if else判断分别配置BRR 和BSRR,可以直接操作ODR寄存器,进一步优化速度。

审核编辑:汤梓红

温馨提示:以上内容整理于网络,仅供参考,如果对您有帮助,留下您的阅读感言吧!
相关阅读
本类排行
相关标签
本类推荐

CPU | 内存 | 硬盘 | 显卡 | 显示器 | 主板 | 电源 | 键鼠 | 网站地图

Copyright © 2025-2035 诺佳网 版权所有 备案号:赣ICP备2025066733号
本站资料均来源互联网收集整理,作品版权归作者所有,如果侵犯了您的版权,请跟我们联系。

关注微信