Форум: "Начинающим";
Текущий архив: 2011.05.01;
Скачать: [xml.tar.bz2];
ВнизПомогите оптимизировать не большой код Найти похожие ветки
← →
novai (2011-01-26 07:08) [0]Можно ли оптимизировать данный код:
...
P: pRGBLine;
..
for yy:= 0 to Height - 1 do
begin
p:= Scanline[yy];
for xx := 0 to Width - 1 do
begin
p^[xx].rgbtRed:= p^[xx].rgbtRed - muldiv(p^[xx].rgbtRed,fade,100);
p^[xx].rgbtGreen:= p^[xx].rgbtGreen - muldiv(p^[xx].rgbtGreen,fade,100);
p^[xx].rgbtBlue:= p^[xx].rgbtBlue - muldiv(p^[xx].rgbtBlue,fade,100);
end;
end;
чтобы не за 3 такта а за один?
как то так:p^[xx]:= p^[xx] - (p^[xx] * fade div 100);
← →
KilkennyCat © (2011-01-26 07:18) [1]может быть и можно. но в одной книжке было написано, что вылизывание такого рода даст прирост скорости на 10%, не более, при колоссальной затрате времени. В то время как пересмотр алгоритма и технологии может позволить ускорить в разы. Ибо все эти математические штучки вычисляются ну очень быстро, а картинки обычным образом сменяются ну очень медленно.
← →
novai (2011-01-26 07:39) [2]это алгоритм FadeIn FadeOut...
работаем с TPngObject.
можно что-то сделать? тк при подготовке и отрисовке:// отрисуем сцену на DrawCanvas (Form.canvas)
BitBlt(
DrawCanvas.Handle,
0, 0,
Width, Height + PanelHeight,
Canvas.Handle,
0, 0,
SRCCOPY);
у меня железные 64 фпс...
← →
novai (2011-01-26 07:40) [3]
> у меня железные 64 фпс...
DrawTimer:= TTimer.Create(nil);
DrawTimer.Enabled:= False;
DrawTimer.Interval:= 10;
DrawTimer.OnTimer:= OnDrawTimer;
← →
novai (2011-01-26 07:42) [4]а при включении кода из первого поста только 14-15 фпс(
← →
Ega23 © (2011-01-26 07:54) [5]
> DrawTimer:= TTimer.Create(nil);
Почему от nil?
← →
Ega23 © (2011-01-26 07:55) [6]
> DrawTimer.Interval:= 10;
Почему 10? Ты думаешь, что уложишься? Поставь 100 для начала.
← →
novai (2011-01-26 07:55) [7]я сам его создаю, работаю с ним и уничтожаю его
← →
novai (2011-01-26 07:57) [8]
> Поставь 100 для начала.
фпс упал до 9-10(
← →
novai (2011-01-26 07:58) [9]что и понятно... или нет?)
← →
Ega23 © (2011-01-26 08:14) [10]fade - что такое? Чему равно?
← →
novai (2011-01-26 08:23) [11]fade: byte;
перед стартом:
выставляется в
fade:= 100;
if fading:= true;
далее
procedure TScene.OnDrawTimer(Sender: TObject);
...
формируем изображение сцены (при DrawTimer.Interval:= 10 - железные 64 фпс)
...
if fading then
begin
fade:= fade - 2;
if fade <= 0 then
begin
fading:= false;
fade:= 0;
end;
for yy:= 0 to Height - 1 do
begin
p:= Scanline[yy];
for xx := 0 to Width - 1 do
begin
p^[xx].rgbtRed:= p^[xx].rgbtRed - muldiv(p^[xx].rgbtRed,fade,100);
p^[xx].rgbtGreen:= p^[xx].rgbtGreen - muldiv(p^[xx].rgbtGreen,fade,100);
p^[xx].rgbtBlue:= p^[xx].rgbtBlue - muldiv(p^[xx].rgbtBlue,fade,100);
end;
end;
end;
// отрисуем сцену на DrawCanvas (Form.canvas)
BitBlt(
DrawCanvas.Handle,
0, 0,
Width, Height + PanelHeight,
Canvas.Handle,
0, 0,
SRCCOPY);
Drawing:= false;
end;
← →
novai (2011-01-26 08:24) [12]
> if fading:= true;
читать без IF...
← →
MBo © (2011-01-26 08:27) [13]Если тормоза действительно в этом коде, то
1) попробовать заменить muldiv на умножение со сдвигом вправо
Поскольку fade - одно и тоже, то множитель и величину сдвига достаточно подобрать до цикла. Проверить, поможет ли это - нетрудно, достаточно
p^[xx].rgbtRed - muldiv(p^[xx].rgbtRed,fade,100) временно поменять на
(p^[xx].rgbtRed * 100) shr 7,и так в каждой строке
2)использовать MMX. Неплохо пойдет, если растр 32-битный, а не 24-битный
3)использовать графические библиотеки, где нужные операции уже есть, типа Graphics32 и т.д.
← →
novai (2011-01-26 08:30) [14]
> Если тормоза действительно в этом коде, то
да(
> если растр 32-битный, а не 24-битный
растр: pf16bit (
← →
novai (2011-01-26 08:35) [15]
> Поскольку fade - одно и тоже, то множитель и величину сдвига
> достаточно подобрать до цикла. Проверить, поможет ли это
> - нетрудно, достаточно
> p^[xx].rgbtRed - muldiv(p^[xx].rgbtRed,fade,100) временно
> поменять на
> (p^[xx].rgbtRed * 100) shr 7,и так в каждой строке
наблюдаю не большое затемнение и окончание работы if fading then
← →
novai (2011-01-26 08:36) [16]
> наблюдаю не большое затемнение и окончание работы if fading
> then
наблюдаю не большое затемнение, потом нормализацию и окончание работы if fading
← →
novai (2011-01-26 09:14) [17]посмотрел
> Graphics32
сделал так:
if fading then
begin
fade:= fade - 2;
if fade <= 0 then
begin
fading:= false;
fade:= 0;
end;
for yy:= 0 to Height - 1 do
begin
p:= Scanline[yy];
for xx := 0 to Width - 1 do
begin
r:= p^[xx].rgbtRed;
g:= p^[xx].rgbtGreen;
b:= p^[xx].rgbtBlue;
Dec(r, fade);
Dec(g, fade);
Dec(b, fade);
if r > 255 then r := 255 else if r < 0 then r := 0;
if g > 255 then g := 255 else if g < 0 then g := 0;
if b > 255 then b := 255 else if b < 0 then b := 0;
p^[xx].rgbtRed:= r;
p^[xx].rgbtGreen:= g;
p^[xx].rgbtBlue:= b;
end;
end;
end;
при работе if fading then - 60 фпс - нормально, всем спасибо!
← →
MBo © (2011-01-26 09:18) [18]>растр: pf16bit
откуда в сканлайнах 16-битного растра возьмутся p^[xx].rgbtRed и т.д.????
← →
novai (2011-01-26 09:20) [19]
> откуда в сканлайнах 16-битного растра возьмутся p^[xx].rgbtRed
> и т.д.????
я сказал:
> работаем с TPngObject.
← →
RWolf © (2011-01-26 09:29) [20]p^[xx].rgbtХХХ неплохо бы заменить на указатель — вычисление этой конструкции занимает лишние такты.
← →
sniknik © (2011-01-26 09:30) [21]> работаем с TPngObject.
тогда я чего то не понимаю... вывод идет битмапом, обработка идет на битмапе, а работаем почему то с TPngObject. ???
разве он не организует "сжатие" в png, которое не получается нужно, а потом "разжатие" для отрисовки, что точно чего то да занимает по времени.
← →
RWolf © (2011-01-26 09:30) [22]и да, MMX тут хорошо подходит, имхо.
← →
novai (2011-01-26 09:37) [23]
> разве он не организует "сжатие" в png, которое не получается
> нужно, а потом "разжатие" для отрисовки,
я не могу объяснить такие тонкости, видимо нет...
← →
RWolf © (2011-01-26 11:33) [24]проверил: с использованием MMX FPS подрос почти в два раза (240 против 140 кадров/с на картинке 640×426).
← →
novai (2011-01-26 11:38) [25]можно посмотреть реализацию?
← →
RWolf © (2011-01-26 11:41) [26]
asm
mov eax,$00010101
movd mm1,eax
end;
for yy:= 0 to Image1.Height - 1 do
begin
p:= Image1.Picture.Bitmap.ScanLine[yy];
dwWidth:=Image1.Width;
asm
push ecx
push edi
mov ecx,dwWidth
mov edi,p
ll:
movd mm0,[edi]
psubusb mm0,mm1
movd [edi],mm0
add edi,3
loop ll
pop edi
pop ecx
end;
end;
asm
EMMS
end;
← →
RWolf © (2011-01-26 11:43) [27]да, это для 24-бит рисунка.
← →
novai (2011-01-26 11:45) [28]я уже понял( а для 16 не сможете?
← →
novai (2011-01-26 11:46) [29]а алгоритм из 17 поста на асме не ускорит его выполнение?
← →
RWolf © (2011-01-26 11:48) [30]в 16 бит всё упирается распаковку R, G и B-составляющих, тут MMX не поможет, как мне кажется.
← →
novai (2011-01-26 11:49) [31]значит 17 оптимален?
← →
RWolf © (2011-01-26 11:52) [32]
> значит 17 оптимален?
нет — как я уже говорил, вполне можно повыкидывать разыменования указателей p и непонятные индексации.
← →
RWolf © (2011-01-26 11:52) [33]но быстрее 24-битного варианта это, скорее всего, не будет.
← →
novai (2011-01-26 12:18) [34]
> повыкидывать разыменования указателей p и непонятные индексации.
можно показать? я только учусь...
← →
han_malign (2011-01-26 12:40) [35]
> p^[xx].rgbtХХХ неплохо бы заменить на указатель — вычисление
> этой конструкции занимает лишние такты.
для 32 bppbyte ptr[ESI +ECX*4 + (1|2|3)]
занимает не больше тактов чем
inc ECXbyte ptr[ESI + (1|2|3)]
inc ESI, 4
- а вот работа с DWORD (даже без MMX - на сдвигах/масках) даст ускорение - аккурат 400%. И учитывая, что строка DIB выравнивается на 32 бита, для однотипных побайтовых операций нам по барабану 32 или 24 bpp...
> а для 16 не сможете?
- еще раз, для тех кто на ручнике, в 16 bpp не может быть никаких TRGBTriple
> да, это для 24-бит рисунка.
- это(mov eax,$00010101) как раз для 32 bpp,
а для 24 bpp - нужно:
asm
mov eax,$01010101
movd mm1,eax
end;
pdw:= PDWORD(Image1.Picture.Bitmap.ScanLine[0]);
cdwPitch:= (Image1.Width*3+3) div 4;//24 bpp image scan line size in DWORDs
cdwSize:= Image1.Height*cdwPitch;
asm
push ecx
push edi
mov ecx,cdwSize
mov edi,p
ll:
movd mm0,[edi]
psubusb mm0,mm1
movd [edi],mm0
add edi,4
loop ll
pop edi
pop ecx
EMMS
end;
- особо дотошные могут в отдельном цикле почистить концевые байты выравнивания:if(Image1.Width and 3 <> 0)then begin
inc(pdw, cdwPitch-1);
fdwClearPad:= not($FFFFFFFF shl ((Image1.Width and 3)*8));
for yy:= 0 to Image1.Height-1 do begin
pdw^:= pdw^ and fdwClearPad;
inc(pdw, cdwPitch);
end;
end;
← →
RWolf © (2011-01-26 12:49) [36]
> для однотипных побайтовых операций нам по барабану 32 или
> 24 bpp
логично, это я не продумал алгоритм :) 420 fps.
← →
novai (2011-01-26 13:11) [37]
> - еще раз, для тех кто на ручнике, в 16 bpp не может быть
> никаких TRGBTriple
создаю так:TScene.createblank({COLOR_RGB} 2, 16, SceneWidth,
SceneHeight + PanelHeight);
вот описание:{Portable Network Graphics object being created as a blank image}
constructor TPNGObject.CreateBlank(ColorType, BitDepth: Cardinal;
cx, cy: Integer);
var NewIHDR: TChunkIHDR;
begin
{Calls creator}
Create;
{Checks if the parameters are ok}
if not (ColorType in [COLOR_GRAYSCALE, COLOR_RGB, COLOR_PALETTE,
COLOR_GRAYSCALEALPHA, COLOR_RGBALPHA]) or not (BitDepth in
[1,2,4,8, 16]) or ((ColorType = COLOR_PALETTE) and (BitDepth = 16)) or
((ColorType = COLOR_RGB) and (BitDepth < 8)) then
begin
RaiseError(EPNGInvalidSpec, EInvalidSpec);
exit;
end;
if Bitdepth = 2 then Bitdepth := 4;
{Add the basis chunks}
InitializeGamma;
BeingCreated := True;
Chunks.Add(TChunkIEND);
NewIHDR := Chunks.Add(TChunkIHDR) as TChunkIHDR;
NewIHDR.IHDRData.ColorType := ColorType;
NewIHDR.IHDRData.BitDepth := BitDepth;
NewIHDR.IHDRData.Width := cx;
NewIHDR.IHDRData.Height := cy;
NewIHDR.PrepareImageData;
if NewIHDR.HasPalette then
TChunkPLTE(Chunks.Add(TChunkPLTE)).fCount := 1 shl BitDepth;
Chunks.Add(TChunkIDAT);
BeingCreated := False;
end;
пока писал, понял, что это RGB...
← →
Slym © (2011-01-26 14:29) [38]RWolf © (26.01.11 11:48) [30]
в 16 бит всё упирается распаковку R, G и B-составляющих
1. какое описание pRGBLine? может там уже все разложено...
2. регистры 64 битные т.е. в пакет по 4 пикселя 16бит, 3 24бит и 2 32бит.procedure Fade32(Bitmap:TBitmap;const Value:integer);
label ll;
var
y,lp:integer;
p:pointer;
begin
if Bitmap.PixelFormat<>pf32bit then exit;
asm
mov eax,Value
and eax, $ff
movd mm1,eax
punpcklbw mm1, mm1
punpcklwd mm1, mm1
punpckldq mm1, mm1
end;
for y:= 0 to Bitmap.Height - 1 do
begin
p:=Bitmap.ScanLine[y];
lp:=Bitmap.Width div 2;
asm
push ecx
push edi
mov ecx,lp
mov edi,p
ll:
movq mm0,[edi]
psubusb mm0,mm1
movq [edi],mm0
add edi, 8
loop ll
pop edi
pop ecx
end;
end;
asm
EMMS
end;
end;
2. можно поиграться с разворотом циклов регистров то 8 MM0—MM7
типа такprocedure Fade32_2(Bitmap:TBitmap;const Value:integer);
label ll;
var
y,lp:integer;
p:pointer;
begin
ifBitmap.PixelFormat<>pf32bit then exit;
asm
mov eax,Value
and eax, $ff
movd mm0,eax
punpcklbw mm0, mm0
punpcklwd mm0, mm0
punpckldq mm0, mm0
end;
for y:= 0 to Bitmap.Height - 1 do
begin
p:=Bitmap.ScanLine[y];
lp:=Bitmap.Width div (2*4);
asm
push ecx
push edi
mov ecx,lp
mov edi,p
ll:
movq mm1,[edi]
movq mm2,[edi+8]
movq mm3,[edi+16]
movq mm4,[edi+24]
psubusb mm1,mm0
psubusb mm2,mm0
psubusb mm3,mm0
psubusb mm4,mm0
movq [edi] ,mm1
movq [edi+8] ,mm2
movq [edi+16],mm3
movq [edi+24],mm4
add edi,32
loop ll
pop edi
pop ecx
end;
end;
asm
EMMS
end;
end;
проверяем такprocedure TForm1.BtnFade32Click(Sender: TObject);
var
Bitmap:TBitmap;
i:integer;
begin
Bitmap:=TBitmap.Create;
try
Bitmap.LoadFromFile("c:\1.bmp");
Bitmap.PixelFormat:=pf32bit;
for i:=0 to (256 div 4 -1) do
begin
Fade32(Bitmap,4);
Image1.Picture.Bitmap.Assign(Bitmap);
Application.ProcessMessages;
end;
finally
Bitmap.Free;
end;
end;
← →
novai (2011-01-26 14:42) [39]
> 1. какое описание pRGBLine? может там уже все разложено.
> ..unit windows
tagRGBTRIPLE = packed record
rgbtBlue: Byte;
rgbtGreen: Byte;
rgbtRed: Byte;
end;
← →
RWolf © (2011-01-26 14:55) [40]
> Slym © (26.01.11 14:29) [38]
> 2. регистры 64 битные т.е. в пакет по 4 пикселя 16бит, 3 24бит и 2 32бит.
тоже верно :) 510 fps.
← →
novai (2011-01-26 14:56) [41]я смотрю, вы тут фпс"ами меряетесь?)
← →
Slym © (2011-01-26 15:00) [42]24 битный вариант с развернутым циклом
procedure Fade24(Bitmap:TBitmap;const Value:integer);
label ll;
var
y,lp:integer;
p:pointer;
begin
if Bitmap.PixelFormat<>pf24bit then exit;
asm
mov eax,Value
and eax, $ff
movd mm0,eax
punpcklbw mm0, mm0
punpcklwd mm0, mm0
punpckldq mm0, mm0
end;
for y:= 0 to Bitmap.Height - 1 do
begin
p:=Bitmap.ScanLine[y];
lp:=Bitmap.Width div 16;// 8*6 в байтах = 16 в пикселях
asm
push ecx
push edi
mov ecx,lp
mov edi,p
ll:
movq mm1,[edi]
movq mm2,[edi+8]
movq mm3,[edi+16]
movq mm4,[edi+24]
movq mm5,[edi+32]
movq mm6,[edi+40]
psubusb mm1,mm0
psubusb mm2,mm0
psubusb mm3,mm0
psubusb mm4,mm0
psubusb mm5,mm0
psubusb mm6,mm0
movq [edi] ,mm1
movq [edi+8] ,mm2
movq [edi+16],mm3
movq [edi+24],mm4
movq [edi+32],mm5
movq [edi+40],mm6
add edi,48
loop ll
pop edi
pop ecx
end;
end;
asm
EMMS
end;
end;
← →
Slym © (2011-01-26 15:05) [43]все мои варианты без обработки хвостов!
вариант Slym © (26.01.11 15:00) [42] выравнивается на 16 пикселей, т.е. хвостовые пиксели (Bitmap.Width mod 16) нужно допиливать вручную
Страницы: 1 2 вся ветка
Форум: "Начинающим";
Текущий архив: 2011.05.01;
Скачать: [xml.tar.bz2];
Память: 0.57 MB
Время: 0.005 c