Delphi-PRAXiS
Seite 2 von 8     12 34     Letzte »    

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)

Harry Stahl 22. Nov 2014 11:34

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
Selbst dieser Versuch, einen lokalen TRGBQuad zu verwenden (cu- und co-Variablen), führt bei 5 Durchläufen, bei einem Bitmap von ca. 3500x2500 Pixel zu 300 MS mehr Zeit:

Delphi-Quellcode:
procedure Draw32BitToBitmapNew(const BitOben: TBitmap; BitUnten: TBitmap);
var
   h,w,i: Integer;
   RGBA_Unten, RGBA_Oben: pRGBALine;
   cu, co : TRGBQuad;
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
         cu := RGBA_Unten^[w];
         co := RGBA_Oben^[w];

         i := Round (cu.rgbBlue - ((cu.rgbBlue - co.rgbBlue) / 255 * co.rgbReserved));
         if i < 0 then RGBA_Unten^[w].rgbBlue := 0 else if i > 255 then RGBA_Unten^[w].rgbBlue := 255 else RGBA_Unten^[w].rgbBlue := i;

         i := Round (cu.rgbGreen - ((cu.rgbGreen - RGBA_Oben^[w].rgbGreen) / 255 * co.rgbReserved));
         if i < 0 then RGBA_Unten^[w].rgbGreen := 0 else if i > 255 then RGBA_Unten^[w].rgbGreen := 255 else RGBA_Unten^[w].rgbGreen := i;

         i := Round (cu.rgbRed - ((cu.rgbRed - co.rgbRed) / 255 * co.rgbReserved));
         if i < 0 then RGBA_Unten^[w].rgbRed := 0 else if i > 255 then RGBA_Unten^[w].rgbRed := 255 else RGBA_Unten^[w].rgbRed := i;

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

Harry Stahl 22. Nov 2014 11:48

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

Zitat von mensch72 (Beitrag 1280733)
Die hier oft verwendete "255" finde ich nicht ganz so dolle, denn 0..255 sind 256 Werte, also setze man doch lieber alle "0..255" Werte mit 256 ins Verhältnis, dann gibt es auch keine Resultate > 255... :)

Was meinst Du hiermit genau?

Ich vermute mal, eine x in 0..255 Prüfung braucht mehr Zeit und ich weiß dann immer noch nicht, ob x evtl. kleiner als 0 (dann schwarz) oder größer 255 ist (dann weiß).

Jens01 22. Nov 2014 11:50

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
Schon mal bei/mit Graphics32 versucht?!

himitsu 22. Nov 2014 12:00

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
länger:

Ist ein bissl erschreckend, aber liegt auch an deiner Speicherverwaltung. (zuviele ungünstig liegende Variablen)
Integer-Operationen werden in den CPU-Registern (EAX usw.) durchgeführt.
Die Fließkommaoperationen in den FPU-Registern, wobei EAX und Co. frei bleibt.

Das Selbe würde dann auch bei den Streaming-Registern auftreten.

Und warum eigentlich ständig
Delphi-Quellcode:
RGBA_Unten^[w]
und nicht Anfangs mal in eine Variable?

mensch72 22. Nov 2014 12:21

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
Ich verwende "/256" statt "/255".

MulDiv ist live wegen der internen multiplen 32Bit über Int64 Logik Langsamer als aktuelle FPU Nutzung, aber mit ging es ums erkennen des Prinzips!

wenn aus "Round (RGBA_Unten^[w].rgbBlue - ((RGBA_Unten^[w].rgbBlue - RGBA_Oben^[w].rgbBlue) / 255 * RGBA_Oben^[w].rgbReserved));"
besser "RGBA_Unten^[w].rgbBlue - ((RGBA_Unten^[w].rgbBlue - RGBA_Oben^[w].rgbBlue) * RGBA_Oben^[w].rgbReserved) div 255; //<div 256> oder besser <shr 8>;" wird...
also geht das auch in 32Bit(Integer) ohne Muldiv völlig ohne Genauigkeitsverlust, weil eben ohne Informationsverlust erst multipliziert und dann dividiert wird.

Nochmal im Detail:
- du hast zwei 8Bit (Farb)Werte, die können multipliziert max. einen 16Bit Wert ergeben(0.65535), welcher Locker in eine 32 Bit passt
- ein "SHR 8" ist minimal schneller wie ein "DIV 256"
- mit glatten 2er Potenzen zu rechnen schadet nie

Also:
Du hast 2 Farbwerte welche du multiplizierst und fix wieder durch 255teislt(oder 256 bzw. um 8 rechts schiebst)... das geht, ist aber per möglicher Tabelle 1 aus 65536(2^16) im Indexbereich von 0.65535 mit vor berechneten Einträgen am schnellsten:

