有没有办法加快对以下表达式的评估?

时间:2013-03-05 17:27:07

标签: c++ math optimization math.h

我已经分析了我的程序,它花费了20%的CPU时间,基本上评估了以下表达式:

abs(x) > abs(y)

其中x,y是双精度浮点变量。

有没有办法将表达式重构为更快的变体?

以下行(在两个不同的地方调用)在每行占用接近10%的CPU时间:

(这是函数Image_3 :: TestGradientAtPoint的片段)

       if (abs(maxx[ch]) < abs(a)) maxx[ch] = a; 
01187AC9  mov         eax,dword ptr [ch]  
01187ACC  sub         esp,8  
01187ACF  fld         qword ptr [ebp+eax*8-68h]  
01187AD3  fstp        qword ptr [esp]  
01187AD6  call        abs (11305F9h)  
01187ADB  fld         qword ptr [ebp-70h]  
01187ADE  fstp        qword ptr [esp]  
01187AE1  fstp        qword ptr [ebp-0F8h]  
01187AE7  call        abs (11305F9h)  
01187AEC  add         esp,8  
01187AEF  fcomp       qword ptr [ebp-0F8h]  
01187AF5  fnstsw      ax  
01187AF7  test        ah,41h  
01187AFA  jne         Image_3::TestGradientAtPoint+176h (1187B06h)
01187AFC  mov         eax,dword ptr [ch]  
01187AFF  fld         qword ptr [ebp-70h]  
01187B02  fstp        qword ptr [ebp+eax*8-68h]  

剖析器声明对abs()的调用占用了20%的CPU时间。 我按照10 ^ 8次迭代的顺序调用方法 - 我正在使用大图像。

修改

我忘了说,但代码是在调试模式下运行的,我需要在这里稍微优化一下,因为我希望仍能在合理的时间内使用MSVC调试器。

5 个答案:

答案 0 :(得分:6)

这可能不会更快但是如果更快地评估算术表达式:

if ((x - y) * (-x - y) < 0)
    // then abs(x) > abs(y)

我相信这会将表达式的数量固定为3(2算术表达式和比较为零)而不是来自abs方法的3表达式(每个abs检查是否为负,反转符号否则只返回值然后比较每个abs)

编辑:

正如安德烈所说,你总是可以明确地对浮子进行平方。回想起来更有意义。

if (x * x > y * y)
    // then abs(x) > abs(y)

因为(x-y)( - x-y)= y ^ 2-x ^ 2

答案 1 :(得分:5)

告诉编译器进行优化。在GCC或clang中,您使用-O2-O3标志执行此操作 - 后者更具攻击性。在MSVC中,您可以使用/O2/Ox标志(IIRC;我很少使用该编译器)。如果没有打开优化,您不能指望100000000次迭代能够快速运行。

如果要在未启用优化的情况下进行调试,但仍在合理的时间范围内,请尝试使用较小的数据集;或者作为Mysticial提到的,启用优化调试并在调试器中接受随机更改的值和其他神秘的观察结果。

答案 2 :(得分:4)

如果maxx[]的顺序不重要,你可以对它进行排序,我认为它会更快。

其他的事情是,如果“a”与所有maxx[]相同,则可以a= abs(a);,然后只是直接比较。

我需要查看更多代码才能帮助您。

答案 3 :(得分:2)

这可能不会更快,但另一个逻辑版本是:

// logical replacement for abs(x) > abs(y)
x >= 0 ? 
    y >= 0 && x > y :
    y <= 0 && x < y ;

由于它只使用比较器和分支,可能更快,但没有保证......

如果没有,请尝试使用fabs,因为它是专为浮点数设计的。

答案 4 :(得分:2)

要检查的第一件事是您实际上是在启用优化。如果没有,也许您的编译器没有内联调用,导致您注意到它的足够开销。

如果我怀疑你实际上已经启用了优化,那么你将不得不采用一种算法方法。我无法想到你能做的任何事情abs让它更快。

所以你需要考虑以下事项:

  • 您是否关心原始的否定数字,或者您可以将数据预先过滤到abs if it it吗?
  • 你关心订单吗?您可以对数据进行排序以改进算法吗
  • 您是在循环中多次计算非变化值的abs吗?