【问题标题】:On a Cortex M0 how expensive is a floating point compare vs an integer compare?在 Cortex M0 上,浮点比较与整数比较的成本是多少?
【发布时间】:2015-09-16 15:01:31
【问题描述】:

所以我正在开发一个需要计算浮点数的嵌入式项目。显然,有多种方法可以估计输出并减少计算周期。我的问题是,浮点比较与整数比较有多贵(相对而言,不是精确的周期)?其中一项操作可能可以通过这种方式进行优化,但我想知道是否值得付出努力。该芯片是皮质 M0(无浮点硬件)。所有浮点都是通过软件完成的。

【问题讨论】:

  • 应该有显着不同,几百个周期?当你尝试它时,你得到了什么?
  • 在许多此类项目中,您可以通过使用定点整数来避免float。使用浮点通常只是因为懒惰的程序员试图避免以浮点膨胀为代价编写一些额外的函数。你确定你需要浮点数吗?
  • 您为什么要专注于“比较”操作?在大多数情况下,其他浮点运算将占主导地位。
  • @dwelch :我怀疑比较操作的“数百”个周期;检查尾数和商的大小不需要那么多指令。然而,这是一个奇怪的问题——使用浮点的其他方面似乎更重要。当然,迭代中的比较可能会累积许多额外的循环,但这个问题暗示了一个操作。
  • 你最好问一个关于优化特定算法的问题,而不是“出汗”。

标签: floating-point embedded instruction-set cortex-m


【解决方案1】:

可靠地确定浮点比较成本的最简单方法是对其计时。如果由于某种原因无法做到这一点,可以估计一下。

我在 2003 年左右使用无 FPU 的 ARM 处理器,并为这些处理器编写了自己的高度优化的单精度浮点。虽然我无法再访问该代码,但我发现它的性能与已发布的性能数据 in this paper by Iordache and Tang for a floating-point emulation library on XScale 非常相似。

这表明单精度加法在 35 个周期内执行,减法时间基本相同。由于比较是减法的一种简化形式,其中不需要计算浮点结果,因此比较会稍微便宜一些,从而为比较的成本设置一个上限。

在浮点仿真中,单精度操作数由 32 位整数表示,并按原样存储在通用寄存器中。如果两个操作数都是有限正操作数,则可以直接通过整数比较进行比较。基本上,这对重新解释为int32binary32 操作数使用整数比较。这给出了成本的下限。 This answer 展示了如何将这种方法推广到非异常操作数对。

【讨论】:

  • 如果将数字存储为 32 位非必要标准化尾数加上 32 位符号和指数字,那么重复浮点加法的时间将如何比较?我一直认为应该有一个“扩展浮点数”来提供扩展双精度数所提供的优势,如果 ANSI 包含“双精度中间操作的结果”和“80 位扩展浮点数”的单独类型。跨度>
【解决方案2】:

尚未在 Cortex M0 上进行测试,但比较两个浮点数,在最坏的情况下,大致如下:

bool floatLess(float a, float b)
{
    uint32_t ai = reinterpret_cast<uint32_t const&>(a);
    uint32_t bi = reinterpret_cast<uint32_t const&>(b);

    if((ai^bi) & 0x80000000) // different signs
    {
        return ai>bi; // smaller one has sign bit set
    }
    else
    {
        return ai<bi; // lexicographic compare of exponent,mantissa
    }
}

处理诸如 NaN 和 -0 与 +0 之类的边缘情况会涉及更多内容,但 IEEE 754 数字的设计目的是在整数上下文中易于比较。不太可能存在显着的周期差异。

【讨论】:

  • 在这种情况下转换为 int 非常昂贵,尤其是因为它可能不适合,并且将符号、指数和尾数分开的专用比较可能会更快。但是张贴者没有解释他们如何在不讨论其余代码的情况下将 int 操作与浮点数进行比较,它总是浮点数并且他们想要浮点数与 int 进行比较,这意味着浮点数到 int 是昂贵的部分而不是整数比较。如果它们完全是关于性能的,那么不要在 cortex-m0 上使用浮点数,你可以有很多额外的数学并且仍然在性能上取胜。
  • @dwelch : reinterpret_cast 是免费的,但是它随后被分配给 uint32_t 导致隐式转换。我想知道这是否是一个错误并且reinterpret_cast&lt;uint32_t const&amp;&gt; 是故意的?但是,我认为代码旨在说明该过程,而不是实际实现 - 在这种情况下,我会将其视为伪代码。
  • 啊,我以为您正在从 int 转换为 float,我看到这解决了每个人都错误地使用联合的问题(即使它通常有效)。谢谢我现在明白了...
【解决方案3】:

比较操作 &gt;,&lt;,&gt;=&lt;=(避免 == 用于浮点)可能无关紧要 - 特别是对于单精度(尽管不如整数比较便宜) )。简单的测试就是构建一些测试代码,在调试器中查看编译器的汇编输出或者反汇编。

然而,使用软件浮点的真正影响在于算术运算,对于 trig、log 和 sqrt 函数更是如此。

在大多数应用程序中很少需要浮点,并且软件定点实现在许多应用程序中将更快且绰绰有余。我测量了 Anthony Williams 在this article 中提供的定点代码,其速度比 ARM9 上的单精度浮点快 5 倍,并且在 Cortex-M3 上使用它。在这个库中,比较运算符 整数运算(虽然是 64 位,所以不像 int32 那样便宜)。在特定的算法中,你甚至可能不需要 64 位定点。

【讨论】:

  • 在进行 int 比较之前,我们是否知道 OP 是否包括从 float 到 int 的转换,或者是否发生了其他一些魔法,因此唯一的周期差异是在固定 vs 浮动比较中没有任何其他具有软 fpu 与定点的代码。一般来说,不使用 float 付出额外的努力通常会得到很大的回报,但我们真的没有足够的信息来真正回答这个问题,甚至没有真正理解它。
  • @dwelch:我同意。我尽可能直接回答问题,但建议这是错误的问题。在这里等待答案所花费的时间最好花在编写和评估目标(或模拟器)上的实现或实验以获得真实答案而不是我们的最佳猜测。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-20
  • 2017-05-30
  • 1970-01-01
  • 1970-01-01
  • 2011-04-19
  • 1970-01-01
相关资源
最近更新 更多