news 2026/4/16 0:06:38

<span class=“js_title_inner“>同事用“与运算“改了这几行代码,运行效率直接起飞~</span>

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
<span class=“js_title_inner“>同事用“与运算“改了这几行代码,运行效率直接起飞~</span>


正文


大家好,我是bug菌~

1

问题背景

最近由于项目指标的需求,查了下程序各个部分的运行效率,发现一直用的环形缓冲区在耗时占比中还挺突出,于是过了一遍代码并尝试着去优化一下,没想到改动不大却得到了较大的效率提升。

如下是之前环形缓冲区的一些代码片段:

#define BUFFER_SIZE 512 uint16_t buffer[BUFFER_SIZE]; uint16_t index = 0; ...... index = (index + 1) % BUFFER_SIZE; ......

当程序高频率的调用含有取模的运算接口时执行时间超出了设计预期,同时在低优化等级(毕竟如果编译器进行了各种优化,那就不好聊下去了)下对取模运算进行了相关sysclock的测量,确实也是效率不高,于是我打算用更高效的运算方式把它替换掉。

2

与运算代替取模

当然了,与运算至少全面替代取模运算没那么容易,毕竟如果能够完全替代,也不会有人用取模了,当时对于嵌入式行业我觉得最有意思的是它并不需要非常的通用,嵌入式只需要在特定的领域,特定的工况下能做到极致就可以了,有取舍才能在有限的资源下把平台充分利用起来。

同样的思路取模运算确实很强大,但是我并不需要利用它所覆盖的方方面面,所以当除数是2的幂(即n = 2^k)时,与运算同样可以满足我的需求:

// 当 n 是 2 的幂(n = 2^k)时 a % n = a & (n - 1) // 等价的情况(n是2的幂) a % 8 == a & 7 // 8 = 2^3 a % 16 == a & 15 // 16 = 2^4 a % 32 == a & 31 // 32 = 2^5

我们知道% 运算通常需要除法指令,开销较大,而& 运算只需要按位与,速度快很多。

所以对应环形缓存区只需要优化下:

#define BUFFER_SIZE 512 // 必须为2的幂 #define BUFFER_MASK (BUFFER_SIZE - 1) // 511 = 0x1FF uint16_t buffer[BUFFER_SIZE]; uint16_t index = 0; ...... index = (index + 1) & BUFFER_MASK; // 快速回绕 ......

3

再细致一点

聊到这里,来龙去脉应该讲清楚了,其实不管了是在这一次的环形缓存区的优化中有所感悟这种方法,只要是在当除数是2的幂时这种方式都能大大提高效率,特别是一些实时性应用场景,一通百通。

比如说你要进行ADC窗口滑动:

samples[sample_index] = adc_read(); ...... // sample_index = (sample_index + 1) % WINDOW_SIZE; //直接方式 sample_index = (sample_index + 1) & WINDOW_MASK; ......

一些限制和风险我们也要非常有数,一些bug大部分都是因为我们没有提前想到:

1、在性能关键路径且除数是2的幂时,才考虑使用与运算替代取模运算,其他地方其实无关痛痒也没必要替换,所以可以做一些防御性检测:

#ifndef IS_POWER_OF_TWO #define IS_POWER_OF_TWO(x) (((x) & ((x) - 1)) == 0) #endif #define QUEUE_SIZE 128 #if !IS_POWER_OF_TWO(QUEUE_SIZE) #error "QUEUE_SIZE must be power of two for optimization" #endif #define QUEUE_MASK (QUEUE_SIZE - 1)

2、如果是处理负数大概率会出问题,要留意。

最后

好了,今天就跟大家分享这么多了,如果你觉得有所收获,一定记得点个~

唯一、永久、免费嵌入式技术知识分享平台

推荐专辑 点击蓝色字体即可跳转

MCU进阶专辑

嵌入式C语言进阶专辑

“bug说”专辑

专辑|Linux应用程序编程大全

专辑|学点网络知识

专辑|手撕C语言

专辑|手撕C++语言

专辑|经验分享

专辑|电能控制技术

专辑 | 从单片机到Linux

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/11 16:14:59

MAC物理地址和IP网络地址有什么区别?

目录 一、什么是MAC地址二、什么是IP地址三、如何隐藏真实的MAC地址四、如何隐藏真实的IP地址 一、什么是MAC地址 MAC地址,全称为媒体访问控制地址(Media Access Control Address),是一种用于网络通信的唯一标识符。它是由IEEE 8…

作者头像 李华
网站建设 2026/4/12 16:24:14

Embedding模型深度解析:从词向量到语义空间的完整指南

本文深入剖析Embedding(嵌入)模型的核心原理,从最基础的词向量概念出发,详细讲解向量空间中的语义关系、相似度计算、训练方法,以及在搜索、推荐、RAG等场景中的实际应用。 一、什么是Embedding? 1.1 从One-Hot到Embedding 问题:计算机如何理解"猫"和"…

作者头像 李华
网站建设 2026/4/15 22:42:45

Substance P (2-11) (Deca-Substance P) ;PKPQPFFGLM-NH₂

一、基础信息 英文名称:Substance P (2-11) (Deca-Substance P)三字母序列:Pro-Lys-Pro-Gln-Gln-Phe-Phe-Gly-Leu-Met-NH₂单字母序列:PKPQPFFGLM-NH₂精确分子量:1191.46 Da等电点(pI):6.0~6.…

作者头像 李华
网站建设 2026/4/15 5:13:48

48 多源动态最优潮流分布式鲁棒优化:应对风光不确定性

48多源动态最优潮流分布式鲁棒优化 关键词:分布式鲁棒优化 风光不确定性 最优潮流 Wasserstein距离 仿真软件:matlabyalmipcplex 参考文档:《多源动态最优潮流的分布鲁棒优化方法》 主要内容:针对大规模清洁能源接入电网引起的系统…

作者头像 李华
网站建设 2026/4/8 17:56:07

空指针之痛:除了 if!=null,你还有更优雅的办法吗?

一、 序言:那个价值十亿美元的错误 在 Java 世界里,java.lang.NullPointerException(NPE)是每个开发者的宿命。它的发明者 Tony Hoare 曾公开道歉,称其为“十亿美元的错误”。 在生产环境中,NPE 往往意味着…

作者头像 李华
网站建设 2026/4/11 14:29:43

城市智能体:宜昌点军区算力供应链平台的区域产业升级路径

宜昌点军区通过利用OpenCSG(开放传神)打造的点军算力供应链平台,整合异构算力并构建行业专属应用生态,实现算力利用率提升80%以上、企业算力使用成本降低40%;预计吸引100AI企业落地,推动数字经济产值增长近…

作者头像 李华