Delphi-PRAXiS
Seite 6 von 8   « Erste     456 78      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Geht das noch schneller? - Bitmap-Verrechnung (https://www.delphipraxis.net/182859-geht-das-noch-schneller-bitmap-verrechnung.html)

Dejan Vu 26. Nov 2014 11:45

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
MulDiv basiert auf In64 und ist damit überlauf-sicher, was bei A*B div C imho nicht der Fall ist. Dafür ist es langsamer als der das einfache A*B DIV C.

Bezüglich des Performancevergleiches zielte ich eher auf 'MulDiv' vs. 'Round(A*B/C)' ab, also Floating Point Arithmetik.

Harry Stahl 26. Nov 2014 20:16

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
Zitat:

Zitat von Dejan Vu (Beitrag 1281096)
Aber wieso verwendest Du 'MulDiv' nicht? Das Ergebnis ist um höchstens 1 unterschiedlich (Rundungsverhalten).

Das habe ich schon in Betrag Nr. 10 gesagt, weil es dann doppelt so lange braucht.

Harry Stahl 26. Nov 2014 20:35

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
Um die bisherigen Ergebnisse zusammenzufassen:

* Zugriff auf ein Lookup-Array dauert länger, als die Berechnung.
* MulDiv bringt eindeutig keine Beschleunigung
* Im vorliegenden Fall bringt auch eine Parallelisierung nichts, da der Verwaltungsaufwand
größer ist, als der Gewinn durch mehrere Prozessorkerne

Das bislang schnellste Ergebnis liefert der untenstehende Code, egal, ob per Pointer-Addition oder Array-Zugriff:

Delphi-Quellcode:
procedure Draw32BitToBitmapxxx(const BitOben: TBitmap; BitUnten: TBitmap); // Array-Zugriff
var
   h,w,i, r, g, b: Integer;
   RGBA_Unten, RGBA_Oben: pRGBALine;
begin
    for h := 0 to BitUnten.Height-1 do begin
     RGBA_Unten := BitUnten.ScanLine[h];
     RGBA_Oben := BitOben.ScanLine[h];

     For w:= 0 to BitUnten.Width-1 do begin
       if RGBA_Oben^[w].rgbReserved = 0 then begin
         // unten bleibt
       end else begin
         RGBA_Unten^[w].rgbred := (RGBA_Oben^[w].rgbReserved * (RGBA_Oben^[w].rgbred - RGBA_Unten^[w].rgbred) shr 8 + RGBA_Unten^[w].rgbred);
         RGBA_Unten^[w].rgbGreen := (RGBA_Oben^[w].rgbReserved * (RGBA_Oben^[w].rgbgreen - RGBA_Unten^[w].rgbGreen) shr 8 + RGBA_Unten^[w].rgbGreen);
         RGBA_Unten^[w].rgbBlue := (RGBA_Oben^[w].rgbReserved * (RGBA_Oben^[w].rgbBlue - RGBA_Unten^[w].rgbBlue) shr 8 + RGBA_Unten^[w].rgbBlue);

         RGBA_Unten^[w].rgbReserved := 255;
       end;
    end;
   end;
end;

procedure Draw32BitToBitmapnew(const BitOben: TBitmap; BitUnten: TBitmap); // Pointer-Addition
var
  h,w: Integer;
  RGBA_Unten, RGBA_Oben: ^TRGBQuad; // pRGBALine;
begin
  For h := 0 to BitUnten.Height-1 do begin
    RGBA_Unten := BitUnten.ScanLine[h];
    RGBA_Oben := BitOben.ScanLine[h];

    For w:= 0 to BitUnten.Width-1 do begin
      if RGBA_Oben^.rgbReserved = 0 then begin
        // unten bleibt
      end else begin
        RGBA_Unten^.rgbBlue := ((RGBA_Oben^.rgbReserved * (RGBA_Oben^.rgbBlue -  RGBA_Unten^.rgbBlue)) shr 8 + RGBA_Unten^.rgbBlue);
        RGBA_Unten^.rgbGreen := ((RGBA_Oben^.rgbReserved * (RGBA_Oben^.rgbgreen - RGBA_Unten^.rgbGreen)) shr 8 + RGBA_Unten^.rgbGreen);
        RGBA_Unten^.rgbred  := ((RGBA_Oben^.rgbReserved * (RGBA_Oben^.rgbred -   RGBA_Unten^.rgbred))  shr 8 + RGBA_Unten^.rgbred);

        RGBA_Unten^.rgbReserved := 255;
      end;
      inc (RGBA_Unten);
      inc (RGBA_oben);
   end;
  end;
end;

Mavarik 27. Nov 2014 11:20

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
Zitat:

Zitat von Harry Stahl (Beitrag 1281237)
* Im vorliegenden Fall bringt auch eine Parallelisierung nichts, da der Verwaltungsaufwand
größer ist, als der Gewinn durch mehrere Prozessorkerne

Das kann ich eigentlich kaum glauben.

Vielleicht über die Parallel FOR ok, kann ich nicht nachvollziehen. Aber einen optimierten thread mit entsprechendem vorbereiteten Prozessen müsste schneller sein.

Können wir am Sa. ja mit unserem Thread König, emm Kaiser, ich meine Kaisler diskutieren. :stupid:

Mavarik

manfred42 27. Nov 2014 21:08

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
Hallo, ich bin hier neu hinzugestoßen und versuche mich am Beschleunigen.
Zuförderst ein paar Fragen zu den Details:
● Ist der Nenner in der Formel 255 oder 256? Bei 255 sind einige Klimmzüge nötig
● Ist Round vonnöten, oder dient es nur zur Float-Integer-Konvertierung?
● Von welcher WEB-Site kann ich 2 repräsentative 32-bittige Bitmaps absaugen?

Da ich schon einmal mit MMX-Befehlen Antialiasing veranstaltet habe,
würde ich mich gern an der Bitmap-Verrechnung versuchen.

MfG Manfred(19)42

Harry Stahl 27. Nov 2014 23:26

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
Zitat:

Zitat von Mavarik (Beitrag 1281300)
Zitat:

Zitat von Harry Stahl (Beitrag 1281237)
* Im vorliegenden Fall bringt auch eine Parallelisierung nichts, da der Verwaltungsaufwand
größer ist, als der Gewinn durch mehrere Prozessorkerne

Das kann ich eigentlich kaum glauben.

Vielleicht über die Parallel FOR ok, kann ich nicht nachvollziehen. Aber einen optimierten thread mit entsprechendem vorbereiteten Prozessen müsste schneller sein.

Können wir am Sa. ja mit unserem Thread König, emm Kaiser, ich meine Kaisler diskutieren. :stupid:

Mavarik

Hängt eben davon ab, was die Funktion macht. Wenn die nur wenige Befehle ausführen muss, sind die Aktionen, welche für die Threadverwaltung benötigt werden, zeitintensiver, als die Abarbeitung der wenigen Befehle. Das gilt sowohl für Parallel FOR und für Parallel Task.

Muss man quasi im Einzelfall testen, wo was schneller ist.

Harry Stahl 27. Nov 2014 23:31

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
Zitat:

Zitat von manfred42 (Beitrag 1281403)
Hallo, ich bin hier neu hinzugestoßen und versuche mich am Beschleunigen.
Zuförderst ein paar Fragen zu den Details:
● Ist der Nenner in der Formel 255 oder 256? Bei 255 sind einige Klimmzüge nötig
● Ist Round vonnöten, oder dient es nur zur Float-Integer-Konvertierung?
● Von welcher WEB-Site kann ich 2 repräsentative 32-bittige Bitmaps absaugen?

Da ich schon einmal mit MMX-Befehlen Antialiasing veranstaltet habe,
würde ich mich gern an der Bitmap-Verrechnung versuchen.

MfG Manfred(19)42

256 wäre wohl richtig.
Round wäre gut, zur Not aber auch ohne.
Erstelle Dir doch einfach selber 2 passende Bitmaps, hier die Größe und Bedingungen, mit denen ich hier teste:

- 3548x2558 Pixel, 32 Bit-Format.
- Das untere Bitmap hat einen Verlaufsuntergrund, das obere Bitmap hat zwei rechteckige Bereiche (jeweils 340 x 2300), die zu 100% transparent sind.

manfred42 28. Nov 2014 00:52

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
Danke für den Ratschlag (um diese Uhrzeit)!
Ich hatte mit 2 kleineren Bitmaps experimentiert und werde
dem Ratschlag folgen.
Jetzt habe die letzte (Pointer)-Version der Prozedur probiert.
Sie läuft sehr flott und schreit förmlich nach dem Einsatz von
MMX-Code.
An einer Thread-Version will ich mich später versuchen. Ich
habe da schon eine Idee. Bei Threads bin ich aber nicht sehr
sattelfest. Auf meinem DualCore-Notebook für Rentner wird es
nicht viel bringen
Wenn ich mit den technischen Rahmenbedingungen der DP
mehr vertraut bin, werde ich auch Codepassagen präsentieren.
Gute Nacht!

Amateurprofi 28. Nov 2014 01:10

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
Delphi-Quellcode:
PROCEDURE Blend32(Source,Dest:pRGBQuad; Width,Height,OOffset,UOffset:Integer);
const
   RegSize=4;
   WOffs=6*RegSize; HOffs=12*RegSize; OOffs=11*RegSize; UOffs=10*RegSize;
asm
         pushad
         mov     ebp,ecx               // Width
         lea     esi,[eax+ebp*4]       // Source
         lea     edi,[edx+ebp*4]       // Dest
         neg     ebp
         mov     [esp+WOffs],ebp
@Loop:  mov     bl,[esi+ebp*4].TRgbQuad.rgbReserved // S.Reserved
         test    bl,bl
         jz      @Next
         // Red
         mov     al,[esi+ebp*4].TRgbQuad.rgbRed     // S.Red
         mov     cl,[edi+ebp*4].TRgbQuad.rgbRed     // D.Red
         sub     al,cl                              // S.Red-D.Red
         imul    bl                                 // (S.Red-D.Red)*S.Reserved
         add     ah,cl                              // ((S.Red-D.Red)*S.Reserved) shr 8 + D.Red
         mov     dx,ax
         // Green
         mov     al,[esi+ebp*4].TRgbQuad.rgbGreen   // S.Green
         mov     cl,[edi+ebp*4].TRgbQuad.rgbGreen   // D.Green
         sub     al,cl                              // S.Green-D.Green
         imul    bl                                 // (S.Green-D.Green)*S.Reserved
         mov     dl,ah                              // ((S.Green-D.Green)*S.Reserved) shr 8
         add     dl,cl                              // ((S.Green-D.Green)*S.Reserved) shr 8 + D.Green
         shl     edx,8
         // Blue
         mov     al,[esi+ebp*4].TRgbQuad.rgbBlue    // S.Blue
         mov     cl,[edi+ebp*4].TRgbQuad.rgbBlue    // D.Blue
         sub     al,cl                              // S.Blue-D.Blue
         imul    bl                                 // (S.Blue-D.Blue)*S.Reserved
         mov     dl,ah                              // ((S.Blue-D.Blue)*S.Reserved) shr 8
         add     dl,cl                              // ((S.Blue-D.Blue)*S.Reserved) shr 8 + D.Blue
         // Reserved
         or      edx,$FF000000
         mov     [edi+ebp*4],edx
         add     ebp,1
         jl      @Loop
         // Nächste Zeile
@Next:  add     esi,[esp+OOffs]
         add     edi,[esp+UOffs]
         mov     ebp,[esp+WOffs]
         sub     [esp+HOffs],1
         jnz     @Loop
@End:   popad
end;
Delphi-Quellcode:
PROCEDURE AsmDraw32BitToBitmap(Source,Dest:TBitmap);
resourcestring
   sWidthDifferent='Bitmaps haben unterschiedliche Breiten';
   sHeightDifferent='Bitmaps haben unterschiedliche Höhen';
   sZeroWidth='Breite der Bitmaps ist 0';
   sLessTwoLines='Höhe der Bitmaps ist < 2';
   sSourceNone32Bit='Source ist keine 32 Bit Bitmap';
   sDestNone32Bit='Dest ist keine 32 Bit Bitmap';
var PSource,PDest:pRGBQuad; W,H,SOffset,DOffset:Integer;
begin
   W:=Source.Width;
   H:=Source.Height;
   if Dest.Width<>W then raise Exception.Create(sWidthDifferent);
   if Dest.Height<>H then raise Exception.Create(sHeightDifferent);
   if W<1 then raise Exception.Create(sZeroWidth);
   if H<2 then raise Exception.Create(sLessTwoLines);
   if Source.PixelFormat<>pf32bit then raise Exception.Create(sSourceNone32Bit);
   if Dest.PixelFormat<>pf32bit then raise Exception.Create(sDestNone32Bit);
   PSource:=Source.ScanLine[0];
   SOffset:=NativeInt(Source.ScanLine[1])-NativeInt(PSource);
   PDest:=Dest.ScanLine[0];
   DOffset:=NativeInt(Dest.ScanLine[1])-NativeInt(PDest);
   Blend32(PSource,PDest,W,H,SOffset,DOffset);
end;

hanvas 28. Nov 2014 08:44

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
Zitat:

Zitat von Harry Stahl (Beitrag 1281237)
Um die bisherigen Ergebnisse zusammenzufassen:

* Im vorliegenden Fall bringt auch eine Parallelisierung nichts, da der Verwaltungsaufwand
größer ist, als der Gewinn durch mehrere Prozessorkerne

Dann müsste man sehen wo der Break-Even ist. Mann könnte z.B. das Bild in 2 Hälften unterteilen und je eine in einem Thread abarbeiten und so die Arbeit in größeren Brocken (und damit einem besseren Verhältnis zum Verwaltungsaufwand) auf zwei Threads auslagern.

Wie an anderer Stelle schon dargestellt sollte die Implementierung mit Hilfe von SIMD Befehlen mehr bringen. Wenn Du dabei lieber mit Pascal als mit Assembler arbeitest, dann schau Dir doch mal Vector-Pascal :

http://sourceforge.net/projects/vectorpascalcom/
http://www.dcs.gla.ac.uk/~wpc/report...index/x25.html

an. Ist zwar schon einige Zeit her das ich damit gespielt habe, aber damals konnte ich damit eine DLL erstellen und die Funktionen in Delphi einbinden und für solche Probleme wie Deines war das Teil ideal.


hth

HaJoe


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:21 Uhr.
Seite 6 von 8   « Erste     456 78      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz