Может ли MulDiv быть менее эффективным, чем хранить известные значения и выполнять математику в другом коде - PullRequest
1 голос
/ 26 января 2011

Я использую Delphi 2007 и работаю над некоторым программным обеспечением для презентаций.Текущий модуль, над которым я работаю, - это фильтр перехода для видео.Код перехода, который я использую (модуль PSEffects в TPicShow), требует 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 ]

3 голосов
/ 26 января 2011

Вы не можете найти фактический код MulDiv , потому что это функция WinAPI. Однако я подозреваю, что, поскольку он интенсивно используется в самом WinAPI, он, вероятно, представляет собой довольно хорошо оптимизированный ассемблерный код, а не просто пару вызовов функций.

Поскольку ваши изменения будут более эффективными, единственный способ определить это - профилировать код в обоих направлениях и посмотреть, что быстрее. Поищите здесь «Delphi profiler» для получения некоторых предложений (если вы используете Delphi XE, вы можете использовать прилагаемый AQTime).

Кстати, когда вы говорите о таких вещах, как оптимизация и так далее, часто очень полезно указывать, какую версию Delphi вы на самом деле используете, так как изменения в компиляторе могут иметь значение в ответах.

2 голосов
/ 26 января 2011

Я был бы очень удивлен, если бы вызовы MulDiv, которые реализованы с помощью целочисленных операций, были неэффективными и источником ваших проблем с производительностью. Вы рассчитали свою программу? Вы использовали профилировщик для определения горячих точек в вашем приложении?

Лично я думаю, что переход от целочисленных операций к операциям с плавающей запятой с двойной точностью вряд ли приведет к улучшению производительности.

В любом случае, я предполагаю, что у вас есть другой код, который вы вызываете после кода, который вы показали, который использует X и Y и который потребляет на ЦП на несколько порядков больше процессора, чем этот маленький фрагмент. Вы, вероятно, не рассчитываете X и Y, а затем отбрасываете их: что вы с ними делаете?

РЕДАКТИРОВАТЬ : Реализация 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;
1 голос
/ 26 января 2011

Как уже говорили другие люди, вам следует обратиться к профилировщику для определения горячих точек.

После того, как вы их определили, поиск чего-то более быстрого, чем ваш текущий код, в вашем случае, в мультимедийном приложении, может привести ктребует, чтобы вы изучили инструкции на машинном языке SIMD, и может потребовать, чтобы вы заменили оптимизированный вручную код ассемблера, чтобы получить более быстрые результаты.

Написание чего-либо самостоятельно в Pascal с использованием типов с плавающей запятой ОЧЕНЬ маловероятнопривести к любым улучшениям производительности.Кэширование промежуточных результатов, вероятно, приведет к экспоненциальному увеличению использования памяти при незначительном улучшении скорости, что может фактически замедлить работу в системах, в которых может произойти пейджинг (перехват) vm.

...