Форум: "Основная";
Текущий архив: 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