【问题标题】:How to decide when to use fixed point arithmetic over float?如何决定何时在浮点数上使用定点算法?
【发布时间】:2021-04-23 07:05:57
【问题描述】:

如何决定何时使用定点算法而不是浮点数?

我已经读过,当处理器中没有浮点单元时使用定点。当没有 FPU 时,是否意味着不支持 'float' 数据类型?

【问题讨论】:

  • 我在 EE 网站 here 上写了一个关于这个主题的答案。 TL;DR 是:“如果您的 MCU 有 FPU,并且您确实需要进行高级数学运算,那么您应该使用浮点数。否则您不应该。”

标签: embedded fixed-point integer-arithmetic


【解决方案1】:
  • 如果没有 FPU 定点会更快、更确定
  • 如果您没有 FPU,固定点在许多情况下会更小 - 当然对于简单的算术。
  • 如果您需要您的代码跨不同平台或工具链(无论是否使用 FPU)生成位相同的结果,则需要定点。
  • 如果您需要进行复杂的数学运算,例如需要三角函数或对数函数,浮点是阻力最小的路径,但绝不是唯一的选择 - 但您需要开发或查找库(参见下面的链接) -并且有很多方法可以做到这一点。
  • 如果你需要宽动态范围浮点更简单。例如,小于 1 的数字的平方根是一个较小的数字 - 使用定点时,您可能会用完位并以零结束,使用浮点时,只需移动点以增加分辨率,但会牺牲范围。
  • 如果您有 FPU 并且正在使用 RTOS,并且不希望在上下文切换上堆叠 FPU 寄存器的开销(或者如果不支持),则定点可以避免这种需要,并且在您忘记时避免错误为每个需要它的任务启用该选项。

Generally if your operation is trivial, use fixed point or at least an integer representation by selecting your units appropriately.例如,将电压值存储为整数毫伏(甚至 ADC 量子)而不是伏特可以避免不必要的浮点。

如果您正在做复杂的数学运算并且有 FPU,那么浮点是更简单、最不容易出错的解决方案。即使没有 FPU,如果您的解决方案满足时序和代码大小约束,浮点可能仍然更简单,但可能会限制您在更多约束执行环境中使用相同代码的能力。因此,需要在广泛的平台上重用,定点可能更可取。

无论您做什么,在大多数情况下都应避免“十进制定点”,尽可能使用二进制定点表示(Q 表示),例如 10Q6 有 10 个整数位和 6 个小数位。这样做的原因是,在乘法/除法之后的重新缩放是移位操作,而不是潜在的昂贵的乘法/除法操作,并且您在重新缩放时不会丢失任何精度。

一些有用的参考资料:

【讨论】:

    【解决方案2】:

    如果没有可用的 FPU,编译器通常可以模拟浮点运算。但这效率低下,因为它需要很多周期。

    如果您受到资源限制(您经常处于没有 FPU 的环境中),那么您可以选择使用常规整数运算的定点算法。

    只是漫无目的:当我使用 FP 时,我错过了编译器 (C/C++) 对能够将变量标记为定点(具有特定数量的小数位)的支持。

    【讨论】:

    • C++ 提供了定义您自己的数字类型并指定小数位数的工具。 CNL 是一个提供此类类型的库。指数(减去小数位数)表示为模板参数。
    【解决方案3】:

    如果您有一个符合标准的编译器,那么floatdouble 始终可用并且可以正常工作。如果没有 FPU,则计算在软件中完成(称为软 FPU 或 FPU 仿真)。这会更慢并且使用更多内存。

    何时使用定点主要是见仁见智,但何时使用它是当变量具有很大的动态范围时,即:当一个数字可能很大但你仍然如果它非常小,需要它是准确的。

    例如:显示汽车的速度。我需要知道 68 和 70 mph 之间的差异,但我不关心 0.68 mph 和 0.70 mph 之间的差异。这具有低动态范围(我关心),因此如果其他原因表明我可能想要的话,我可以使用定点。或者,测量样品的放射性:我关心每秒计数 100 到 90 之间的差异,但我仍然关心每秒计数 1 到 0.9 之间的差异。这种高动态范围意味着固定点不适合。

    【讨论】:

    • “始终可用并正常工作”/“主要是见仁见智” 这不是真的。例如,如果我使用没有 FPU 的非常低端的 MCU 进行编程——比如说一个垃圾 Arduino——那么使用浮点会破坏 RAM 的使用、执行时间和闪存大小。以至于我很容易遇到堆栈溢出、破坏实时性能等问题。如果我无缘无故地使用浮点数,那么我就不必要地破坏了整个程序的性能。
    • @Lundin,您是否错过了前几句话:如果您有一个符合标准的编译器...
    • 没有。如果您有标准编译器但没有 FPU,那么您将获得导致所有上述问题的软件浮点库。
    • 你认为在使用浮点数之前你有无限的内存吗?并以无限的速度奔跑?无论此问题的特定主题如何,这些考虑因素始终是每个项目的一部分,但我编辑了答案以提醒您在此处也考虑它们。
    • 是的,大多数 Arduino 用户和其他各种涉足低端微控制器的庸医似乎都这么认为:浮点是靠魔法工作的,它们拥有无限的系统资源。
    【解决方案4】:

    如何决定何时使用定点算法而不是浮点数?

    这取决于许多可能会或可能不会影响您的因素,包括...

    优点:

    • 定点需要更少的电路,因此在更小、更简单的设备上可能更实用。
    • 定点使用较少的能量,因此可能更实用
      • 在电池供电的设备上,
      • 在密集计算会产生大量能源费用的应用中,或
      • 哪里有散热问题。
    • 定点实际上只是整数运算,因此运算是无损的。
    • 定点允许您在您选择的数字基数中precisely express real numbers,例如值 1/10 或 1/3。
    • 浮点运算可能会表现出与以下内容相关的不一致行为
      • 全局舍入模式,
      • 优化,
      • 关联性,
      • 实现定义的行为,以及
      • FPU 硬件的变化。

    缺点:

    • 虽然是无损的,但定点运算容易出现超出范围的错误,例如溢出。 (库和 UB 消毒剂可以帮助避免/检测错误。)
    • 在模运算符 (%) 的帮助下实现无损除法,这通常更难使用。
    • 大多数语言都不太支持定点算术:您必须使用整数手动执行容易出错的计算,或者找到一个库来帮助您。
    • 浮点格式在架构之间往往更加一致,这与宽度和字节序不同的整数不同。
    • 浮点类型不仅具有动态小数点,而且该小数点的最佳位置会自动保持,从而避免头痛和精度损失。

    确实,浮点数是一种易于使用且得到广泛支持的用于表示实数的解决方案。如果浮点适合您,请在探索替代方案之前仔细考虑。

    例外:专业人士将定点作为自然选择的应用是货币。面额的无损表示在金融领域尤为重要。 (example)

    我已经读过,当处理器中没有浮点单元时使用定点。

    确实如此。没有 FPU,浮点运算非常慢!

    当没有 FPU 时,是否意味着不支持 'float' 数据类型?

    不,不一定要遵循,尽管实现可能会有所不同。 (IIRC,旧版本的 GCC 有一个启用浮点支持的标志。)使用

    执行浮点运算是完全可能的
    • 编译器,通过生成等效的 ALU 指令,或
    • 系统,通过在遇到 FPU 指令时中断进程并推迟到软件例程。

    这两者都慢得多,因此在此类硬件上使用定点算术可能成为一种实际的选择。最好将定点视为一种优化技术,在发现性能缺陷后使用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-23
      相关资源
      最近更新 更多