Rust 如何在ARM中实现内存少的模运算

Rust 如何在ARM中实现内存少的模运算,rust,arm,embedded,modulo,cortex-m,Rust,Arm,Embedded,Modulo,Cortex M,我在STM32F446 MCU的Rust中嵌入了一个项目。考虑下一行: led::set_g(self.next_update_time%2000==0) 模用于在线阅读,似乎Cortex M4没有模指令。相反,一个函数被添加到二进制文件中,在软件中执行此操作。使用cargo bloat(基于Google的Bloaty),可以找到它 File .text Size Crate Name ... 0.1% 6.9% 990B compil

我在STM32F446 MCU的Rust中嵌入了一个项目。考虑下一行:

led::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
...
令我大吃一惊的是,它只需要不到1千字节的内存。我想那太多了。它背后的代码也相当长,请参见链接。我假设这个实现是为了快速实现的。幸运的是我有多余的记忆

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

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


当然,采用类似的解决方案是可行的,但这样我就失去了使用
%
操作符的能力。

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

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

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


FWIW这个生锈的版本看起来确实有点胖-例如更小。

正如另一个答案所说:如果你能将模数四舍五入到2的幂(例如2048),测试就变成了一个简单的位测试,即使在嵌入式系统上也应该是一条指令。例如,如果
next\u update\u time%2048==0
为真,则
next\u update\u time
中较低的15位都为零。这在大小上是昂贵的,因为您在32位机器上使用的是64位数据类型,并且必须将其分成两半。32位mod运算符要小得多。