Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.06.27;
Скачать: CL | DM;

Вниз

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

 
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;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.022 c
6-1083822446
Term
2004-05-06 09:47
2004.06.27
Может ли ктонить дать ссылки о инфе для написания FTP-клиента?


11-1075928030
Sniper
2004-02-04 23:53
2004.06.27
альтернатива RichEdit1.SelAttributes.Color := clRed; в KOL?


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


1-1086788472
Sour
2004-06-09 17:41
2004.06.27
Работа с ключами рееста типа REG_MULTI_SZ


10-1013693872
GenBr
2002-02-14 16:37
2004.06.27
Как узнать имя компьютера?