Avatar billede delphi Nybegynder
26. oktober 2000 - 10:53 Der er 10 kommentarer og
1 løsning

Masser af pixels....

I forbindelse med realtime behandling af data fra et videokamera, skal jeg ha\' sat en værdi afhængigt lystyrken (Y) i en pixel værdi.  Det ligger lige som i luften, at behandlingen skal gå hurtigt, idet der i sagens natur kommer mange data hvert sekund fra et 640*480 pixels kamera.

Det jeg ønsker er at få en outputværdi på enten $00 eller $FF anhængigt af om input værdien er over eller under en værdi på $80.

I alm. Object Pascal kan det udtrykkes som:

  If Y>127 Then
    X := 255
  else
    X := 0;

Laves denne forespørgelses/assignment kombination for hver indkommen pixel, går CPU belastningen på min 650 MHz Pc fra 20 til ~55% - det er ikke rigtigt holdbart.
Jeg har en ide om, at jeg kan droppe forspørgelsen, dvs. If-delen, og istedet lave det om til en gang logisk algebra  evt i kombination med noget bit shifteri/rotation, i et assignment, som jeg så formoder er hurtigere.  Noget i retning af

  X := (Y And $80) ... ... ..

Men hvorledes...  Parantesen (Y And $80) vil altid resultere i en værdi på enten $00 eller $80 - det skal altså bare laves om til 0 og $FF.  (Jeg kan godt acceptere en værdi på $01 istedet for $00 - hvis det gør sagerne nemmere fx i fbm. en rotation).

