【问题标题】:Can you replace floating points divisions by integer operations?你能用整数运算代替浮点除法吗?
【发布时间】:2014-08-27 09:23:21
【问题描述】:

我使用的 Cortex MCU 不支持硬件中的浮点除法。 GCC 编译器通过基于软件来解决这个问题,但警告说它可能非常慢。

现在我想知道如何完全避免它们。例如,我可以将值因子 10000(整数乘法)放大,然后除以另一个大因子(整数除法),得到完全相同的结果。

但是这两个运算实际上会比单个浮点运算更快吗?例如,替换是否有意义:

int result = 100 * 0.95f

通过

int result = (100 * 9500) / 10000

要达到 95% 吗?

【问题讨论】:

  • 试试看。是时候做一个虚拟应用和一些基准测试了。
  • 通过测量可以轻松回答。 -1 表示零努力。
  • 正确答案是在目标硬件 imo 上进行基准测试。
  • @Joe 简单地衡量更快的东西对我没有任何帮助。我想了解为什么它更快/更慢,并更好地了解处理器如何在内部处理这个问题。
  • @Muis 那么您的答案就在于您正在使用的特定 CPU 的数据表和您的编译器发出的汇编程序。它将特定于您的 GCC 版本和您的特定 cpu,以及您的编译器标志。欢迎使用嵌入式开发...

标签: c performance gcc embedded cortex-m


【解决方案1】:

如果可以的话,最好完全摆脱分裂。如果除数是编译时常数,这相对容易。通常,您会安排一些事情,以便任何除法运算都可以用按位移位代替。所以对于你的例子:

 unsigned int x = 100;
 unsigned int y = (x * (unsigned int)(0.95 * 1024)) >> 10; // y = x * 0.95

显然你需要非常清楚x的范围,这样你才能避免中间结果溢出。

和往常一样,请记住,过早的优化是邪恶的 - 如果您发现了性能瓶颈,请仅使用诸如此类的定点优化。

【讨论】:

  • Ick,混合操作,(x * (unsigned int)(0.95 * 1024)) / 1024 更清晰,结果相同。
  • @ams:我使用>> 10 而不是/ 1024 来明确表示没有发生实际的除法,但你是对的,对于未签名的情况,任何体面的编译器都应该将后者转换为前者。
【解决方案2】:

是的,整数表达式会更快 - 整数除法和乘法指令是单机指令,而浮点运算将是函数调用(用于直接软件浮点)或异常处理程序(用于 FPU 指令仿真)——无论哪种方式,每个操作将包含多条指令。

然而,虽然对于简单的运算,整数表达式和临时定点(缩放整数)表达式可能就足够了,但对于涉及三角函数和对数等的数学密集型应用程序可能会变得复杂。为此,您可以使用通用的定点表示和库。这在 C++ 而不是 C 中是最简单的,例如 Anthony Williams' fixed point library,由于大量的运算符和函数重载,在大多数情况下,您可以简单地将 floatdouble 关键字替换为 fixed 和现有的表达式和算法对于许多操作,其性能与配备 FPU 的 ARM 相当。如果您不习惯使用 C++,则其余代码无需使用任何 C++ 特定功能,基本上可以将 C 代码编译为 C++。

【讨论】:

    猜你喜欢
    • 2013-06-12
    • 1970-01-01
    • 1970-01-01
    • 2017-11-22
    • 2023-03-10
    • 2016-07-23
    • 2021-08-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多