在C ++中找到最多两个浮点数的最快方法是什么?

时间:2009-05-19 13:40:59

标签: c++

找到最多两个浮点数的最快方法是什么:

A)

y = std::max(x1, x2);

b)中

if (x1 > x2)
    y = x1;
else
    y = x2;

c)中

y = x1 > x2 ? x1 : x2;

由于

13 个答案:

答案 0 :(得分:24)

这是一个不同的问题

  

为什么您认为如此小的优化在您的计划的更大背景下会很重要?

我发现高度不太可能像这样的微优化会对您的程序产生可感知的影响。除非探查器明确证明这是一个问题,否则你不应该像这样进行微优化。

编辑在评论中添加一些澄清

这个问题没有很好的答案的原因是该代码的性能高度依赖于......

  1. 在程序中使用它的方式
  2. 您正在使用的特定编译器
  3. 传递给编译器的优化标志
  4. 您在
  5. 上运行代码的特定体系结构
  6. 许多其他非常微小的事情未包含在问题中
  7. 即使包含了所有这些信息,我们的答案也是最好的猜测。回答这个问题的唯一方法是扯出一个分析器并找出哪个更快。

    然而,这几乎肯定不值得努力。微优化您的程序中的这么小部分几乎肯定不会为您的代码添加任何显着的性能优势。一般来说,优化这样的代码是一个非常糟糕的主意,除非探查器明确告诉你这是一个问题。否则你会花很多时间来优化一些东西而不会产生任何好处。

    是的,有些情况下这种优化可能很重要。但这只是在非常特殊的情况下,其中代码是一个非常严格的高度调用循环的一部分。但是,识别此类代码的唯一方法是使用分析器。

答案 1 :(得分:5)

您可以在自己的系统上自行查看。

我是在gcc上为你做的 - redhat。我的系统上的结果,执行100,000次,x1 = 432943.5,x2 = 434232.9

a)~1200 uSec b)~600 uSec c)~600 uSec

编辑: 通过 -O2 优化,我在所有3种情况下获得了相同的结果:~110 uSec。

当然,实际结果取决于您特定问题和系统中的许多因素。

答案 2 :(得分:4)

这是编译器特定的,但我怀疑结果是一样的。看一下编译器的汇编输出。

答案 3 :(得分:4)

-O3双核Macbook pro 2.4ghz

  

std :: max(x1,x2)时间:4.19488 RMAAx   :4.19613如果时间:4.18775?时间:   4.18831

     

std :: max(x1,x2)时间:4.1836 RMAAx   :4.18274如果时间:4.18603?时间:   4.18857

     

std :: max(x1,x2)时间:4.18714 RMAAx   :4.18759如果时间:4.19752?时间:   4.19797

     

std :: max(x1,x2)时间:4.1926 RMAAx's   :4.19293如果时间:4.19334?时间:   4.19626

     

std :: max(x1,x2)时间:4.18963 RMAAx's   :4.19628如果时间:4.19253?时间:   4.19107

#include <iostream>

using namespace std;

int main (int argc, char * const argv[]) {

    uint64_t iterations = 10000000000;
    float x1 = 3455.232;
    float x2 = 7456.856;
    float y = 0;

    for (int count = 0; count < 5; ++count)
    {       
        clock_t begin_time = clock();
        for (uint64_t ii = 0; ii < iterations; ++ii)
        {
            y = std::max(x1, x2);
        }

        std::cout << "std::max(x1, x2) Time: " << float( clock () - begin_time ) /  CLOCKS_PER_SEC << endl;


        begin_time = clock();
        for (uint64_t ii = 0; ii < iterations; ++ii)
        {
            y = x1;
            if (y < x2)
                y = x2;
        }

        std::cout << "RMAAx's : " << float( clock () - begin_time ) /  CLOCKS_PER_SEC << endl;


        begin_time = clock();
        for (uint64_t ii = 0; ii < iterations; ++ii)
        {
            if (x1 > x2)
                y = x1;
            else
                y = x2;
        }

        std::cout << "if Time: " << float( clock () - begin_time ) /  CLOCKS_PER_SEC << endl;


        begin_time = clock();
        for (uint64_t ii = 0; ii < iterations; ++ii)
        {
            y = x1 > x2 ? x1 : x2;
        }

        std::cout << "? Time: " << float( clock () - begin_time ) /  CLOCKS_PER_SEC << endl;
    }

    return 0;
}

答案 4 :(得分:3)

Intel x86具有instructions(FCOMI / FCOMIP / FUCOMI / FUCOMIP),可快速比较浮点值。你的CPU也可能有这样的指示。诀窍是找出要编写的C ++,以便最大限度地提高编译器使用这些指令的机会,而不是做一些更慢但更通用的事情。

乐观的建议是使用std :: max(float,float)希望别人忽略那些嘲讽“微基准”和“过早优化”的人,并做了必要的研究来为std ::提供专业化max(float,float)将使用您硬件的专用指令。

答案 5 :(得分:2)

B和C至少在理论上会编译相同的。我选择那些因为除非std::max 不是函数调用(例如宏),否则那些将是最快的。

编辑显然,std::max是一个模板函数调用,就像表格C一样。 http://www.cplusplus.com/reference/algorithm/max/

答案 6 :(得分:2)

与“平时”相同,当谈到“最快”时。您是否测量了最大计算的执行时间,并报告了该过程的其余执行时间?此“优化”决策是否会对您的应用程序的执行时间产生重大影响?

我99%确定您的提案之间的差异不值得考虑。

答案 7 :(得分:2)

真正了解的唯一方法是衡量它们。它们可能因编译器和编译器或平台而异。

运行每个循环,进行100,000或500,000次迭代,并比较总执行时间。

答案 8 :(得分:2)

对他们进行基准测试并找出答案。

答案 9 :(得分:2)

首先,正如其他人所说的那样,对代码进行分析并确保这是值得优化的。如果是,请继续阅读:你可以不分支。有关详细信息,请参阅Down with fcmp: Conditional Moves For Branchless Math

答案 10 :(得分:1)

这种方式可能更好吗?

y = x1;
if (y < x2)
    y = x2;

编译器可以更好地解释删除else条件。

Edit1:如果基准测试不要忘记用x1大于x2,另一半用x2做大一半的测试。 否则结果不会反映真实案例。

Edit2:如果您在具有1或2k内存的嵌入式系统中工作,Microoptimazions在某种程度上是有用的。而且,这是一个有趣的问题,可以考虑为什么每种情况下的时间都不同。

答案 11 :(得分:0)

#define b c 作为宏很常见,并在整个代码中使用它。请注意,这仅适用于大多数情况,如果传入由非幂等运算符或具有副作用的函数调用修改的 x y 参数,则会死亡。例如:

#define MAX(x,y) (((x) < (y)) ? (y) : (x))
...
MAX(i++, ++j); //won't work properly, the ++'s will get executed twice.
MAX(changeKSomehow(k), changeLSomehow(L)); //won't work, the functions will get called twice.

事实证明,std :: max,至少对于GNU libstdc ++来说,几乎完全相同,并使用inline提示。编译器应该能够在适当的时候采用提示(当&lt;操作符需要足够的指令时,如果内联则不会导致大量的I $压力)。

答案 12 :(得分:0)

在存在一个不错的优化器的情况下,它们是等效的。