MulDiv可能比存储已知值和在其他代码中进行数学运算效率低

时间:2011-01-26 14:02:46

标签: windows delphi optimization math delphi-2007

我正在使用Delphi 2007并开发一些演示软件。我正在处理的当前模块是视频的过渡过滤器。我正在使用的转换代码(TPicShow的PSEffects单元)需要X和Y值,这些值基于框架的尺寸和转换的进度。这是代码

Type
TPercent = 0..100;
var
ATo  : TBitmap; //
Prog : Integer; //Progress of the transition

      if ATo.Width >= ATo.Height then
    begin
      X := MulDiv(ATo.Width, Prog, High(TPercent));
      Y := MulDiv(X, ATo.Height, ATo.Width);
    end
  else
    begin
      Y := MulDiv(ATo.Height, Prog, High(TPercent));
      X := MulDiv(Y, ATo.Width, ATo.Height);
    end;

我正在尝试对此进行优化,并发现我可以保存不变的计算(直到ATo的尺寸发生变化)并且每帧删除2次除法计算。

所以它会像

{All of these are calculated when the dimensions of ATo Change}
WDP : real; // width divided by High(TPercent)
HDW : real; // Height divided by width
HDP : real; // Height divided by High(TPercent)
WDH : real; // Width divided by Height

  if ATo.Width >= ATo.Height then
    begin
      X := Trunc(WDP * Prog);
      Y := Trunc(HDW * X);
    end
  else
    begin
      Y := Trunc(HDP * Prog);
      X := Trunc(WDH * Y);
    end;

听起来不错,但没有MulDiv的实际代码我无法确定。如果它只是(非常简化)

MulDiv(a,b,c : Integer)
begin
  Round((A*B)/C);
end

然后我知道我的改变会更有效率,但是如果MulDiv在优化功能方面做了很多非常酷的事情(我可能做的事情),那么我不确定我的改变是否会给我带来任何好处。

我的改变会更有效率吗?

编辑:我还没有实现这个,我只是在接受这个概念。

3 个答案:

答案 0 :(得分:3)

您无法找到MulDiv的实际代码,因为它是WinAPI函数。但我怀疑,因为它在WinAPI本身中大量使用,它可能是一些非常优化的汇编程序代码,而不仅仅是几个函数调用。

至于您的更改是否更有效,确定这一点的唯一方法是以两种方式分析代码并查看哪些更快。在这里搜索“Delphi profiler”以获取一些建议(如果您使用的是Delphi XE,则可以使用附带的AQTime)。

顺便说一句,当你谈论优化之类的东西时,通常非常有用的是指出你实际使用的是哪个Delphi版本,因为编译器中的变化会对答案产生影响。

答案 1 :(得分:2)

如果使用整数运算实现对MulDiv的调用效率低下并且是性能问题的根源,我会感到非常惊讶。你有时间计划吗?您是否使用了分析器来识别应用中的热点?

我个人认为从整数到双精度浮点运算的转换不太可能产生性能提升。

在任何情况下,我的猜测是你有其他代码,你在你显示的代码之后调用它,它使用XY并且消耗比这个小几个数量级的CPU片段。你可能不会计算XY,然后丢弃它们:你用它们做什么?

编辑:MulDiv的Wine实现可能非常接近Windows,并且其中的内容是如此:

if ( ( (nMultiplicand <  0) && (nMultiplier <  0) ) ||
     ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
  ret = (((LONGLONG)nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
else
  ret = (((LONGLONG)nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;

答案 2 :(得分:1)

正如其他人所说,你应该寻找一个分析器来识别热点。

一旦确定了它们,找到比当前代码更快的内容,在您的情况下,在多媒体应用程序中,可能需要您了解SIMD机器语言指令,并且可能需要您编写替换的手动优化的声明代码,获得更快的结果。

使用浮点类型在Pascal中自己编写内容非常不会导致任何性能提升。缓存中间结果可能会导致内存使用量呈指数级增长,速度只有适度提升,这可能会让您在可能发生vm分页(抖动)的系统上减慢速度。