Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 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&#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.


 
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
2-1295695155
Тимоха111
2011-01-22 14:19
2011.05.01
record из dll


2-1295713769
Taras1995
2011-01-22 19:29
2011.05.01
StringGrid &amp; QReport


2-1296210428
lemparius
2011-01-28 13:27
2011.05.01
Еще одна задача на PageControl


15-1295343778
Knight
2011-01-18 12:42
2011.05.01
Программа regmon+filemon


15-1295382887
cross
2011-01-18 23:34
2011.05.01
hex-редактор





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский