DNG-Viewer soll ein Programm werden, mit dem man RAW-Bilder öffnen und bearbeiten kann. Das Ergebnis soll in einem üblichen Format wie z. B. Jpeg gespeichert werden. Das Programm soll auf Smartphones und Tablet PCs mit dem Betriebsystem Android laufen.
Die Oberfläche ist dabei in Java programmiert. Die eigentliche Funktionalität ist in C++ programmiert. Damit der C++ Code sich kompilieren lässt, muss man auf einige C++ Standards verzichten. Der Code darf z. B. keine C++ Exception enthalten. Die Schnittstelle JNI verbindet dann denn Java Programmteil mit dem C++ Programmteil.
Es gibt einen neuen Gehaltsrechner für 2012. Anstelle einer Android App, die nur mit dem Android Betriebssystem funktioniert, ist das Progam nun eine Web App, die in den meisten Browsern funktionieren sollte. Für die Richtigkeit des Ergebnisses gibt es keine Gewähr.
Die Rechenleistung von ARM Prozessoren ist schwach. Um ein Programm zu schreiben für die Bildverarbeitung müsste ein solches Programm in Assembler programmiert werden, zum Beispiel um Prozessoreinheiten wie Neon optimal zu nutzen. Dieses Vorgehen hätte zur Folge, dass ein solches Programm nur auf einen speziellen Prozessor läuft. Damit das Programm auf möglichst vielen Geräten läuft und eine akzeptable Laufzeit erreicht, habe ich begonnen Teile in OpenCL zu programmieren. OpenCL wird zurzeit nur auf Desktop Rechnern unterstützt. Hersteller von ARM Prozessoren entwickeln aber auch schon an Prozessoren mit OpenCL Unterstützung zum Beispiel Texas Instruments mit dem Omap 5 Prozessor, ARM selbst mit dem Mali-T604 und von NVIDIA werden solche Prozessoren auch erwartet.
Drei Funktionen meines Programms wurden in OpenCL neue programmiert. Einmal eine Funktion zur linearen Farbtransformation, eine Funktion zur Gammakorrektur und den Demosaic Algorithmus. Verglichen wurde das Programm mit der CPU Core i5 430m und einer AMD GPU Mobility Radeon HD 5650m (Reedwood). Das Programm wurde mit Visual Studio 2010 entwickelt. Folgende Compiler Optimierungen /O2 /Ob2 /Oi /Ot /Oy- /GL wurden verwendet, für den Vergleich ist das Programm für die x64 Plattform übersetzt worden. Als Ausgangspunkt des Vergleichs nahm ich die alten Funktionen, die mit pThreads zur Multicore Unterstützung programmiert wurden. Das OpenCL Programm konnte auf zwei Laufzeitumgebungen laufen, entweder mit der AMD-Laufzeitumgebung, die sowohl CPU als auch GPU unterstützt oder mit der Intel Laufzeitumgebung, die nur die CPU unterstützt.
In der unteren Tabelle sind die Laufzeiten der Funktionen angegeben. Bei den kleineren Funktionen mul_matrix und gamma_correction war die erste OpenCL Version ein voller Erfolg. Beide Funktionen benötigten nur noch ein Zehntel der Zeit. Enttäuschend war die Funktion demosaik_AHD, sie benötigte die doppelte Zeit. Eine zweite Version zeigte wesentlich bessere Ergebnisse. Die erste Version verwendet wenig lokalen Speicher aber viele Register, die zweite Version verwendet weniger Register aber mehr globalen Speicher. Die zweite Version besteht aus vielen kleinen Funktionen anstatt einer großen. Den Erfolg kann man deutlich in der Tabelle erkennen. Die zweite Version verwendet keinen lokalen Speicher, eine dritte Version soll mehr lokalen Speicher verwenden. An der gamma_correction Funktion kann man sehen, dass ein OpenCL Programm an eine CPU oder GPU angepasst werden kann. Während die reine CPU-Version eine look-up-table verwendet, berechnet die OpenCL Version die Werte. Was dazu führt, dass die OpenCL CPU Version noch langsamer läuft. Zum Vergleich gibt es die Funktion nochmal in OpenCL mit einer look-up-table, was zu wesentlich besseren Laufzeiten führte für die OpenCL CPU Version, die GPU-Version wurde dramatisch langsamer.
demosaik_AHD | mul_matrix | gamma_correction | |
---|---|---|---|
CPU x64 pthread | 1,185 sec | 0,141 | 0,100 |
Version 1 AMD GPU OpenCL | 2,385 sec | 0,013 | 0,010 |
Version 1 AMD CPU OpenCL | 2,193 sec | 0,063 | 1,294 oder mit lut 0,047 sec |
Version 2 AMD CPU OpenCL | 5,122 sec | 0,054 | 0,939 sec |
Version 2 AMD GPU OpenCL | 0,923 sec | 0,012 | 0,010 sec |
Version 2 Intel CPU OpenCL | 1,519 sec | 0,105 | 0,292 sec |
Die nächste Abbildung zeigt, wo sehr viel Zeit bei der GPU verloren geht. Nämlich bei der Übertragung der Daten in den Speicher der Grafikkarte. Der blaue Bereich zeigt die Zeit für den Datentransfer an und der grüne Bereich die Zeit für die Berechnung. Theoretisch würde das Programm einen parallelen Ablauf von Übertragen der Daten und berechnen der vorhandenen Daten erlauben. Leider unterstützen die AMD Treiber dieses Feature nicht.
Eine lauffähige Version mit GUI kann hier heruntergeladen werden. Es handelt sich dabei um einen sehr frühen Prototyp, der nicht jeden Fehler abfängt. Falls beim Start bemängelt wird, dass die Datei msvcr100.dll nicht gefunden wird, muss man das Microsoft Visual C++ 2010 Redistributable Package (x86) von Microsoft installieren. Außerdem ist es notwendig Hardware und Treiber zu installieren die OpenCL 1.1 unterstützen, entweder von Nvidia, AMD oder Intel. Bei mir lief die Treiberversion Catalyst 11.9 von AMD und alle Intel Treiber problemlos, Produkte von Nvidia habe ich nicht getestet.
Den Source-Code werde ich bald als OpenSource zum Download anbitten.
Der AHD-Demosaicing Algorithmus ist implementiert. In der nächsten Tabelle kann man überblicken welchen Vorteil man von der Verwendung von Threads hat.
|
AMD BE-2350 |
Intel Core i5 m430 |
1 Thread |
3.17 sec |
3,76 sec |
1 Thread / 1 Thread |
1 |
1 |
2 Thread |
2,01 sec |
2.12 sec |
1 Thread / 2 Thread |
1,57 |
1,77 |
3 Thread |
1,97 sec |
1,94 sec |
1 Thread / 3 Thread |
1,6 |
1,93 |
4 Thread |
|
1,84 sec |
1 Thread / 4 Thread |
|
2,04 |
Der Sourcecode kann hier heruntergeladen werden. Um das Programm zu erstellen Importiert man es am besten in Eclipse. Das CDT-Plugin und das QT-Plugin müssen in Eclipse installiert sein.
Das Programm wurde um einen Bild-Browser erweitert. Die MobilRaw-Library bekam dazu die Fähigkeit exif Information auszulesen. Der Prototyp ist in dem Video unten zusehen.
Als nächster Schritt soll ein besserer Demosaic-Algorithmus programmiert werden. Als Erstes soll der AHD-Verfahren programmiert werden wie ihn auch DCRAW verwendet. Ziele sind, dass die Funktion leicht an die SIMD-Einheit moderner Prozessoren angepasst werden kann und dass die Funktion Threads unterstützt.
Die ersten Versuche auf dem vom Android SDK mitgelieferten Emulator waren ehr ernüchtern. Nun habe ich mir für weitere Tests ein Beagleboard besorgt. Das Beagleboard verfügt über einen Cortex A8 Prozessor mit 720 MHz. Trotz dieses ehr schwachen Prozessors im Vergleich mit den heute angebotenen Handys, die mit Prozessoren um die 1000 MHz Angebotenen werden oder sogar mit Dual-Core Prozessoren, waren die ersten Versuche damit sehr viel versprechend.
Zum Testen habe ich auf dem Beagleboard Ubuntu Maverick installiert. Beim ersten Versuch brauchte mein Programm ungefähr 15 sec zum Öffnen eines Bildes. Was natürlich immer noch nicht gut ist, aber schon besser als 1:30 Minute. Durch Setzen der Compileroptimierung
dauerte das Öffnen der Bilder nur noch 9 – 10 sec. Ich habe die Funktion mit der längsten Laufzeit mit gprof ausfindig gemacht und die noch weiter optimiert. Zur Optimierung habe ich die SIMD-Einheit Neon des Prozessors benutzt und die Funktion nochmal in Assembler neu programmiert. Die komplette Laufzeit konnte dann von 9sec auf 6sec verringert werden.
Zurzeit gibt es einen Prototyp der eine DNG Datei öffnet und aus den Raw Daten ein Bild berechnet. Es fehlt noch ein Dateibrowser zur Auswahl einer Datei und ein Dateibrowser zur Speicherung der Datei. Der Prototyp zeigt schon mal, dass das Programm stark an die Hardware angepasst werden muss. Das unten stehende Video zeigt wie viel Zeit der Simulator benötigt um die Datei zu öffnen. Der Simulator läuft auf einem Intel Core i5 430m Prozessor mit 2.26 GHz.