rust - 如何在 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'
不会改变这一点。
但是如果我买不起这个怎么办,我怎么能让它占用更少的内存呢?
当然诉诸这样的解决方案会奏效,但我会失去使用%
操作员的能力。
解决方案
不确定 Rust 链接器有多聪明,但在许多嵌入式链接器实现中,您可以在自己的实现中交换__udivmodi4
使用更小(但更慢)的方法,而不是编译器提供的版本。
一般来说,通用除法和取模在嵌入式平台上是昂贵的,但常数除法通常可以通过智能编译器的“固定”实现来专门化(通常有公约数的特殊情况 - 3、5、7、10 等) .
如果您可以控制应用程序,那么将代码更改为除法或模数2^N
显然是可取的(它折叠为除法的“右移”指令或模数的“与”指令)。例如,在这种情况下,2048 可能会接近 2000,并将 1 KB 的代码转换为 4 字节的代码。
FWIW 的 Rust 版本似乎有点胖 -例如GCC 实现要小得多。
推荐阅读
- python - 从字典中删除空元素
- android - React Native Android 中的 AAB Bundle Size 太大
- kubernetes - Pod 是否使用 k8s API 服务器来获取规范声明?
- javascript - 如何从弹出窗口中获取复选框值以使其更改页面的 CSS?
- c++ - 多态向量 C++ – 没有匹配的成员函数来调用“比较”
- sql - 将层次结构放在其自己的单独维度中还是将其设置为相关维度的一部分?
- algorithm - Mandelbrot 集的内部距离估计算法
- performance - SpyderKernelApp WARNING No such comm in windows 10 on spyder3 ide
- sql - 没有参数时从表中获取所有数据的 SQL 查询
- javascript - 删除文件名的扩展名并使用正则表达式 vscode 片段将 camelCase 转换为蛇形大小写?