Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2004.06.27;
Скачать: [xml.tar.bz2];

Вниз

Производительность (оптимизация) функции   Найти похожие ветки 

 
pasha_golub ©   (2004-06-09 10:44) [0]

Имеем код:

type
 TForm1 = class(TForm)
    ...
 end;

MeasureFunc = procedure(ACanvas: TCanvas; ARect: TRect;
         FromColor, ToColor: TColor);
var
 Form1: TForm1;

implementation

{$R *.dfm}

procedure VGradientFill(ACanvas: TCanvas; ARect: TRect;
         FromColor, ToColor: TColor);
var
 FC: array [0..3] of byte absolute FromColor;
 TC: array [0..3] of byte absolute ToColor;
 Steps, Y: integer;
 DR, DG, DB: integer;
begin
 Steps := ARect.Bottom - ARect.Top - 2;
 if Steps <= 0 then Exit;
 FromColor := ColorToRGB(FromColor);
 ToColor := ColorToRGB(ToColor);
 DR := TC[0] - FC[0];
 DG := TC[1] - FC[1];
 DB := TC[2] - FC[2];
 for Y := ARect.Top + 1  to ARect.Bottom - 1 do
   with ACanvas do
     begin
      MoveTo(ARect.Left, Y);
      Pen.Color := RGB(TC[0] - MulDiv(DR,Y,Steps),
                       TC[1] - MulDiv(DG,Y,Steps),
                       TC[2] - MulDiv(DB,Y,Steps));
      LineTo(ARect.Right,Y);
     end;
end;

procedure VGradientFill2(ACanvas: TCanvas; ARect: TRect;
         FromColor, ToColor: TColor);
var
 Steps, Y: integer;
 DR, DG, DB: integer;
begin
 Steps := ARect.Bottom - ARect.Top - 2;
 if Steps <= 0 then Exit;
 FromColor := ColorToRGB(FromColor);
 ToColor := ColorToRGB(ToColor);
 DR := GetRValue(ToColor) - GetRValue(FromColor);
 DG := GetGValue(ToColor) - GetGValue(FromColor);
 DB := GetBValue(ToColor) - GetBValue(FromColor);
 for Y := ARect.Top + 1  to ARect.Bottom - 1 do
   with ACanvas do
     begin
      MoveTo(ARect.Left, Y);
      Pen.Color := RGB(GetRValue(ToColor) - MulDiv(DR,Y,Steps),
                       GetGValue(ToColor) - MulDiv(DG,Y,Steps),
                       GetBValue(ToColor) - MulDiv(DB,Y,Steps));
      LineTo(ARect.Right,Y);
     end;
end;

procedure VGradientFill3(ACanvas: TCanvas; ARect: TRect;
         FromColor, ToColor: TColor);
var
 Steps, Y: integer;
 DR, DG, DB: integer;
 TR,TG,TB:byte;
begin
 Steps := ARect.Bottom - ARect.Top - 2;
 if Steps <= 0 then Exit;
 FromColor := ColorToRGB(FromColor);
 ToColor := ColorToRGB(ToColor);
 TR := GetRValue(ToColor);
 TG := GetGValue(ToColor);
 TB := GetBValue(ToColor);
 DR := TR - GetRValue(FromColor);
 DG := TG - GetGValue(FromColor);
 DB := TB - GetBValue(FromColor);
 for Y := ARect.Top + 1  to ARect.Bottom - 1 do
   with ACanvas do
     begin
      MoveTo(ARect.Left, Y);
      Pen.Color := RGB(TR - MulDiv(DR,Y,Steps),
                       TG - MulDiv(DG,Y,Steps),
                       TB - MulDiv(DB,Y,Steps));
      LineTo(ARect.Right,Y);
     end;
end;

function Measure(MF: MeasureFunc):int64;
var i:integer;
begin
 SetThreadPriority(GetCurrentThread,THREAD_PRIORITY_TIME_CRITICAL);
 Result := GetTickCount;
 for i:=1 to 10000 do
  with Form1 do
   MF(Canvas,ClientRect,i,0);
 Result := GetTickCount - Result;
 SetThreadPriority(GetCurrentThread,THREAD_PRIORITY_NORMAL);
end;

procedure TForm1.Button1Click(Sender: TObject);
var s :string;
begin
 FmtStr(S,"1:%d; 2:%d; 3:%d",[Measure(@VGradientFill),Measure(@VGradientFill2),Measure(@VGradientFill3)]);
 ShowMessage(S);
end;

end.


Итак, три реализации градентной заливки. Здесь я не хочу обсуждать другую реализацию алгоритма, а хочу заострить внимание на некоторых мелочах.

А именно.
1 функция: доступ к каждому компоненту цвета реализован через совместный доступ к памяти (директива absolute)
2 функция: доступ к каждому компоненту цвета реализован через существующие для этого функции (GetXValue), по сути через shr&shl
3 функция: тоже самое, что и вторая, но используются вспомогательные локальные переменные (TR,TG,TB)

Результаты:
1) 30544
2) 30798
3) 46199

Вопросы:
1. Могу ошибаться, но кто-то заявлял, что работа через absolute медленнее аналогичных. Про небезопасность кода и предупреждения компилятора я знаю, сейчас не про это. Так вот, это ошибка эксперимента или как?

2. Почему 3 функция так значительно отстает от 2? Ведь наскоко я понимаю доступ к локальным переменным осуществляется быстрее чем получение результатов функций (в данном примере GetXValue)

3. Если все-таки работа через absolute быстрее чем со сдвигами, почему же много людей так неохотно использовали (в связи с грядущим .НЕТ, я понимаю, что это небезопасно) эту гибкую систему?

