Überblick
Ich habe einen Bildpuffer, den ich in ein anderes Format konvertieren muss. Der Ursprungsbildpuffer besteht aus vier Kanälen, 8 Bit pro Kanal, Alpha, Rot, Grün und Blau. Der Zielpuffer besteht aus drei Kanälen, 8 Bit pro Kanal, Blau, Grün und Rot.
Die Brute-Force-Methode lautet also:
// Assume a 32 x 32 pixel image
#define IMAGESIZE (32*32)
typedef struct{ UInt8 Alpha; UInt8 Red; UInt8 Green; UInt8 Blue; } ARGB;
typedef struct{ UInt8 Blue; UInt8 Green; UInt8 Red; } BGR;
ARGB orig[IMAGESIZE];
BGR dest[IMAGESIZE];
for(x = 0; x < IMAGESIZE; x++)
{
dest[x].Red = orig[x].Red;
dest[x].Green = orig[x].Green;
dest[x].Blue = orig[x].Blue;
}
Allerdings brauche ich mehr Geschwindigkeit, als eine Schleife und drei Byte-Kopien bieten. Ich hoffe, es gibt ein paar Tricks, mit denen ich die Anzahl der Lese- und Schreibvorgänge im Speicher reduzieren kann, da ich auf einem 32-Bit-Computer laufe.
zusätzliche Information
Jedes Bild ist ein Vielfaches von mindestens 4 Pixeln. Wir könnten also 16 ARGB-Bytes adressieren und sie in 12 RGB-Bytes pro Schleife verschieben. Vielleicht kann diese Tatsache genutzt werden, um die Dinge zu beschleunigen, zumal sie schön in 32-Bit-Grenzen fällt.
Ich habe Zugriff auf OpenCL – und während dies das Verschieben des gesamten Puffers in den GPU-Speicher und das anschließende Verschieben des Ergebnisses wieder hinaus erfordert, sind die Tatsache, dass OpenCL gleichzeitig an vielen Teilen des Bildes arbeiten kann, und die Tatsache, dass große Speicherblockbewegungen tatsächlich erfolgen ziemlich effizient kann dies zu einer lohnenden Erkundung machen.
Während ich oben das Beispiel kleiner Puffer gegeben habe, verschiebe ich wirklich HD-Video (1920 x 1080) und manchmal größere, meistens kleinere Puffer, so dass eine 32 x 32-Situation trivial sein mag, das Kopieren von 8,3 MB Bilddaten Byte für Byte ist es jedoch wirklich, wirklich schlecht.
Auf Intel-Prozessoren (Core 2 und höher) ausgeführt, und daher gibt es Streaming- und Datenverarbeitungsbefehle, von denen ich weiß, dass sie existieren, von denen ich aber nichts weiß – vielleicht wären Hinweise darauf, wo Sie nach speziellen Anweisungen zur Datenverarbeitung suchen sollten, gut.
Dies geht in eine OS X-Anwendung, und ich verwende XCode 4. Wenn die Assemblierung schmerzlos und der offensichtliche Weg ist, kann ich diesen Weg gehen, aber da ich es bei diesem Setup noch nicht getan habe, bin ich vorsichtig zu viel Zeit darin versinken.
Pseudocode ist in Ordnung – ich suche keine vollständige Lösung, nur den Algorithmus und eine Erklärung für alle Tricks, die möglicherweise nicht sofort klar sind.
richtet der Compiler BGR an Dword aus?
– Marinara
24. Juli 2011 um 1:03 Uhr
@marinara Nein, es ist Byte-ausgerichtet.
– Adam Davis
24. Juli 2011 um 1:11 Uhr
Es sollte keinen Sinn machen, die GPU dafür zu verwenden, es sei denn, die Daten kommen von dort in das System. Sie sollten in der Lage sein, den Speicherbus mit der CPU zu sättigen.
– Stephan Eggermont
16. August 2011 um 15:46 Uhr
Ich habe mit niemandes Code gespielt, aber AFAICT hat niemand die Möglichkeit des Äquivalents von erwähnt
for(x = 0; x < IMAGESIZE; x++) { dest[x].Red = orig[x].Red; } for(x = 0; x < IMAGESIZE; x++) { dest[x].Green = orig[x].Green; } for(x = 0; x < IMAGESIZE; x++) { dest[x].Blue = orig[x].Blue; }
. Überholen in diesem Fall die einfacheren Loops das Bit Twiddling?– Mark Hurd
24. Januar 2015 um 13:01 Uhr