Delphi
Avatar billede delphi Nybegynder
26. oktober 2000 - 11:04 #1
Jeg tror at jeg har løst problemet selv (så\'en går det når man skal forklare det til andre....).

Nedenstående bør gøre tricket:

  X := ($FF00 SHR ((X AND $80) SHR 4) AND $FF;

Det indgår nu 4 logiske operationer + noget der ligner 4 load accumulator opeartioner.... gad vide om det er hurtigere end en IF sætning, men det skal en test vise.  1 cpu cycle/pixel kan ses når der behandles ca. 9 mill pixels pr. sekund.

Delphi

PS: Pointsne er stadig ude, hvis der er en anden der kommer med et lignende svar inden for ~5 min eller evt et bedre svar på et senere tidspunkt.
Avatar billede pellelil Nybegynder
26. oktober 2000 - 11:43 #2
Hvordan kigger du på dine pixels?. Hvis du kigger på dem en pixel af gangen så tager det en evighed (og lidt til). I stedet skal du bruge ScanLine
<SNIP>
procedure TForm1.Button1Click(Sender: TObject);

// This example shows drawing directly to the BitMap
var
  x,y : Integer;
  BitMap : TBitMap;
  P : PByteArray;
begin
  BitMap := TBitMap.create;
  try
    BitMap.LoadFromFile(\'..\\Images\\Splash\\256color\\factory.bmp\');
    for y := 0 to BitMap.height -1 do
    begin
      P := BitMap.ScanLine[y];
      for x := 0 to BitMap.width -1 do
        P[x] := y;
    end;
  Canvas.draw(0,0,BitMap);

  finally
    BitMap.free;
  end;
end;
</SNIP>
Avatar billede borrisholt Novice
26. oktober 2000 - 12:49 #3
Jeg har ikke testet det men logisk set må du sætte tid til ved din omskrivning :

Hvis nu vi omsætter det til funkioner så ser det sådan her ud (for eksemplets skyld):

Function _ModifyX(x : integer) : Integer;
begin
  If x>127 Then
    result := 255
  else
    result := 0;
end;

og

Function __ModifyX(x : integer) : Integer;
begin
  result := ($FF00 SHR ((X AND $80) SHR 4) AND $FF;
end;

Oversætter vi det til assebmler ser regnestykker sådan her ud :


Function _ModifyX(x : integer) : Integer;
asm
  mov ecx,eax
  and ecx,$80
  shr ecx,$04
  mov eax,$ff00
  shr eax,cl
  and eax,$ff
end;

og

Function __ModifyX(x : integer) : Integer;
asm
  cmp eax,$7f
  jle @@0
  mov eax,$00ff
  ret
@@0:
  xor eax,eax
end;

i det vi skal huske at end; også bliver til en ret instruktion må man i det sidste tilfælde have sparet 3 instruktioner.

problemet ligger nok nærmere i at en alm TBitmsp er sløv som bare det ...

Skriv en ny eller spørg mig efter en der er hurtigere ...

Jens B
Avatar billede delphi Nybegynder
26. oktober 2000 - 12:49 #4
Der er ikke tale om pixels på en skærm.  som jeg skrev kommer de fra et kamera.  Rent faktisk fra et Sony DFW-V500 kamera forbundet til en Fire wire.  Dataene leveres i en buffer (stort array) fra driverene.

Delphi
Avatar billede borrisholt Novice
26. oktober 2000 - 12:51 #5
derforr sætter du tid til alligevel ..

Jens B
Avatar billede pellelil Nybegynder
26. oktober 2000 - 13:20 #6
borrisholt> Med optimering slået til kan det svare sig at \"ty til Assembler\" ? - jeg mener der er jo ingen HEST i assembler :-)
Avatar billede borrisholt Novice
26. oktober 2000 - 13:29 #7
Som regl kan det ikke svare sig .... nej. Det var nu også mere for at anskugeligøre mit argument om at det første kode var hurtigere end den andet .... Dog lod det ikke til at mine argumenter vandt megen indpas hos hin spørger.

bare fordi man koder assembler kan man vel godt have en hest eller to gående/travende rundt i koden ..... eller hvad ?

Jens B
Avatar billede pellelil Nybegynder
26. oktober 2000 - 13:35 #8
Ja nogle gange når man kigger på andres kode så kan det da godt se ud som om en HEST eller to har travet rundt i det :-)

Desværre var jeg ikke selv i besidelse af en PC da jeg i sin tid blev undervist i Assembler så det hang ikke så godt fast. Jeg havde i de gode gamle TP7 dage en del strengroutiner i assembler, men i forbindelse med Delphi valgte jeg at omskrive den til Delphi kode.
Avatar billede delphi Nybegynder
26. oktober 2000 - 14:05 #9
Nu er antallet af assembler instruktionen ikke nødvendigvis det samme som tid - ihvertfald skal man tage hensyn til typen af instruktioner. 
Her underneden kigger jeg på borris\'s kode.  Jeg vælger at se bort fra alle RET\'s idet jeg jo liggger og drøner rundt i en løkke, hvor der ikke er tid til at involvere procedure kald.  Jeg tager mig lidt friheder, idet jeg anvender lidt andre modes end i borris\'s kode, bl.a. er jeg inde i et array for at hente mine data (Based Indexed)

Tallet foran kommandoerne er det antal cycles der skal benyttes i de aktuelle addreserings modes:

17  mov eax, (BP)+(SI)
2  mov ecx,eax
4  and ecx,$80
2  shr ecx,$04
4  mov eax,$ff00
12  shr eax,cl // Jeg er lidt usikker på tallet her - det kan være 4.
4  and eax,$ff
17  mov (BP)+(SI), ax
---
62 cycles  (måske 54)


17  mov eax, (BP)+(SI)
4  cmp eax,$7f
4/16 jle @@0
4  mov eax,$00ff
15  jmp @@1
@@0:
3  xor eax,eax
@@1:
17  mov (BP)+(SI), ax
---
57/61

eler hvis man flytter de fælles MOV instruktioner væk:

28 (evt 20) imod 23/27 cycles.  - Det er her helt klart jump instruktionerne der tager tiden.

Det er første gang i mere end 10 år hvor jeg har haft brug for at tune et program på den måde.  Men der sker altså noget når der ryger 9.000.000 pixels (af 16 bit) ind pr sekund - så hver cpu cycle tæller.

Delphi
Avatar billede borrisholt Novice
26. oktober 2000 - 16:00 #10
Placer 2 knapper og 2 labels på en form og prøv det her :

Function GetTimeStamp : Int64;
var
  TimeStamp : Record
    case byte of
      1 : (Whole: Int64);
      2 : (LO, HI : longint);
    end;
begin
  asm
    db $0F;
    db $31;
    mov [TimeStamp.LO], eax
    mov [TimeStamp.HI], edx
  end;
  Result:=TimeStamp.Whole;
end;


procedure TForm1.Button1Click(Sender: TObject);
var
  Start, Stop : Int64;
  i : integer;
  y : integer;
begin
  Start := GetTimeStamp;

  i := 12;
  If i>127 Then
    y := 255
  else
    y := 0;

  Stop := GetTimeStamp;

  Label1.Caption := IntToStr(y);
  Label1.Caption := IntToStr(Stop-Start);
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  Start, Stop : Int64;
  i : integer;
  y : integer;
begin
  Start := GetTimeStamp;

  i:= 12;
  y:= ($FF00 SHR ((i AND $80) SHR 4) AND $FF);

  Stop := GetTimeStamp;

  Label2.Caption := IntToStr(y);
  Label2.Caption := IntToStr(Stop-Start);
end;

Jens B
Avatar billede borrisholt Novice
26. oktober 2000 - 16:16 #11
Nå men der hvor jeg etenlig ville hen var at jeg med mit lille korte eksempel ikke kan får tingende til at passe ... Og anyway nu er du udstyret med en nem måde til at tællt clock cycels med ....

Jens B
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester