优化浮点除法和转换操​​作

时间:2009-09-02 08:26:43

标签: c++ c algorithm floating-point

我有以下公式

float mean = (r+b+g)/3/255.0f;

我想加快速度。有以下先决条件

0<= mean <= 1  and 0 <= r,g,b <= 255 and r, g, b are unsigned chars

所以如果我尝试使用&gt;&gt;的事实8就像是除以256,我使用类似

的东西
float mean = (float)(((r+b+g)/3) >> 8);

这将始终返回0.有没有办法跳过昂贵的浮动分区,最终仍然是0到1之间的平均值?

5 个答案:

答案 0 :(得分:16)

将您的分区预转换为可乘法常数:

a / 3 / 255

相同
a * (1 / (3 * 255))

所以预先计算:

const float AVERAGE_SCALE_FACTOR = 1.f / (3.f * 255.f)

然后就这样做

float mean = (r + g + b) * AVERAGE_SCALE_FACTOR;

因为乘法通常比分割快得多。

答案 1 :(得分:8)

你显然将平均值与其他值进行比较,也就是0到1之间。 那你怎么把这个东西乘以255呢?

答案 2 :(得分:5)

让我们看看真正的编译器实际上用这个代码做了什么?我喜欢mingw gcc 4.3(x86)。我用过“gcc test.c -O2 -S -c -Wall”

此功能:

float calc_mean(unsigned char r, unsigned char g, unsigned char b)
{
    return (r+b+g)/3/255.0f;
}

生成此对象代码(为清楚起见,删除了函数入口和退出代码。我希望我添加的注释大致正确):

 movzbl 12(%ebp), %edx    ; edx = g
 movzbl 8(%ebp), %eax     ; eax = r
 addl %eax, %edx        ; edx = eax + edx
 movzbl 16(%ebp), %eax    ; eax = b
 addl %eax, %edx        ; edx = eax + edx
 movl $1431655766, %eax ; 
 imull %edx              ; edx *= a const
 flds LC0               ; put a const in the floating point reg
 pushl %edx              ; put edx on the stack
 fidivrl (%esp)            ; float reg /= top of stack

这个功能:

float calc_mean2(unsigned char r, unsigned char g, unsigned char b)
{
    const float AVERAGE_SCALE_FACTOR = 1.f / (3.f * 255.f);
    return (r+b+g) * AVERAGE_SCALE_FACTOR;
}

生成这个:

 movzbl 12(%ebp), %eax    
 movzbl 8(%ebp), %edx
 addl %edx, %eax
 movzbl 16(%ebp), %edx
 addl %edx, %eax
 flds LC2
 pushl %eax
 fimull (%esp)

如您所见,第二个功能更好。使用-freciprocal-math进行编译会将fidivrl从第一个函数转换为fimull,这应该是一个改进。但第二个功能仍然更好。

但是,如果您认为现代桌面CPU具有18级流水线并且每个周期能够执行多个这些指令,您可以看到这些功能的性能将受到由于数据依赖。希望你的程序有这个代码片段内联并且有一些循环展开。

考虑隔离这么小的代码片段并不理想。这有点像用双筒望远镜粘在眼窝上驾驶汽车。缩小男人!

答案 3 :(得分:1)

如安德鲁所示,原始功能根本没有优化。编译器不能,因为您首先将总和除以整数,然后除以浮点数。这与乘以上述平均比例因子不同。如果你将(r + g + b)/3/255.0f改为(r + g + b)/3.0f/255.0f,编译器可能会优化它以自动使用fimull。

答案 4 :(得分:1)

为平台优化此类操作非常常见,而不是作为算法或可移植的C. Virtual Dub blog非常值得阅读有关如何在针对x86和x64架构的软件中完成的提示,并且有一些关于优化像素平均值的条目1 2