首先,以防不明显:更长的执行时间意味着更多的功耗。尽管如果您最感兴趣的是降低功耗,请先查看系统时钟。
为什么模运算会消耗更多功率?
它不在现代编译器上。对于大多数内核来说,除法和取模是繁重的 CPU 操作,但生成实际div
etc 指令的 C 代码大部分发生在大约 15 到 20 年前。当您启用优化时,现代编译器会选择最好的代码,并在可以避免的情况下避免除法。此外,在 8 和 16 苦味等低端 MCU 的性能方面,除法也是一个更大的问题。
但是,应该提到的是,在嵌入式系统中,在禁用所有优化的情况下运行是一种常见的做法。主要是因为在 90 年代和 2000 年代初期,各种质量平庸的嵌入式编译器的编译器优化器正确地建立了一个令人讨厌的错误声誉。
如果您在禁用优化的情况下运行,那么您当然只能靠自己,并且必须手动执行所有优化 - 除非您对 C 和目标 CPU 都有深入的了解,否则绝对不建议这样做。
让我们在 gcc-arm-none-eabi 中反汇编您的特定代码示例,使用-O3
. 我做了这些独立的例子:
void func1 (void)
{
static unsigned int my_index;
while(1)
{
my_index++;
if (my_index >= 8) my_index = 0;
volatile unsigned int out = my_index;
}
}
void func2 (void)
{
static unsigned int my_index;
while(1)
{
my_index = (my_index + 1) % 8;
volatile unsigned int out = my_index;
}
}
需要 volatile 作为副作用来阻止优化器完全删除代码。现在,使用 Godbolt https://godbolt.org/z/bM5M5v38h反汇编它,我们得到几乎相同的机器代码。看不到分裂。cmp
由于指令(分支),添加的版本实际上表现得稍微差一点。
我认为删除条件语句可以表现得更好
通常是的,在你的情况下它确实是这样,尽管它是一个微优化。Cortex M 通常没有高级分支预测,也没有高速缓存。在 M0 上,甚至不值得考虑头痛。我相信一些 STM32x4 对简单形式的分支预测有一些硬件支持。高端 M7 等将具有缓存,然后避免分支更重要。
一般来说:
您应该努力编写尽可能可读的代码。然后在代码中存在实际性能瓶颈时进行优化。手动优化是高素质的工作,需要大量经验。
在这种特殊情况下,我会说加法/计数器版本更具可读性,因此无论多少 CPU 滴答声,我都会使用它。
至于你链接的博客,作者不是一个完整的菜鸟,提出了一些好的观点,但提到了一些奇怪甚至误导的东西。让我评论一下您从以下获得模数评论的项目符号列表:
-
尽可能使用“静态常量”类来防止运行时复制消耗功率的数组、结构等。
我不知道“静态常量”类应该是什么意思。C 尤其区分大小写,并且没有 class 关键字。我假设作者不知道正确的 C 术语,实际上的意思是说:static
尽可能使用存储类说明符和 const 正确性。如果这就是他们的意思,那是一般的好建议。
-
使用指针。对于初学者来说,它们可能是 C 语言中最难理解的部分,但它们最适合有效地访问结构和联合。
这有点像告诉建筑工人使用混凝土......这是强制性的,而不是一种选择。指针是 C 语言的基本组成部分。
-
避免模数!
正如上面所证明的,这不是很好的建议。
-
在可能的情况下,局部变量优于全局变量。局部变量包含在 CPU 中,而全局变量存储在 RAM 中,CPU 访问局部变量的速度更快。
尽管文件范围变量(“全局变量”)也可能临时存储在寄存器中,但通常是正确的。避免真正的全局(外部链接)变量的主要原因是程序设计,而不是性能。
此外,在大多数 MCU 上,寄存器和 RAM 访问之间的差异并不大,此评论主要适用于 x86、Cortex A、Power PC 等高端 CPU。当手动优化 Cortex M 等中端 MCU 的内存访问时,您应该而是考虑闪存与 RAM,因为闪存通常具有等待状态。
然而,减少变量的范围对于可读性来说总是一件好事,可以最大限度地减少错误并减少命名空间的混乱。
-
在可能的情况下,无符号数据类型是您最好的朋友。
是的,但不是因为性能,而是因为在按位运算中使用时有符号/负操作数的隐式转换和定义不明确的行为。
-
尽可能为循环采用“倒计时”。
好吧,这比模一更糟糕的恐龙建议。这样做的基本原理是众所周知的,与零比较比与一个值比较更快。但是编译器已经能够进行这种优化很长时间了!不要写下计数循环,这只是一无所获的混淆。这是 1993 年左右的有效建议,而不是 2022 年。
-
使用位掩码代替无符号整数的位字段。
很好的建议,但也与性能无关,但与可移植性和定义不明确的行为有关。
总体而言,博客文章的质量是多种多样的:非常好的建议与普通的坏建议混合在一起。我会停止阅读那个博客。请注意,在这个答案中,我在评论它时必须多久回到 20-30 年前。