0

我已经分析了我的程序,它花费了 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 调试器。

4

5 回答 5

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)

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

于 2013-03-05T18:06:13.927 回答
5

告诉你的编译器进行优化。在 GCC 或 clang 中,您可以使用-O2or-O3标志来执行此操作——后者更具侵略性。在 MSVC 中,您可以使用/O2or/Ox标志(IIRC;我很少使用该编译器)。如果不启用优化,您不能指望 100000000 次迭代能够快速运行。

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

于 2013-03-05T17:56:49.977 回答
4

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

另一件事是,如果“a”对于maxx[]你所能做的一切都是一样的a= abs(a);,然后直接与 a 进行比较。

我需要查看更多代码以尝试为您提供更多帮助。

于 2013-03-05T17:42:36.890 回答
2

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

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

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

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

于 2013-03-05T17:50:32.403 回答
2

首先要检查的是您实际上是在启用优化。如果不是,那么您的编译器可能没有内联调用,从而导致您注意到它的足够开销。

如果我怀疑您实际上启用了优化,那么您将不得不采用算法方法。我想不出你能做些什么abs来让它更快。

因此,您需要考虑以下事项:

  • 您是否关心原始的负数,或者您可以预先过滤数据以确认abs它?
  • 你在乎订单吗?你能对数据进行排序以改进你的算法吗
  • 您是否abs在循环中多次计算不变值?
于 2013-03-05T17:52:14.973 回答