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