RelColResult:=RelColTable[(ColValueA shl 8)+ColValueB];
("RelColTable" sein ein Array 0..65535 of BYTE)



(Ich rechne das irgendwie anders, deshalb erschließt sich mir der Sinn deine nachfolgenden Abfrage aus ">255" nicht, denn mir fällt kein Wertepaar der 2 Ausgangsfarben ein, wo das Ergebnis >255 sein kann... Nur weil Round auch "aufrundet" passiert dir das eventuell... Ich denke wenn du Round durch Floor ersetzt kannst du dir das "if" sparen und Kommafarbwerte gibt es bei 8Bit 0.255 eh nicht :) )

Harry Stahl 22. Nov 2014 12:42

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
wenn ich Round durch Floor ersetze, dauert es 3 mal so lang...

Harry Stahl 22. Nov 2014 13:08

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
Ich glaube, Du könntest Recht haben, mit der Vermutung, dass es eigentlich nie größer als 255 werden kann, da ja von einem Ausgangswert, der nie größer als 255 sein kann, immer etwas abgezogen wird. Also muss man in der Tat nur den <0 Fall berücksichtigen.

Auch /256 statt /255 müsste richtig sein, da es ja um die Anzahl der möglichen Farbabstufungen geht.

Super!!

Das umgesetzt werden laut AQTime pro Aufruf der Funktion ca. 20 MS gespart:-D

Das Ding sieht jetzt also so aus:

Delphi-Quellcode:
procedure Draw32BitToBitmapNew(const BitOben: TBitmap; BitUnten: TBitmap);
var
   h,w,i: 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
         i := Round (RGBA_Unten^[w].rgbBlue - ((RGBA_Unten^[w].rgbBlue - RGBA_Oben^[w].rgbBlue) / 256 * RGBA_Oben^[w].rgbReserved));
         if i < 0 then RGBA_Unten^[w].rgbBlue := 0 else RGBA_Unten^[w].rgbBlue := i;

         i := Round (RGBA_Unten^[w].rgbGreen - ((RGBA_Unten^[w].rgbGreen - RGBA_Oben^[w].rgbGreen) / 256 * RGBA_Oben^[w].rgbReserved));
         if i < 0 then RGBA_Unten^[w].rgbGreen := 0 else RGBA_Unten^[w].rgbGreen := i;

         i := Round (RGBA_Unten^[w].rgbRed - ((RGBA_Unten^[w].rgbRed - RGBA_Oben^[w].rgbRed) / 256 * RGBA_Oben^[w].rgbReserved));
         if i < 0 then RGBA_Unten^[w].rgbRed := 0 else RGBA_Unten^[w].rgbRed := i;

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

Harry Stahl 22. Nov 2014 14:03

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
Jetzt noch mal Ergebnisse bei Parallelisierung des ganzen mit TParallel:

Auf 2-Kern-Rechner von ca. 300 MS auf 150
Auf 4-Kern-Rechner von ca. 300 MS auf 100
Auf 6-Kern-Rechner von ca. 300 MS auf 56

Also fast 6 mal so schnell!!

Jetzt lohnt sich das mit den Kernen so richtig, insbesondere bei den rechenintensiven Grafikbearbeitungsaufgaben eine echt hilfreiche Sache.

Also was das angeht, bringt XE7 voll den Turbo!!:thumb:

Mein nächster Entwicklungsrechner wird also mit mindestens 6 Kernen kommen...

mensch72 22. Nov 2014 16:23

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
Eine Bitte:
mach dir mal für mich die Mühe und "messe" die Zeiten noch für diese 2 Varianten:

i := RGBA_Unten^[w].rgbBlue - (((Int(RGBA_Unten^[w].rgbBlue - RGBA_Oben^[w].rgbBlue) * Int(RGBA_Oben^[w].rgbReserved)) div 256);
und
i := RGBA_Unten^[w].rgbBlue - (((Int(RGBA_Unten^[w].rgbBlue - RGBA_Oben^[w].rgbBlue) * Int(RGBA_Oben^[w].rgbReserved)) shr 8);

(für je alle 3 Farben halt)

Das wird genauso exakt und "müsste" schneller sein... Das "div 256" und "shr 8" könnte sogar der Compiler optimieren, wenn es keinen Unterschied machen sollte.

Bin gespannt auf deine Ergebnisse:)

Harry Stahl 22. Nov 2014 16:32

AW: Geht das noch schneller? - Bitmap-Verrechnung
 
Mache ich doch gerne. Rückmeldung zu Variante 1+2:

E2015: Operator ist auf diesen Operandentyp nicht anwendbar.


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:36 Uhr.
Seite 2 von 8     12 34     Letzte »    

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