首页 > 解决方案 > 如何在 ARM 嵌入式 Rust 中使用更少的内存进行模运算

问题描述

我在 STM32F446 MCU 上有一个 Rust 嵌入式项目。考虑下一行:

leds::set_g(self.next_update_time % 2000 == 0)

使用模数并在线阅读,看来 Cortex M4 没有模数指令。相反,一个函数被添加到在软件中执行此操作的二进制文件中。使用 cargo bloat(基于 Google 的 Bloaty),可以找到它。

File  .text    Size                 Crate Name
...
0.1%   6.9%    990B     compiler_builtins __udivmoddi4
...

令我惊讶的是,它只需要不到一千字节的内存。我认为这很多。它背后的代码也很长,请参阅链接。我认为这个实现很快。幸好我有空余的内存。

使用opt-level = 'z'不会改变这一点。

但是如果我买不起这个怎么办,我怎么能让它占用更少的内存呢?

当然诉诸这样的解决方案奏效,但我会失去使用%操作员的能力。

标签: rustarmembeddedmodulocortex-m

解决方案


不确定 Rust 链接器有多聪明,但在许多嵌入式链接器实现中,您可以在自己的实现中交换__udivmodi4使用更小(但更慢)的方法,而不是编译器提供的版本。

一般来说,通用除法和取模在嵌入式平台上是昂贵的,但常数除法通常可以通过智能编译器的“固定”实现来专门化(通常有公约数的特殊情况 - 3、5、7、10 等) .

如果您可以控制应用程序,那么将代码更改为除法或模数2^N显然是可取的(它折叠为除法的“右移”指令或模数的“与”指令)。例如,在这种情况下,2048 可能会接近 2000,并将 1 KB 的代码转换为 4 字节的代码。

FWIW 的 Rust 版本似乎有点胖 -例如GCC 实现要小得多。


推荐阅读