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

Вниз

Помогите оптимизировать не большой код   Найти похожие ветки 

 
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&#215;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 bpp
byte ptr[ESI +ECX*4 + (1|2|3)]
inc  ECX
занимает не больше тактов чем
byte 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.



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

Текущий архив: 2011.05.01;
Скачать: CL | DM;

Наверх




Память: 0.57 MB
Время: 0.016 c
2-1295709528
Новик
2011-01-22 18:18
2011.05.01
Изменение поля ввода TEdit;


2-1292196382
Германн
2010-12-13 02:26
2011.05.01
Структура БД


15-1295136146
Palladin
2011-01-16 03:02
2011.05.01
Java 7, большие числовые константы


2-1296220502
Сергей _
2011-01-28 16:15
2011.05.01
Вопрос оптимизации


2-1295808004
faiwer
2011-01-23 21:40
2011.05.01
Макрос