Фух, спасибо за внимание.


 
pasha_golub ©   (2004-06-09 10:45) [1]

Прошу простить за путаницу в терминах, конечно речь идет о процедурах. :-)


 
MBo ©   (2004-06-09 12:34) [2]

1. у меня время одинаковое
2. 96% процента времени занимает вывод графики ;)


 
pasha_golub ©   (2004-06-09 12:38) [3]

1. у меня время одинаковое
Хм, вот те на. Что совсем одинаковое? :-)

2. 96% процента времени занимает вывод графики ;)
Кто ж спорит? :-)


 
MBo ©   (2004-06-09 12:44) [4]

>Что совсем одинаковое? :-)
Да, в пределах погрешности (полпроцента)

>96% процента времени занимает вывод графики ;)
В частности, изменение цвета пера (Pen.Color := ) - более половины времени работы программы.

>Кто ж спорит? :-)
Так сделай тест разумнее...


 
Daniel_   (2004-06-09 13:22) [5]

MBo ©  
А можно глупый, наверное, вопрос?

Каким образом вы узнаете какую долю времени выполняется каждая операция?


 
pasha_golub ©   (2004-06-09 13:24) [6]

Изменил код процедур:

procedure VGradientFill(ACanvas: TCanvas; ARect: TRect;
         FromColor, ToColor: TColor; var Res:TColor);
var
 FC: array [0..3] of byte absolute FromColor;
 TC: array [0..3] of byte absolute ToColor;
 Steps, Y: integer;
 DR, DG, DB: integer;
begin
 Steps := ARect.Bottom - ARect.Top - 2;
 if Steps <= 0 then Exit;
 FromColor := ColorToRGB(FromColor);
 ToColor := ColorToRGB(ToColor);
 DR := TC[0] - FC[0];
 DG := TC[1] - FC[1];
 DB := TC[2] - FC[2];
 for Y := ARect.Top + 1  to ARect.Bottom - 1 do
   with ACanvas do
     begin
      MoveTo(ARect.Left, Y);
      Res := RGB(TC[0] - MulDiv(DR,Y,Steps),
                TC[1] - MulDiv(DG,Y,Steps),
                TC[2] - MulDiv(DB,Y,Steps));
      //LineTo(ARect.Right,Y);
     end;
end;


В результате на 10000 итерациях:
1. 3810
2. 3959
3. 3815


 
MBo ©   (2004-06-09 13:27) [7]

>Daniel_
с помощью профайлера


 
pasha_golub ©   (2004-06-09 13:28) [8]

Daniel_   (09.06.04 13:22) [5]
Профайлером скорее всего.


 
pasha_golub ©   (2004-06-09 13:28) [9]

Удалено модератором
Примечание: Дубль


 
MBo ©   (2004-06-09 13:32) [10]

>pasha_golub ©   (09.06.04 13:24) [6]
А оптимизатор не удаляет строку:
Res := RGB(TC[0] - MulDiv(DR,Y,Steps),
               TC[1] - MulDiv(DG,Y,Steps),
               TC[2] - MulDiv(DB,Y,Steps));
?
может, завести глобальную переменную dummy, делать, например, dummy:=Res xor dummy, в конце вывести ее значение...


 
pasha_golub ©   (2004-06-09 13:33) [11]

Опять я прогнал. Забыл убрать Canvas.MoveTo:

procedure VGradientFill(ACanvas: TCanvas; ARect: TRect;
         FromColor, ToColor: TColor; var Res:TColor);
var
 FC: array [0..3] of byte absolute FromColor;
 TC: array [0..3] of byte absolute ToColor;
 Steps, Y: integer;
 DR, DG, DB: integer;
begin
 Steps := ARect.Bottom - ARect.Top - 2;
 if Steps <= 0 then Exit;
 FromColor := ColorToRGB(FromColor);
 ToColor := ColorToRGB(ToColor);
 DR := TC[0] - FC[0];
 DG := TC[1] - FC[1];
 DB := TC[2] - FC[2];
 for Y := ARect.Top + 1  to ARect.Bottom - 1 do
   with ACanvas do
     begin
      //MoveTo(ARect.Left, Y);
      Res{Brush.Color} := RGB(TC[0] - MulDiv(DR,Y,Steps),
                       TC[1] - MulDiv(DG,Y,Steps),
                       TC[2] - MulDiv(DB,Y,Steps));
      //LineTo(ARect.Right,Y);
     end;
end;

В таком же духе и другие процедуры. Получил на 10000 итерациях:
1. 1854
2. 2001
3. 1846


 
pasha_golub ©   (2004-06-09 13:36) [12]

MBo ©   (09.06.04 13:32) [10]
Нет, не удаляет. Res - это ж вар-параметр


 
Daniel_   (2004-06-09 14:37) [13]

> с помощью профайлера
> Профайлером скорее всего.

 Спасибо, пошел выбирать. Их, оказывается, много.



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2004.06.27;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.49 MB
Время: 0.032 c
1-1087066633
jack128
2004-06-12 22:57
2004.06.27
Почему ESCAPE считается символом, а DELETE нет?


4-1085076219
Pupernik
2004-05-20 22:03
2004.06.27
невидимые формы


14-1086433773
Iraizor
2004-06-05 15:09
2004.06.27
Млин, подскажите сайт


14-1086896423
gn
2004-06-10 23:40
2004.06.27
Процессоры Intel будут определять местоположение пользователя


1-1087207741
Arestotel
2004-06-14 14:09
2004.06.27
Проблемы с MDI !!!





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский