GPU-Implementation von “Neural Gas Principal Component Analysis”
GPU-Implementation von “Neural Gas Principal Component Analysis”
GPU-Implementation von “Neural Gas Principal Component Analysis”
Sie wollen auch ein ePaper? Erhöhen Sie die Reichweite Ihrer Titel.
YUMPU macht aus Druck-PDFs automatisch weboptimierte ePaper, die Google liebt.
Universität Bielefeld<br />
Technische Fakultät<br />
AG Technische Informatik<br />
Bachelorarbeit<br />
<strong>GPU</strong>-<strong>Implementation</strong> <strong>von</strong> <strong>“Neural</strong> <strong>Gas</strong><br />
<strong>Principal</strong> <strong>Component</strong> <strong>Analysis”</strong> mit<br />
blockweisem Ansatz<br />
Christian Menßen<br />
26. September 2012<br />
im Studiengang<br />
Kognitive Informatik<br />
Betreuer<br />
Dr.-Ing. Wolfram Schenck
Diese Bachelorarbeit wurde <strong>von</strong> Dr.-Ing. Wolfram Schenck betreut und begutachtet.<br />
Der zweite Gutachter war Dipl.-Inform. Alexander Kaiser.<br />
Ich danke meinem Betreuer Dr.-Ing. Wolfram Schenck für das interessante Thema und<br />
die Unterstützung während der Bearbeitung.<br />
2 Universität Bielefeld, AG Technische Informatik
Kurzbeschreibung<br />
Die Verwendung der Grafikkarte als universelle Berechnungseinheit hat in den letzten<br />
Jahren stark zugenommen. Viele rechenintensive Anwendungen wie z.B. physikalische<br />
Simulationen, Bild- und Videoverarbeitung oder die automatische Spracherkennung<br />
können durch den Einsatz <strong>von</strong> Grafikkarten signifikant beschleunigt werden. In dieser<br />
Bachelorarbeit wird gezeigt, wie ein künstliches neuronales Netzwerk (genauer: ein<br />
Neural-<strong>Gas</strong>-Netzwerk mit lokaler Hauptkomponentenanalyse) mit Hilfe der Programmierschnittstelle<br />
OpenCL auf einem Grafikprozessor trainiert werden kann, wodurch<br />
eine deutliche Geschwindigkeitssteigerung erreicht wird.<br />
Universität Bielefeld, AG Technische Informatik 3
Inhaltsverzeichnis<br />
Inhaltsverzeichnis<br />
1 Einleitung 6<br />
2 Theoretische Grundlagen 7<br />
2.1 <strong>GPU</strong> Computing . . . . . . . . . . . . . . . . . . . . . . . . . . . 7<br />
2.1.1 Erreichbarer Speedup . . . . . . . . . . . . . . . . . . . . 7<br />
2.1.2 Programmierschnittstellen . . . . . . . . . . . . . . . . . . 8<br />
2.1.3 Speichermodell . . . . . . . . . . . . . . . . . . . . . . . . 8<br />
2.2 Hauptkomponentenanalyse . . . . . . . . . . . . . . . . . . . . . 8<br />
2.3 Vektorquantisierung . . . . . . . . . . . . . . . . . . . . . . . . . 9<br />
2.4 Neural <strong>Gas</strong> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9<br />
2.5 Erweiterung zu NGPCA . . . . . . . . . . . . . . . . . . . . . . . 10<br />
2.5.1 Lokale PCA . . . . . . . . . . . . . . . . . . . . . . . . . . 10<br />
2.5.2 Distanzmaß . . . . . . . . . . . . . . . . . . . . . . . . . . 11<br />
2.5.3 Training . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12<br />
2.6 Orthonormalisierung . . . . . . . . . . . . . . . . . . . . . . . . . 12<br />
3 <strong>Implementation</strong> 13<br />
3.1 Initialisierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15<br />
3.2 Distanzberechnung . . . . . . . . . . . . . . . . . . . . . . . . . . 15<br />
3.2.1 Verwendetes Potential . . . . . . . . . . . . . . . . . . . . 16<br />
3.3 Ranking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16<br />
3.3.1 Sortierverfahren . . . . . . . . . . . . . . . . . . . . . . . 16<br />
3.4 Adaptierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16<br />
3.4.1 Hauptkomponentenanalyse . . . . . . . . . . . . . . . . . 17<br />
3.4.2 Orthonormalisierung . . . . . . . . . . . . . . . . . . . . . 17<br />
3.5 Harte Vektorquantisierung . . . . . . . . . . . . . . . . . . . . . . 18<br />
3.5.1 Adaptive Anpassung der parallelen Trainingsvektoren . . 19<br />
4 Experimentelle Ergebnisse 20<br />
4.1 Hardware . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20<br />
4.2 Roboterarmsteuerung . . . . . . . . . . . . . . . . . . . . . . . . 21<br />
4.3 CT Slices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22<br />
4.4 Speedup nach gewählten Parametern . . . . . . . . . . . . . . . 23<br />
4.4.1 Anzahl der Prototypen . . . . . . . . . . . . . . . . . . . . 23<br />
4.4.2 Anzahl der Eigenwerte . . . . . . . . . . . . . . . . . . . . 24<br />
4.4.3 Verwendetes Potential . . . . . . . . . . . . . . . . . . . . 25<br />
4.5 Kernellaufzeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . 25<br />
4 Universität Bielefeld, AG Technische Informatik
Inhaltsverzeichnis<br />
5 Diskussion 27<br />
5.1 Pre-Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27<br />
5.1.1 PCA-Verfahren . . . . . . . . . . . . . . . . . . . . . . . . 27<br />
5.1.2 Orthonormalisierungsverfahren . . . . . . . . . . . . . . . 27<br />
5.1.3 <strong>Implementation</strong> einer OpenCL Matrix-Bibliothek . . . . . . 28<br />
5.2 Beurteilung der Ergebnisse . . . . . . . . . . . . . . . . . . . . . 28<br />
5.2.1 Einfluss der gewählten Parameter . . . . . . . . . . . . . 29<br />
5.2.2 Wahl der Plattform . . . . . . . . . . . . . . . . . . . . . . 31<br />
6 Ausblick 32<br />
6.1 EFORRLSA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32<br />
6.2 AVX, Nvidia Tesla, AMD Plattform . . . . . . . . . . . . . . . . . 32<br />
6.3 Orthonormalisierung . . . . . . . . . . . . . . . . . . . . . . . . . 33<br />
6.4 Adaptive Anpassung der parallelen Trainingsvektoren . . . . . . 33<br />
Literaturverzeichnis 34<br />
A Verwendete Parameter 36<br />
A.1 Roboterarmsteuerung . . . . . . . . . . . . . . . . . . . . . . . . 36<br />
A.2 CT Slices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36<br />
B Quelltexte 37<br />
C Kompilierung und Ausführung der Quelltexte 43<br />
D Verwendete Software-Bibliotheken 44<br />
E Kommandozeilenparameter 45<br />
Universität Bielefeld, AG Technische Informatik 5
1<br />
Einleitung<br />
In den letzten Jahren hat <strong>GPU</strong> Computing, also die Verwendung der Grafikkarte<br />
als universelle Berechnungseinheit, immer mehr an Bedeutung gewonnen. Moderne<br />
Grafikkarten besitzen mittlerweile ein Vielfaches der Rechenleistung aktueller Prozessoren<br />
1 , so dass sie auch für wissenschaftliche Anwendungen interessant werden.<br />
Zudem steht mit OpenCL eine Programmierschnittstelle zur Verfügung, mit der die<br />
Implementierung abstrakt zur eigentlichen Hardwareplattform stattfinden kann.<br />
Im Rahmen dieser Bachelorarbeit wurde eine <strong>GPU</strong>-Implementierung für ein Neural-<br />
<strong>Gas</strong>-Netzwerk mit lokaler <strong>Principal</strong> <strong>Component</strong> Analysis (Möller und Hoffmann,<br />
2004) erstellt. Aufgrund der Unterteilung in lokale PCAs verspricht die Umsetzung<br />
auf der Grafikkarte einen erheblichen Geschwindigkeitszuwachs, da die bei diesem<br />
Verfahren verwendeten Prototypen parallel berechnet werden können.<br />
Kapitel 2 beginnt mit einer näheren Betrachtung des <strong>GPU</strong> Computing und führt<br />
anschließend das zugrunde liegende Verfahren Neural <strong>Gas</strong> mit lokaler <strong>Principal</strong><br />
<strong>Component</strong> Analysis 2 mit den nötigen Grundlagen ein.<br />
In Kapitel 3 wird die grundlegende Struktur der Applikation erläutert, woraufhin auf die<br />
einzelnen Schritte des Lernverfahrens mit den nötigen <strong>GPU</strong>-spezifischen Anpassungen<br />
eingegangen wird.<br />
Die resultierende Geschwindigkeit der <strong>Implementation</strong> wird in Kapitel 4 anhand <strong>von</strong><br />
zwei ausgewählten Datensätzen evaluiert. Dabei wird der Speedup betrachtet, also das<br />
Verhältnis <strong>von</strong> CPU-Laufzeit zu <strong>GPU</strong>-Laufzeit.<br />
Abschließend werden in Kapitel 5 die vor dieser Bachelorarbeit durchgeführten Tests<br />
erläutert und die aus Kapitel 4 resultierenden Ergebnisse diskutiert. Einen Ausblick auf<br />
mögliche Erweiterungen und Verbesserungen gibt Kapitel 6.<br />
1 http://developer.download.nvidia.com/compute/DevZone/docs/html/C/<br />
doc/CUDA_C_Programming_Guide.pdf<br />
Datum: 03.09.2012<br />
2 Im Folgenden “NGPCA” genannt<br />
6 Universität Bielefeld, AG Technische Informatik
2<br />
Theoretische Grundlagen<br />
2.1 <strong>GPU</strong> Computing<br />
Mit <strong>GPU</strong> Computing (auch GP<strong>GPU</strong> 1 genannt) bezeichnet man die Verwendung der<br />
<strong>GPU</strong> für Berechnungen, die normalerweise auf der CPU ausgeführt werden.<br />
Im Laufe der letzten Jahre hat sich die Leistungsfähigkeit <strong>von</strong> Grafikkarten rasant<br />
entwickelt. Während moderne Prozessoren weniger als 500 GFLOPs 2 verarbeiten<br />
können, schaffen aktuelle Grafikkarten bereits über 3.000 GFLOPs 3 . Sie sind also<br />
theoretisch sehr gut zum wissenschaftlichen Rechnen geeignet. Leider lässt sich<br />
bestehende Software nicht 1:1 auf die <strong>GPU</strong> übertragen, was an der zugrunde liegenden<br />
Hardware-Architektur liegt:<br />
Während CPUs zum schnellen Abarbeiten <strong>von</strong> sequenziellen Befehlen ausgelegt sind,<br />
erreichen <strong>GPU</strong>s ihre Leistung durch starke Parallelisierung.<br />
2.1.1 Erreichbarer Speedup<br />
Sei P ∈ [0, 1] der parallelisierbare Anteil des Algorithmus, (1 − P ) der serielle Anteil<br />
und N ∈ N ∗ die Anzahl an parallelen Recheneinheiten. Dann wird der theoretische<br />
maximale Speedup S, also die erreichbare Beschleunigung, durch Amdahls Gesetz<br />
(Amdahl, 1988) beschrieben:<br />
S(N) =<br />
1<br />
(1 − P ) + P N<br />
Der Speedup wird dabei nach oben beschränkt durch:<br />
lim S(N) = 1<br />
N→∞ (1 − P )<br />
1 GP<strong>GPU</strong> = General Purpose Computation on Graphics Processing Unit<br />
2 GFLOPs = 10 9 Gleitkommaoperationen pro Sekunde<br />
3 http://developer.download.nvidia.com/compute/DevZone/docs/html/C/<br />
doc/CUDA_C_Programming_Guide.pdf<br />
Datum: 03.09.2012<br />
(2.1)<br />
(2.2)<br />
Universität Bielefeld, AG Technische Informatik 7
2 Theoretische Grundlagen<br />
Somit ist eine hohe Parallelisierbarkeit essenziell für eine schnelle Implementierung<br />
auf der Grafikkarte.<br />
2.1.2 Programmierschnittstellen<br />
Für die Programmierung <strong>von</strong> <strong>GPU</strong>s stehen einige Programmierschnittstellen zur<br />
Verfügung, <strong>von</strong> denen sich jedoch das proprietäre Nvidia CUDA C und der offene Standard<br />
OpenCL durchgesetzt haben. Der große Vorteil <strong>von</strong> OpenCL ist, dass die Implementierung<br />
abstrakt zur eigentlichen Hardwareplattform stattfindet, weshalb es auch für<br />
diese Bachelorarbeit verwendet wurde. Dem entgegen steht die etwas umständlichere<br />
Programmierung und die geringere Verbreitung im Gegensatz zu CUDA C.<br />
OpenCL<br />
OpenCL kann ein oder mehrere OpenCL-Geräte ansprechen, wobei diese <strong>von</strong> verschiedenen<br />
Treibern, den sog. Plattformen, gesteuert werden. Geschriebener Quellcode muss<br />
dabei für jede Plattform separat kompiliert werden, was jedoch zur Laufzeit geschieht.<br />
Funktionsaufrufe auf der <strong>GPU</strong> werden Kernel genannt. Kernel führen den selben Programmcode<br />
parallel auf mehreren sog. Work-Items aus, die ein-, zwei- oder dreidimensional<br />
angeordnet sein können. Work-Items werden zu Work-Groups zusammengefasst,<br />
in denen gemeinsamer lokaler Speicher (schnell, siehe Kapitel 2.1.3) und Synchronisationsmechanismen<br />
zur Verfügung stehen (Munshi, 2012).<br />
2.1.3 Speichermodell<br />
Während auf dem Host nur eine Art <strong>von</strong> Hauptspeicher vorhanden ist, besitzen Grafikkarten<br />
verschiedene Arten <strong>von</strong> Speicher mit unterschiedlichen Eigenschaften (Munshi,<br />
2012; Sanders und Kandrot, 2010):<br />
• Globaler Speicher<br />
Größter verfügbarer Speicherbereich (ca. 512 MB - 2 GB), langsamer Zugriff.<br />
• Konstanter Speicher<br />
Spezieller nur lesbarer Speicher, optimiert für schnellen parallelen Zugriff.<br />
• Lokaler Speicher<br />
Sehr schneller Speicherbereich, den sich die Work-Items einer Work-Group teilen.<br />
Typischerweise 16 KB groß.<br />
• Privater Speicher<br />
Innerhalb eines Work-Items genutzter Speicher. Wird z.B. für lokale Variablen<br />
verwendet.<br />
2.2 Hauptkomponentenanalyse<br />
<strong>Principal</strong> <strong>Component</strong> Analysis (PCA) (Jolliffe, 1986) ist ein lineares Dimensionsreduktionsverfahren.<br />
Dabei wird die Menge der Eingabevektoren X = { ⃗x 1 , ..., x⃗<br />
N } ⊂ R n auf<br />
Vektoren niedriger Dimensionalität Y = {⃗y 1 , ..., y⃗<br />
N } ⊂ R m mit m ≤ n abgebildet. Um<br />
8 Universität Bielefeld, AG Technische Informatik
2 Theoretische Grundlagen<br />
den Informationsverlust zu minimieren werden genau die Achsen weggelassen, die die<br />
geringste Varianz aufweisen. Dies sind die Eigenvektoren zu den kleinsten Eigenwerten<br />
der Kovarianzmatrix<br />
C = 1 N∑<br />
(⃗x n − ⃗µ)(⃗x n − ⃗µ) T (2.3)<br />
N<br />
mit ⃗µ = 1 N<br />
∑ N<br />
n=1 ⃗x n.<br />
n=1<br />
2.3 Vektorquantisierung<br />
Vektorquantisierung ist ein Verfahren zur Datenkompression bzw. zum Datenclustering.<br />
Hierbei werden die Eingabedaten durch k Merkmalsvektoren ausgedrückt. Die Menge<br />
der Prototypen C = {⃗c 1 , . . . , ⃗c k } wird auch als Codebuch bezeichnet. Grundsätzlich<br />
unterscheidet man 2 Arten <strong>von</strong> Vektorquantisierung:<br />
• Harte Vektorquantisierung<br />
Jedem Eingabevektor wird genau ein Merkmalsvektor zugewiesen:<br />
q : ⃗x ↦→ ⃗c i , i ∈ {1 . . . k} (2.4)<br />
• Weiche Vektorquantisierung<br />
Die Wahrscheinlichkeit p(⃗x|⃗c i ), i ∈ {1 . . . k}, dass der Eingabevektor <strong>von</strong> dem i-<br />
ten Merkmalsvektor erzeugt wurde, wird modelliert. Die Wahrscheinlichkeitsverteilung<br />
lässt sich nun als Summe der Zuordnungswahrscheinlichkeiten definieren:<br />
k∑<br />
p(⃗x) = π i p(⃗x|⃗c i ) (2.5)<br />
i=1<br />
Wobei die Mischkoeffizienten π i > 0 mit<br />
Wahrscheinlichkeiten angeben.<br />
2.4 Neural <strong>Gas</strong><br />
∑ k<br />
i=1 π i = 1 die A-priori-<br />
Der Neural-<strong>Gas</strong>-Algorithmus (NG) (Martinetz et al., 1993) kann als Generalisierung<br />
der Online-Variante des k-Means-Algorithmus verstanden werden. Im Unterschied<br />
zu k-Means ist Neural <strong>Gas</strong> jedoch ein weiches Vektorquantisierungsverfahren, da in<br />
jedem Lernschritt alle Merkmalsvektoren in Abhängigkeit <strong>von</strong> der Entfernung zum<br />
Datenpunkt angepasst werden. Hierdurch wird eine robuste und <strong>von</strong> der Initialisierung<br />
der Prototypen größtenteils unabhängige Konvergenz erreicht.<br />
Zunächst werden alle k Merkmalsvektoren mit zufällig ausgewählten Eingabevektoren<br />
initialisiert. Anschließend wird in jedem Lernschritt ein Eingabevektor ⃗x zufällig aus<br />
den Eingabedaten gezogen und der Rang<br />
r(⃗c i , ⃗x) = |{⃗c j | ‖⃗c j − ⃗x‖ < ‖⃗c i − ⃗x‖}| (2.6)<br />
jedes Prototypen ermittelt. Der Rang eines Prototypen ist also die Position des Merkmalsvektors<br />
in einer aufsteigend nach Distanz zum Eingabevektor sortierten Liste. Dieser<br />
geht direkt als Gewichtung in die Lernregel<br />
∆⃗c i = ɛ · h p (r(⃗c i , ⃗x)) · (⃗x − ⃗c i ) (2.7)<br />
Universität Bielefeld, AG Technische Informatik 9
2 Theoretische Grundlagen<br />
ein, wobei ɛ ∈ [0, 1] die Lernrate und h p (r) = e −r/p der Nachbarschaftsfaktor mit<br />
Nachbarschaftsreichweite p ist. Sowohl die Lernrate als auch der Nachbarschaftsfaktor<br />
fallen exponentiell während des Trainingsprozesses ab:<br />
ɛ(t) = ɛ init ·<br />
(<br />
ɛfinal<br />
ɛ init<br />
) t/tmax<br />
(2.8)<br />
p(t) = p init ·<br />
(<br />
pfinal<br />
p init<br />
) t/tmax<br />
(2.9)<br />
Durch das Abfallen der Trainingsparameter kann neben der “globalen Ordnung” auch<br />
gegen Ende des Lernprozesses die “lokale Ordnung” durch nur noch kleine lokale Änderungen<br />
der Merkmalsvektoren optimiert werden.<br />
2.5 Erweiterung zu NGPCA<br />
Das in dieser Bachelorarbeit auf der <strong>GPU</strong> implementierte Verfahren NGPCA (Möller<br />
und Hoffmann, 2004) basiert auf Neural <strong>Gas</strong>, erweitert es jedoch um lokale PCAs und<br />
benutzt dazu passende Distanzmaße.<br />
2.5.1 Lokale PCA<br />
Lokale PCA-Verfahren beruhen darauf, mit Hilfe eines Vektorquantisierers den Eingaberaum<br />
zu partitionieren und anschließend jede Partition durch eine PCA zu approximieren.<br />
Bei hinreichender Anzahl an Partitionen lassen sich so beliebig komplexe Mannigfaltigkeiten<br />
gut approximieren. NGPCA ist ein solches Verfahren, welches Neural<br />
<strong>Gas</strong> als Vektorquantisierer benutzt. Jede lokale PCA wird dabei zu einem Tupel, der<br />
sog. Unit U i = (⃗c i , W i , Λ i , σi 2 ) zusammengefasst. Dabei ist ⃗c i der Merkmalsvektor, W i<br />
eine Matrix mit den m größten Hauptachsen der PCA, Λ i eine Diagonalmatrix mit den<br />
entsprechenden Varianzen der Hauptachsen und σi 2 = ∑ n<br />
j=m+1 λ j die Residualvarianz,<br />
also die summierte Varianz der (n−m) Dimensionen, die nicht durch W i erfasst werden.<br />
Somit ergibt sich als neues Codebuch U = {U i , . . . , U k }<br />
Robust Recursive Least Squares Learning Algorithm (RRLSA)<br />
Robust Recursive Least Squares Learning Algorithm (RRLSA) (Ouyang et al., 2000)<br />
ist ein Verfahren zur Hauptkomponentenanalyse und kommt bei dieser Bachelorarbeit<br />
zum Einsatz.<br />
Grundlage für das Verfahren ist die Hebbsche Lernregel,<br />
∆⃗w = ɛ · y · ⃗x − λ⃗w (2.10)<br />
mit der die erste Hauptkomponente der Daten iterativ mit einem Perzeptron bestimmt<br />
werden kann. ɛ ist dabei die Lernrate, ⃗w der Gewichtsvektor, y = ⃗w T ⃗x die Ausgabe des<br />
Perzeptrons und λ⃗w ein Abklingterm, der durch λ parametrisiert wird. Dies spart die<br />
aufwändige Berechnung der Kovarianzmatrix.<br />
Um nun auch die weiteren Hauptachsen bestimmen zu können, werden Perzeptren sequenziell<br />
verknüpft.<br />
10 Universität Bielefeld, AG Technische Informatik
2 Theoretische Grundlagen<br />
Dem zweiten Perzeptron wird der Eingabevektor abzüglich der Projektion auf den ersten<br />
Gewichtsvektors als Eingabe präsentiert:<br />
⃗ξ i =<br />
{ ⃗x i = 1<br />
⃗ξ i−1 − y i−1 ⃗w i−1 i > 1<br />
(2.11)<br />
Führt man dieses als Deflation (Sanger, 1989) bezeichnete Verfahren fort, erhält man<br />
sequenziell verschaltete Neuronen, die zu den Eigenvektoren der Kovarianzmatrix konvergieren.<br />
Dieses Verfahren wird Generalized Hebbian Algorithm (Sanger, 1989) genannt.<br />
RRLSA baut auf der Deflation auf, verwendet jedoch unnormalisierte Gewichtsvektoren.<br />
Diese lassen sich rekursiv durch<br />
∆ ˜w i = ɛ( ⃗ ξ i y i − ˜w i ) (2.12)<br />
berechnen. Den Eigenwert erhält man aus der Länge des Gewichtsvektors, den Eigenvektor<br />
durch Normalisierung:<br />
λ i = ‖ ˜w i ‖, ⃗w i =<br />
˜w i<br />
‖ ˜w i ‖<br />
(2.13)<br />
Da die resultierenden Eigenvektoren nicht zwingend paarweise orthogonal zueinander<br />
sind, ist eine regelmäßige Orthonormalisierung notwendig (siehe Kapitel 2.6).<br />
2.5.2 Distanzmaß<br />
Neural <strong>Gas</strong> bestimmt den Rang eines Merkmalsvektors mit Hilfe des euklidischen Abstandes.<br />
Dadurch wird die Struktur der PCA-Unterräume jedoch nicht beachtet, weshalb<br />
es sinnvoll ist, die verwendete Metrik anzupassen. NGPCA beschreibt die normalisierte<br />
Mahalanobis-Distanz und ein volumenunabhängiges Abstandsmaß. In dieser Bachelorarbeit<br />
wurde das volumenunabhängige Abstandsmaß verwendet, da die normalisierte<br />
Mahalanobis-Distanz bei stark gestreuten Datenpunkten problematisch ist (Hoffmann,<br />
2004).<br />
Volumenunabhängiges Abstandsmaß<br />
Grundlage für das volumenabhängige Abstandsmaß ist die normalisierte Mahalanobis-<br />
Distanz. Diese basiert auf multivariaten Normalverteilungen, dessen Zentren die<br />
Merkmalsvektoren bilden. Als Achsen für den Hyperellipsoiden werden die Hauptachsen<br />
der PCA verwendet, skaliert mit der Standardabweichung der entsprechenden<br />
Richtungen. Da im Falle einer Dimensionsreduktion (m < n) nicht mehr alle Punkte<br />
korrekt zugeordnet werden können (Möller und Hoffmann, 2004), wird das Modell um<br />
den Rekonstruktionsfehler (Kambhatla und Leen, 1997) erweitert.<br />
Durch Normalisieren der Eigenwerte abhängig vom Volumen des Ellipsoiden (Hoffmann,<br />
2004) erhält man<br />
(<br />
d i (⃗x) = ⃗y i T Λ −1<br />
i ⃗y i + 1 )<br />
( ξ<br />
λ ⃗T ⃗ ∗ i ξ i − ⃗y i T ⃗y i ) V 2/n<br />
i (2.14)<br />
i<br />
mit ⃗ ξ i = ⃗x − ⃗c i , ⃗y i = W T<br />
i ⃗ ξ i , λ ∗ i =<br />
σ2 i<br />
und V = √ |Λ|.<br />
n−m<br />
Universität Bielefeld, AG Technische Informatik 11
2 Theoretische Grundlagen<br />
2.5.3 Training<br />
Das Training eines NGPCA-Netzwerkes verläuft analog zu Neural <strong>Gas</strong>. Zuerst werden<br />
die Mittelpunkte ⃗c i der Units zufällig mit Vektoren aus der Trainingsmenge initialisiert.<br />
Die Wahl der Eigenwerte ist beliebig, alle Units sollten jedoch mit den selben Eigenwerten<br />
initialisiert werden. W i kann ebenfalls frei gewählt werden, hier ist allerdings<br />
auf Orthonormalität zu achten.<br />
Während des Lernprozesses werden zufällig Trainingsvektoren ⃗x aus der Trainingsmenge<br />
gewählt und der Rang r(⃗c i , ⃗x) aller Prototypen bestimmt. Dabei wird die in Gl.<br />
2.14 definierte Metrik verwendet. Anschließend werden die Zentren der Units nach<br />
Gl. 2.7 aktualisiert, wobei die Trainingsparameter nach Gl. 2.8 und 2.9 exponentiell<br />
abfallen.<br />
Das Verfahren zur Bestimmung der lokalen PCAs ist austauschbar. In dieser Bachelorarbeit<br />
wurde RRLSA (Möller und Hoffmann, 2004) verwendet. Hierbei ist auf anschließende<br />
Orthonormalisierung <strong>von</strong> W i zu achten. Die Residualvarianz ergibt sich aus<br />
mit α = ɛ · h p (r(⃗c i , ⃗x)).<br />
∆σ 2 i = α( ⃗ ξ i T ⃗ ξi − ⃗y i T ⃗y i − σ 2 i ) (2.15)<br />
Das beschriebene Verfahren aktualisiert in jeder Iteration alle Units und wird im Folgenden<br />
Soft Clustering genannt. In einigen Szenarien kann es ausreichend sein, nur die Unit<br />
mit der niedrigsten Distanz zum Trainingsvektor ⃗x zu adaptieren (U i mit r(⃗c i , ⃗x) = 0).<br />
Dieser als Hard Clustering bezeichnete Ansatz hat den Vorteil, einen Großteil der für<br />
die Adaption der PCAs benötigten Rechenzeit einzusparen.<br />
2.6 Orthonormalisierung<br />
Zur Orthonormalisierung wird das Gram-Schmidtsche Orthonormalisierungsverfahren<br />
(Giraud et al., 2005) verwendet, welches zu den Vektoren ⃗a 1 , . . . , ⃗a n ein Orthonormalsystem<br />
⃗q 1 , . . . , ⃗q n berechnet. Der klassische Algorithmus (Listing 2.1) ist jedoch numerisch<br />
instabil (Björck, 1994), weshalb die mathematisch äquivalente modifizierte Variante<br />
benutzt wird (Listing 2.2).<br />
f o r i = 1 : n<br />
⃗q i = ⃗a i<br />
f o r i = 1 : n<br />
⃗q i = ⃗a i<br />
f o r j = 1 : i −1<br />
∆⃗q i = −〈⃗q j , ⃗a i 〉 · ⃗q j<br />
end<br />
f o r j = 1 : i −1<br />
∆⃗q i = −〈⃗q j , ⃗q i 〉 · ⃗q j<br />
end<br />
end<br />
⃗q i = ⃗q i / ‖⃗q i ‖<br />
end<br />
⃗q i = ⃗q i / ‖⃗q i ‖<br />
Listing 2.1: Klassische Gram-Schmidt Orthogonalisierung<br />
Listing 2.2: Modifizierte Gram-Schmidt Orthogonalisierung<br />
Dabei bezeichnet 〈⃗a, ⃗ b〉 das Skalarprodukt zwischen ⃗a und ⃗ b.<br />
12 Universität Bielefeld, AG Technische Informatik
3<br />
<strong>Implementation</strong><br />
In diesem Kapitel wird die Realisierung des NGPCA-Algorithmus auf der Grafikkarte<br />
erläutert. Hierfür wurde C++ als Programmiersprache und OpenCL als Schnittstelle<br />
zur Programmierung der <strong>GPU</strong> verwendet. Da OpenCL in C geschrieben ist, wurden<br />
die OpenCL C++ Bindings (siehe Anhang D) verwendet. Diese ermöglichen einen<br />
objektorientierten Zugriff auf die OpenCL-Funktionen und erlauben die elegante<br />
Fehlerabfrage mittels Exceptions.<br />
Die Anwendung wurde durchgehend objektorientiert entworfen, eine Übersicht über<br />
die wichtigsten erstellten Klassen können Sie dem Klassendiagramm in Abbildung 3.1<br />
entnehmen.<br />
CLI<br />
CLI(argc,argv)<br />
parse() : int<br />
units : Unit*<br />
params : NGPCAParams<br />
NGPCA<br />
NGPCA(params,threadCount,hardClustering,...,deviceId)<br />
loadFromFile(file)<br />
learn(iterations)<br />
write(file)<br />
NGPCAParams<br />
prototypes : uint<br />
eigenvalues : uint<br />
Unit<br />
center : T*<br />
w : T*<br />
lambda : T*<br />
sigma : T*<br />
write(out) : void<br />
Abbildung 3.1: Klassendiagramm der wichtigsten Klassen. Einzelne Attribute und Methoden wurden weggelassen.<br />
Einstiegspunkt der Applikation ist die CLI-Klasse. Hier werden die Kommandozeilenparameter<br />
mit Hilfe der Boost Program Options Bibliothek (siehe Anhang<br />
D) ausgewertet und durch sinnvolle Vorgabewerte erweitert. Des Weiteren werden<br />
Hilfsfunktionen wie die Anzeige aller verfügbarer OpenCL-Geräte oder die Darstellung<br />
einer Hilfeseite bereitgestellt. Die zuvor erfassten Trainingsparameter werden in einem<br />
NGPCAParams-Struct gespeichert und für die Instanziierung eines NGPCA-Objektes<br />
verwendet. Da die NGPCA-Klasse generisch programmiert wurde, ist eine einfache<br />
Umstellung <strong>von</strong> 32 Bit Fließkommazahlen auf 64 Bit möglich. In der Praxis muss ein<br />
NGPCA-Netzwerk aber mit doppelter Genauigkeit trainiert werden, da das Ergebnis<br />
Universität Bielefeld, AG Technische Informatik 13
3 <strong>Implementation</strong><br />
sonst unzureichend ist. Dies ist insbesondere für die Implementierung auf der Grafikkarte<br />
<strong>von</strong> Nachteil, da Berechnungen mit doppelter Genauigkeit deutlich langsamer<br />
durchgeführt werden (siehe Tabelle 4.1).<br />
Über die loadFromFile-Methode der NGPCA-Klasse kann nun eine Matrix mit<br />
Trainingsdaten geladen werden. Dabei wird der OpenCL-Quellcode für das gewählte<br />
Gerät kompiliert, wobei datensatzspezifische Precompiler-Direktiven wie z.B. die<br />
Größe der Eingabevektoren, die zu benutzende Eigenwertanzahl etc. gesetzt werden.<br />
Dadurch kann der OpenCL-Compiler Optimierungen wie z.B. Loop Unrolling (Murthy<br />
et al., 2010) vornehmen, die bei Übergabe der Parameter zur Laufzeit nicht möglich<br />
wären. Nach dem Kompiliervorgang werden die Units auf der Grafikkarte initialisiert<br />
und die Eingabedaten auf das OpenCL-Gerät kopiert (siehe Kapitel 3.1), so dass nach<br />
dem Ausführen der loadFromFile-Methode alle benötigten Daten initialisiert auf der<br />
Grafikkarte vorliegen.<br />
Der Lernprozess kann mit der learn-Methode der NGPCA-Klasse gestartet werden,<br />
wobei die Anzahl der Iterationen als Parameter übergeben wird. Grundidee<br />
ist, dass jede Unit eine Work-Group bildet, so dass die Distanzberechnung und die<br />
Adaption parallel über alle Units durchgeführt wird. Die Daten der Units U i =<br />
(⃗c i , W i , Λ i , σi 2 ) verbleiben dabei aus Performancegründen während des gesamten Lernprozesses<br />
im globalen Speicher der Grafikkarte und werden erst zur finalen Speicherung<br />
wieder in den Arbeitsspeicher kopiert. Da eine globale Synchronisation<br />
über alle Units nicht innerhalb eines Kernels möglich ist, jedoch für das Ranking<br />
benötigt wird, wurde jede Iteration in 4 Kernel unterteilt (siehe Abbildung 3.2).<br />
Zunächst wird die Distanzberechnung für<br />
einen Datenpunkt ⃗x parallel ausgeführt. Anschließend<br />
werden die Resultate zur Rangbestimmung<br />
r(⃗c i , ⃗x) sortiert und parallel dazu<br />
die Lernparameter bestimmt. Abschließend<br />
findet die Adaption (inkl. Orthonormalisierung)<br />
wieder parallel über alle Units statt. Bei<br />
der Verwendung <strong>von</strong> Hard Clustering (Kapitel<br />
2.5.3) wird jedoch nur eine Unit angepasst,<br />
weshalb die in Abbildung 3.2 rot markierten<br />
Schritte nicht ausgeführt werden.<br />
Alle j Iterationen wird ein weiterer Kernel<br />
zur Überprüfung der Units gestartet. Dieser<br />
erkennt “tote” Units und setzt diese zurück<br />
(Welsch, 2009).<br />
Der auf der CPU während einer Iteration<br />
ausgeführte Programmcode ist ein potentieller<br />
Flaschenhals und wurde somit möglichst<br />
effizient gestaltet. Es wird lediglich der<br />
nächste Trainingsvektor zufällig bestimmt,<br />
dessen Index als Kernelparameter übergeben<br />
Kernel: Distanzberechnung<br />
Unit 1 Unit 2 ... Unit k<br />
Kernel: Ranking und Parameterbestimmung<br />
Ranking<br />
Kernel: Adaption<br />
Parameterbestimmung<br />
Unit 1 Unit 2 ... Unit k<br />
Kernel: Überprüfung der Units<br />
Unit 1 Unit 2 ... Unit k<br />
Abbildung 3.2: Kernelaufrufe einer Iteration<br />
und der Start der entsprechenden Kernel angestoßen. In den Kapiteln 3.1 bis 3.4 werden<br />
die einzelnen Trainingsschritte näher erläutert.<br />
14 Universität Bielefeld, AG Technische Informatik
3 <strong>Implementation</strong><br />
Nachdem das NGPCA-Netzwerk erfolgreich trainiert wurde, kann mit der write-<br />
Methode der NGPCA-Klasse das Ergebnis in einer Datei gespeichert werden. Dabei<br />
werden die Daten U i <strong>von</strong> der Grafikkarte kopiert und in einem speziellen Format in die<br />
übergebene Datei geschrieben.<br />
3.1 Initialisierung<br />
Die Initialisierung beginnt mit der Bestimmung einer sinnvollen Work-Group-Größe<br />
aufgrund der festgelegten Thread-Anzahl. Dazu werden die zu benutzenden Threads<br />
auf ein zweidimensionales Gitter aufgeteilt, wobei dieses jeweils optimal zu den<br />
verwendeten Kerneln gewählt wird. Außerdem wird sichergestellt, dass aufgrund der<br />
verwendeten Reduktionen (Sanders und Kandrot, 2010) nur Zweierpotenzen benutzt<br />
werden.<br />
Anschließend wird der in die Applikation automatisch einkompilierte OpenCL-<br />
Quellcode für das gewählte Gerät kompiliert, wonach die Trainingsvektoren auf das<br />
Gerät kopiert werden. Abschließend wird (globaler) Speicher für die Units reserviert,<br />
welcher dann mit einem Kernel parallel für alle Units initialisiert wird. Der Trainingsvektor<br />
wird innerhalb des Kernels zufällig gewählt und gesetzt, wobei ein 32 Bit Xorshift<br />
Pseudozufallszahlengenerator 1 (Marsaglia, 2003) zum Einsatz kommt. Dieser wird<br />
auch für die Initialisierung der Gewichtsmatrix W i benutzt, die anschließend gemäß<br />
Kapitel 3.4.2 orthonormalisiert wird. Alle weiteren Parameter können einfach aus dem<br />
übergebenen NGPCAParams-Struct übernommen werden.<br />
3.2 Distanzberechnung<br />
Wie bereits erwähnt, berechnet jede Work-Group die Distanz einer Unit U i zum<br />
Trainingsvektor ⃗x. Bei Vektoroperationen wie z.B. ξ ⃗ i = ⃗x − ⃗c i werden die Work-Items<br />
eindimensional verwendet, so dass jedes Work-Item eine oder mehrere Positionen in<br />
dem resultierenden Vektor ermittelt. Matrixoperationen werden hingegen zweidimensional<br />
ausgeführt.<br />
Skalare Werte wie ⃗ ξ i T ⃗ ξi und ⃗y i T ⃗y i werden mittels Reduktion (Sanders und Kandrot,<br />
2010) berechnet, was sich insbesondere bei großen Trainingsvektoren positiv auf die<br />
Laufzeit auswirkt. Um doppelte Berechnungen zu vermeiden, wird das resultierende ⃗ ξ i ,<br />
⃗y i , ⃗ ξ i T ⃗ ξi und ⃗y i T ⃗y i für die spätere Adaption im globalen Speicher zwischengespeichert.<br />
Für die Erkennung <strong>von</strong> “toten” Units besitzt jede Unit einen Zähler, der die “Restlebensdauer”<br />
angibt. Dieser wird bei der Distanzberechnung dekrementiert und bei Adaptierung<br />
einer Unit wieder zurückgesetzt. Ein spezieller Kernel (siehe Abbildung 3.2)<br />
überprüft die verbleibende Lebensdauer aller Units in einem einstellbaren Intervall und<br />
setzt diese ggf. zurück (Welsch, 2009).<br />
1 Quellcode siehe Anhang B.1<br />
Universität Bielefeld, AG Technische Informatik 15
3 <strong>Implementation</strong><br />
3.2.1 Verwendetes Potential<br />
Das in Gl. 2.14 beschriebene Potential wurde implementiert und wird im Folgenden<br />
VConst bezeichnet. Es eignet sich jedoch nicht optimal für die <strong>GPU</strong>, da Wurzeln mit<br />
relativ hohen Wurzelexponenten berechnet werden müssen. Während das Wurzelziehen<br />
auf 32 Bit Fließkommazahlen hardwareseitig implementiert ist (Munshi, 2012), sind 64<br />
Bit Wurzeloperationen relativ langsam.<br />
Als Alternative wurde daher ein weiteres Potential<br />
(<br />
d i (⃗x) = ⃗y i T Λ −1<br />
i ⃗y i + 1 )<br />
( ξ<br />
λ ⃗T ⃗ ∗ i ξ i − ⃗y i T ⃗y i ) ·<br />
i<br />
(<br />
Tr (Λ −1<br />
i ) +<br />
) −1<br />
(n − m)2<br />
(3.1)<br />
σi<br />
2<br />
mit ξ ⃗ i = ⃗x − ⃗c i , ⃗y i = Wi T ξ ⃗ i und λ ∗ i = σ2 i<br />
implementiert, welches im Folgenden<br />
n−m<br />
TracePotential genannt wird (Kaiser und Schenck).<br />
3.3 Ranking<br />
Zur Bestimmung des Ranges r(⃗c i , ⃗x) einer Unit U i werden die in Kapitel 3.2 berechneten<br />
Distanzen aufsteigend sortiert. Der resultierende Rang ist dann die Position<br />
z ∈ [0 . . . k − 1] der zu der Unit gehörenden Distanz in der sortierten Distanzliste.<br />
3.3.1 Sortierverfahren<br />
Als Sortierverfahren wurde eine modifizierte Variante des Parallel Selection Sort 2,3<br />
verwendet. Dies ist ein naiver Algorithmus, der parallel jeden zu sortierenden Wert mit<br />
allen anderen Einträgen vergleicht.<br />
Da alle Work-Items gleichzeitig dieselbe Distanz zum Vergleich heranziehen, kann<br />
durch Broadcasting (Sanders und Kandrot, 2010) dennoch eine recht hohe Geschwindigkeit<br />
erreicht werden. Bei genügend Hardwareressourcen und damit einer echten<br />
parallelen Ausführung des Sortiervorganges wird eine Komplexität <strong>von</strong> O(n) erreicht.<br />
Es gibt durchaus noch schnellere und durch lokalen Speicher beschleunigte Sortierverfahren.<br />
Auf einen aufwändigen Algorithmus wurde aufgrund der niedrigen Anzahl der<br />
zu sortierenden Elemente und dem hierdurch geringen Anteil des Rankings an der Gesamtlaufzeit<br />
(siehe Tabelle 4.5) allerdings verzichtet.<br />
3.4 Adaptierung<br />
Die Adaptierung erfolgt wieder parallel für alle Units und basiert auf dem zuvor<br />
ermittelten Rang. Während beim Soft Clustering alle Units angepasst werden, wird<br />
beim Hard Clustering nur die Unit mit Rang 0 angepasst. Alle anderen Work-Groups<br />
beenden ihre Ausführung unmittelbar nach dieser Überprüfung.<br />
2 http://www.bealto.com/gpu-sorting_parallel-selection.html<br />
Datum: 21.09.2012<br />
3 Quellcode siehe Anhang B.2<br />
16 Universität Bielefeld, AG Technische Informatik
3 <strong>Implementation</strong><br />
Zunächst wird nach Gl. 2.7 das Zentrum der jeweiligen der Unit aktualisiert. Anschließend<br />
erfolgt die Berechnung der lokalen PCA mittels RRLSA (siehe Kapitel 3.4.1) und<br />
das wie in Kapitel 3.2 beschriebene Zurücksetzen des Alters der Unit. Die Residualvarianz<br />
wird nach Gl. 2.15 angepasst. Bei Erreichen des eingestellten Orthonormalisierungsintervalles<br />
(siehe Anhang E) erfolgt die Orthonormalisierung <strong>von</strong> W i nach Kapitel<br />
3.4.2.<br />
3.4.1 Hauptkomponentenanalyse<br />
Die lokale PCA wird mittels RRLSA (siehe Kapitel 2.5.1) berechnet. Dafür wird<br />
zunächst das während der Distanzberechnung ermittelte ⃗y i wegen der häufigen Verwendung<br />
in den lokalen Speicher geladen. Zur einfacheren Berechnung wird eine unnormalisierte<br />
Version <strong>von</strong> W i zusätzlich im globalen Speicher vorgehalten. W i und Λ i ergibt<br />
sich dann aus Gl. 2.13. Für die Normalisierung wird wie bei der Distanzberechnung eine<br />
Reduktion verwendet.<br />
3.4.2 Orthonormalisierung<br />
Das in Kapitel 2.6 beschriebene modifizierte Gram-Schmidtsche Orthogonalisierungsverfahren<br />
(MGS) ist zwar numerisch stabil, allerdings erzeugt es das Orthonormalsystem<br />
⃗q 1 , . . . , ⃗q n sequenziell. Aus diesem Grund ist es nur schlecht für eine<br />
Verwendung auf der <strong>GPU</strong> geeignet. Dennoch lässt sich das Verfahren parallel auf der<br />
<strong>GPU</strong> implementieren, so dass es deutlich schneller als die naive MGS Implementierung<br />
ist.<br />
Der Algorithmus 4 (Listing 3.1) arbeitet dabei direkt auf den zu orthonormalisierenden<br />
Vektoren, womit die Initialisierung ⃗q i = ⃗a i entfällt. Diese werden im Folgenden<br />
⃗q 1 , . . . , ⃗q n bezeichnet.<br />
Zunächst wird der erste Vektor ⃗q 1 mittels Reduktion normalisiert und das Ergebnis<br />
zurück in den globalen Speicher geschrieben. Der normalisierte Vektor ⃗q 1 verbleibt jedoch<br />
im lokalen Speicher der Work-Group und wird im Folgenden q last ⃗ genannt. Anschließend<br />
können alle Vektoren ⃗q i , i ∈ [2 . . . n] parallel das Skalarprodukt mit q last ⃗<br />
bilden. Dieses wird multipliziert mit q last ⃗ <strong>von</strong> dem Vektor ⃗q i subtrahiert:<br />
∆⃗q i = −〈⃗q i , q last ⃗ 〉 · q last ⃗ ∀ i ∈ [2 . . . n] (3.2)<br />
Durch Normalisierung ⃗q 2 = ⃗q 2 / ‖⃗q 2 ‖ ergibt sich der zweite Vektor des Orthonormalsystemes.<br />
Dieser wird nun als letzter orthonormalisierter Vektor q last ⃗ im lokalen<br />
Speicher gehalten, womit der Algorithmus mit der Aktualisierung aller Vektoren<br />
⃗q i , i ∈ [3 . . . n] fortfährt. Bei jeder Iteration ergibt sich also sequenziell ein Ergebnisvektor<br />
⃗q i , wobei die Anpassung der verbleibenden Vektoren ⃗q j , j ∈ [i + 1 . . . n] parallel<br />
geschieht.<br />
Der gesamte Algorithmus lässt sich zu Listing 3.1 zusammenfassen.<br />
4 Quellcode siehe Anhang B.4<br />
Universität Bielefeld, AG Technische Informatik 17
3 <strong>Implementation</strong><br />
⃗q 1 = ⃗q 1 / ‖⃗q 1 ‖<br />
q last ⃗ = ⃗q 1<br />
f o r j = 2 : n<br />
∆⃗q i = −〈⃗q i , q last ⃗ 〉 · q last ⃗ ∀ i ∈ [j . . . n]<br />
end<br />
⃗q j = ⃗q j / ‖⃗q j ‖<br />
q last ⃗ = ⃗q j<br />
Listing 3.1: Parallele Gram-Schmidt Orthonormalisierung<br />
Dabei erfolgt die Anpassung ∆⃗q i parallel über alle i. Alle Normierungen und Skalarprodukte<br />
werden durch Reduktionen berechnet.<br />
3.5 Harte Vektorquantisierung<br />
Wie bereits in Kapitel 2.5.3 und 3 erwähnt wurde, wird beim Hard Clustering nur eine<br />
Unit adaptiert. Dies spart einen Großteil der für die Adaption benötigten Rechenzeit<br />
ein. Es hat jedoch auch zur Folge, dass der Parallelitätsgrad während der Adaption sehr<br />
niedrig ist, wodurch nur ein Bruchteil der möglichen <strong>GPU</strong>-Leistung tatsächlich benutzt<br />
wird.<br />
Um die Auslastung der Grafikkarte zu<br />
erhöhen werden r Trainingsvektoren gleichzeitig<br />
Kernel: Distanzberechnung<br />
präsentiert (siehe Abbildung 3.3).<br />
Der Distanzkernel arbeitet folglich auf k · r<br />
Unit 1<br />
Unit k<br />
...<br />
x 1, x 2, ... x r<br />
x 1, x 2, ... x r<br />
Work-Groups, wobei k die Anzahl der benutzten<br />
Prototypen ist. Jede Work-Group berechnet<br />
also die Distanz einer bestimmten Unit U i<br />
Kernel: Ranking und Parameterbestimmung<br />
zu einem festgelegten Trainingsvektor ⃗x j .<br />
Ranking<br />
Ranking<br />
Parameterbestimmung<br />
Durch die Erweiterung auf mehrere Datenpunkte<br />
kann das Ranking ebenfalls erwei-<br />
...<br />
x 1<br />
x r<br />
tert werden. Dabei ermittelt jede Work-Group<br />
des Ranking-Kernels für einen bestimmten<br />
Kernel: Altersupdate der Units<br />
Datenpunkt ⃗x j die “Gewinnerunit” U i mit<br />
r(⃗c i , ⃗x j ) = 0. Bei den ermittelten “Gewinnerunits”<br />
Unit ... Unit<br />
kann es jedoch zu Überschneidungen<br />
kommen, falls zwei Trainingsvektoren derselben<br />
Kernel: Adaption<br />
Unit zugeordnet sind. Daher werden nur<br />
die zugeordneten Units der ersten s ≤ r Datenpunkte<br />
adaptiert, bei denen keine Überschneidung<br />
in den zu adaptierenden Units vorliegt.<br />
Unit<br />
Unit<br />
...<br />
x 1<br />
x s<br />
Kernel: Überprüfung der Units<br />
Im schlechtesten Fall wird nur eine Unit<br />
angepasst, im günstigsten Fall allerdings r<br />
Unit 1 ... Unit k<br />
Units auf einmal.<br />
Abbildung 3.3: Kernelaufrufe einer Iterationsreihe,<br />
Bitte beachten Sie, dass das in Kapitel 3.2 beschriebene<br />
dekrementieren der “Restlebens-<br />
Hard Clustering<br />
dauer” aller Units durch die geänderte Distanzberechnung nicht mehr im Distanzkernel<br />
18 Universität Bielefeld, AG Technische Informatik
3 <strong>Implementation</strong><br />
geschehen kann, weshalb für diese Aufgabe ein zusätzlicher Kernel “Altersupdate der<br />
Units” hinzugefügt wurde.<br />
3.5.1 Adaptive Anpassung der parallelen Trainingsvektoren<br />
Der in Kapitel 3.5 beschriebene Ansatz funktioniert bei passend gewählter Anzahl<br />
r an parallel zu verarbeitenden Trainingsvektoren sehr gut und liefert einen hohen<br />
zusätzlichen Speedup. Leider ist dieser Parameter nicht intuitiv zu wählen und hängt<br />
stark vom verwendeten Datensatz und der Anzahl an Prototypen ab. Zu kleine Werte<br />
<strong>von</strong> r lasten die <strong>GPU</strong> nicht vollständig aus und verschenken so einen möglichen<br />
Performancegewinn. Wählt man den Parameter zu hoch, werden Distanzen zu sehr<br />
vielen Datenpunkten berechnet, <strong>von</strong> denen allerdings nur ein geringer Teil tatsächlich<br />
verwendet wird. Die Folge ist ein schlechter Speedup.<br />
Lösung für dieses Problem ist eine adaptive Anpassung der Anzahl an parallelen Trainingsvektoren.<br />
Zu Beginn des Lernprozesses ist der Parameter hoch gewählt, wird aber<br />
in einem einstellbaren Intervall (siehe Anhang E) durch den beobachteten (aufgerundeten)<br />
Mittelwert der tatsächlich adaptierten Units ersetzt.<br />
Universität Bielefeld, AG Technische Informatik 19
4<br />
Experimentelle Ergebnisse<br />
In diesem Kapitel wird die erzielte Geschwindigkeit anhand <strong>von</strong> zwei ausgewählten<br />
Datensätzen mit der Referenz-CPU-Implementierung verglichen. Betrachtet wird dabei<br />
der Speedup S = tcpu<br />
t gpu<br />
, also die durch die <strong>GPU</strong>-Implementierung erzielte Beschleunigung<br />
des Lernprozesses.<br />
Zunächst wird in Kapitel 4.1 kurz auf die verwendete Hardware eingegangen, während<br />
anschließend in Kapitel 4.2 und 4.3 die analysierten Datensätze erläutert werden. Der<br />
Einfluss einzelner Parameter auf den Speedup wird in Kapitel 4.4 betrachtet. Eine Übersicht<br />
über die Laufzeiten der einzelnen Kernel liefert Kapitel 4.5.<br />
4.1 Hardware<br />
Sämtliche Analysen wurden auf baugleichen Rechnern 1 durchgeführt, einzig die Laufzeiten<br />
der AMD Karten sind auf einem etwas langsameren System 2 gemessen worden.<br />
Die Leistungsdaten der verwendeten Grafikkarten können Sie Tabelle 4.1 entnehmen,<br />
wobei die theoretische Maximalleistung durch<br />
P max = Prozessortakt · #Shader · Operationen<br />
Takt<br />
(4.1)<br />
berechnen wurde. Von besonderem Interesse ist hier die 64 Bit Performance, da NGPCA<br />
in doppelter Genauigkeit trainiert wird (siehe Kapitel 3). Dabei ergibt sich die 64 Bit<br />
Performance bei Nvidia Consumer Karten als 1/8 der 32 Bit Performance bzw. bei<br />
AMD als 1/4.<br />
1 Intel(R) Core(TM) i7-2600 CPU, 8 GB RAM<br />
2 Intel(R) Core(TM) i7-930 CPU, 6 GB RAM<br />
20 Universität Bielefeld, AG Technische Informatik
4 Experimentelle Ergebnisse<br />
Bezeichnung Takt #Shader P max (32 Bit) P max (64 Bit)<br />
Nvidia GTX 560 Ti 1,645 GHz 384 1263 GFLOPs 158 GFLOPs<br />
Nvidia GTX 570 1,4 GHz 480 1344 GFLOPs 168 GFLOPs<br />
AMD Radeon HD 6970 3 0,94 GHz 1536 2888 GFLOPs 722 GFLOPs<br />
AMD Radeon HD 7970 4 1,05 GHz 2048 4301 GFLOPs 1075 GFLOPs<br />
Tabelle 4.1: Theoretische Leistungsdaten der verwendeten Grafikkarten (Operationen/Takt = 2 bei FMA)<br />
4.2 Roboterarmsteuerung<br />
Bei diesem 68-dimensionalen Datensatz aus N = 3213 Datenpunkten soll die<br />
Steuerung eines Roboterarmes gelernt werden. Dabei soll der Roboterarm ein kleines<br />
Klötzchen greifen. Eine detaillierte Beschreibung des Szenarios finden Sie in Schenck<br />
(2008) und Hoffmann et al. (2005).<br />
Abbildung 4.1 zeigt den erreichten Speedup in Abhängigkeit <strong>von</strong> der verwendeten Grafikkarte.<br />
Dabei wurde jeweils die Threadanzahl mit dem besten Speedup gewählt (siehe<br />
Anhang A.1). Interessant ist hierbei die schlechte Performance der AMD Karten und<br />
der deutlich höhere Speedup beim Soft Clustering.<br />
12<br />
10<br />
Nvidia GTX 560 Ti<br />
Nvidia GTX 570<br />
AMD Radeon HD 6970<br />
AMD Radeon HD 7970<br />
6<br />
5<br />
Nvidia GTX 560 Ti<br />
Nvidia GTX 570<br />
AMD Radeon HD 6970<br />
AMD Radeon HD 7970<br />
8<br />
4<br />
speedup<br />
6<br />
speedup<br />
3<br />
4<br />
2<br />
2<br />
1<br />
0<br />
0 20 40 60 80 100 120 140 160 180 200<br />
clusters<br />
(a) Soft Clustering<br />
0<br />
0 20 40 60 80 100 120 140 160 180 200<br />
clusters<br />
(b) Hard Clustering<br />
Abbildung 4.1: Speedup der Grafikkarten nach Anzahl der Prototypen [4 Eigenwerte, 20.000 Iterationen, optimale<br />
Threadanzahl]<br />
Für die Evaluation der Lernqualität (Tabelle 4.2) wurde der in Schenck (2008) beschriebene<br />
Greiffehler betrachtet. Dabei ist erkennbar, dass die <strong>GPU</strong> <strong>Implementation</strong> bei diesem<br />
Datensatz qualitativ gleichwertig mit der CPU-Referenzimplementierung ist.<br />
CPU <strong>GPU</strong> (VConst) <strong>GPU</strong> (TracePot.)<br />
Avg. Error 0,871 0,862 0,872<br />
Std. Dev 0,030 0,036 0,041<br />
Tabelle 4.2: Greiffehler [4 Eigenwerte, 100 Prototypen, 20.000 Iterationen, Hard Clustering]<br />
3 http://www.msi.com/product/vga/R6970-Lightning.html<br />
Datum: 18.09.2012<br />
4 http://www.hisdigital.com/de/product2-692.shtml<br />
Datum: 18.09.2012<br />
Universität Bielefeld, AG Technische Informatik 21
4 Experimentelle Ergebnisse<br />
4.3 CT Slices<br />
Dieser 385-dimensionale Datensatz mit N = 53500 Datenpunkten enthält Merkmale<br />
aus Computertomographie-Schnittbildaufnahmen 5 . Der Merkmalsvektor wird dabei aus<br />
zwei Histogrammen gebildet, die die Knochenstruktur und die Lufteinschlüsse jeder<br />
Aufnahme beschreiben. Ziel dabei ist, die relative Position der Schnittbilder zu erlernen.<br />
In Abbildung 4.2 wird der erreichte Speedup bei optimaler Threadanzahl (siehe Anhang<br />
A.2) in Abhängigkeit <strong>von</strong> der verwendeten Grafikkarte gezeigt. Dabei ist die relative hohe<br />
Soft Clustering Performance der Radeon HD 7970 und der allgemein höhere Speedup<br />
beim Hard Clustering besonders bemerkenswert.<br />
4.5<br />
6<br />
4<br />
5<br />
3.5<br />
4<br />
speedup<br />
3<br />
2.5<br />
2<br />
1.5<br />
Nvidia GTX 560 Ti<br />
Nvidia GTX 570<br />
Radeon HD 6970<br />
Radeon HD 7970<br />
speedup<br />
3<br />
2<br />
1<br />
Nvidia GTX 560 Ti<br />
Nvidia GTX 570<br />
Radeon HD 6970<br />
Radeon HD 7970<br />
1<br />
50 100 150 200 250 300<br />
clusters<br />
(a) Soft Clustering<br />
0<br />
50 100 150 200 250 300<br />
clusters<br />
(b) Hard Clustering<br />
Abbildung 4.2: Speedup der Grafikkarten nach Anzahl der Prototypen [20 Eigenwerte, 20.000 Iterationen, optimale<br />
Threadanzahl]<br />
Die Lernqualität wurde mit dem normalized Mean Square Error (Normalized MSE)<br />
beurteilt, der über alle Datenpunkte berechnet wurde (Tabelle 4.3). Hierbei ist eine<br />
deutliche Qualitätverbesserung durch die <strong>GPU</strong>-Implementierung gegenüber der CPU-<br />
Referenzimplementierung sichtbar. Des Weiteren verbessert das vermeintlich schlechtere<br />
Potential das Ergebnis.<br />
CPU <strong>GPU</strong> (VConst) <strong>GPU</strong> (TracePot.)<br />
Avg. Error 4,663 1,306 0,899<br />
Std. Dev 1,478 0,315 0,301<br />
Tabelle 4.3: Normalized MSE [20 Eigenwerte, 200 Prototypen, 200.000 Iterationen, Hard Clustering]<br />
5 http://archive.ics.uci.edu/ml/datasets/Relative+location+of+CT+<br />
slices+on+axial+axis<br />
Datum: 18.09.2012<br />
22 Universität Bielefeld, AG Technische Informatik
4 Experimentelle Ergebnisse<br />
4.4 Speedup nach gewählten Parametern<br />
In diesem Kapitel wird der Einfluss einzelner Trainingsparameter auf den Speedup untersucht.<br />
Da sich die Architektur der verwendeten Nvidia Karten untereinander bzw.<br />
der AMD Karten untereinander nur gering unterscheidet, werden im Folgenden nur die<br />
Nvidia GTX 570 und die AMD Radeon HD 7970 betrachtet.<br />
4.4.1 Anzahl der Prototypen<br />
Abbildung 4.3 und 4.4 zeigen die Abhängigkeit des Speedup <strong>von</strong> der Anzahl der verwendeten<br />
Prototypen. Eine höhere Anzahl bewirkt einen größeren Speedup, wobei die<br />
Steigung mit steigender Anzahl an Unit’s abnimmt. Insbesondere das Hard Clustering<br />
profitiert <strong>von</strong> vielen Prototypen.<br />
11<br />
10<br />
9<br />
8<br />
32 threads<br />
64 threads<br />
128 threads<br />
256 threads<br />
512 threads<br />
5.5<br />
5<br />
4.5<br />
4<br />
7<br />
3.5<br />
speedup<br />
6<br />
speedup<br />
3<br />
5<br />
4<br />
3<br />
2.5<br />
2<br />
1.5<br />
32 threads<br />
64 threads<br />
128 threads<br />
256 threads<br />
512 threads<br />
2<br />
1<br />
1<br />
0 20 40 60 80 100 120 140 160 180 200<br />
clusters<br />
(a) Soft Clustering, Nvidia GTX 570<br />
0.5<br />
0 20 40 60 80 100 120 140 160 180 200<br />
clusters<br />
(b) Hard Clustering, Nvidia GTX 570<br />
Abbildung 4.3: Speedup nach Prototypen und Threads [Arm Datensatz, 4 Eigenwerte, 20.000 Iterationen]<br />
speedup<br />
4.5<br />
4<br />
3.5<br />
3<br />
2.5<br />
speedup<br />
5<br />
4.5<br />
4<br />
3.5<br />
3<br />
2.5<br />
2<br />
32 threads<br />
64 threads<br />
128 threads<br />
256 threads<br />
512 threads<br />
2<br />
1.5<br />
32 threads<br />
64 threads<br />
128 threads<br />
256 threads<br />
512 threads<br />
1.5<br />
1<br />
0.5<br />
1<br />
50 100 150 200 250 300<br />
clusters<br />
(a) Soft Clustering, Radeon HD 7970<br />
0<br />
50 100 150 200 250 300<br />
clusters<br />
(b) Hard Clustering, Radeon HD 7970<br />
Abbildung 4.4: Speedup nach Prototypen und Threads [CT Datensatz, 20 Eigenwerte, 20.000 Iterationen]<br />
Universität Bielefeld, AG Technische Informatik 23
4 Experimentelle Ergebnisse<br />
4.4.2 Anzahl der Eigenwerte<br />
Der Zusammenhang zwischen Speedup und der verwendeten Anzahl an Eigenwerten<br />
wird in Abbildung 4.5 gezeigt. Für diese Evaluation wurde der CT Datensatz ausgewählt,<br />
da die Qualität der Lernergebnisse relativ unempfindlich auf die gewählte<br />
Eigenwertanzahl ist.<br />
Beim Soft Clustering fällt der Speedup mit steigender Eigenwertanzahl auf einen Grenzwert<br />
ab, wobei dieser bei der AMD Radeon HD 7970 höher ausfällt und die Änderung<br />
geringer ist. Für Hard Clustering ist die Nvidia GTX 570 jedoch besser geeignet, da<br />
der Speedup hier deutlich höher ausfällt und ab einer gewissen Eigenwertanzahl auch<br />
wieder leicht ansteigt.<br />
speedup<br />
10<br />
9<br />
8<br />
7<br />
6<br />
5<br />
4<br />
32 threads<br />
64 threads<br />
128 threads<br />
256 threads<br />
512 threads<br />
speedup<br />
7<br />
6<br />
5<br />
4<br />
3<br />
32 threads<br />
64 threads<br />
128 threads<br />
256 threads<br />
512 threads<br />
3<br />
2<br />
2<br />
1<br />
0 5 10 15 20 25 30<br />
eigenvalues<br />
(a) Soft Clustering, Nvidia GTX 570<br />
1<br />
0 5 10 15 20 25 30<br />
eigenvalues<br />
(b) Soft Clustering, Radeon HD 7970<br />
7<br />
6<br />
5<br />
4<br />
3.5<br />
3<br />
32 threads<br />
64 threads<br />
128 threads<br />
256 threads<br />
512 threads<br />
speedup<br />
4<br />
speedup<br />
2.5<br />
3<br />
2<br />
32 threads<br />
64 threads<br />
128 threads<br />
256 threads<br />
512 threads<br />
2<br />
1.5<br />
1<br />
0 5 10 15 20 25 30<br />
eigenvalues<br />
(c) Hard Clustering, Nvidia GTX 570<br />
1<br />
0 5 10 15 20 25 30<br />
eigenvalues<br />
(d) Hard Clustering, Radeon HD 7970<br />
Abbildung 4.5: Speedup nach Eigenwerten und Threads [CT Datensatz, 20 Eigenwerte, 200 Prototypen, 20.000 Iterationen]<br />
24 Universität Bielefeld, AG Technische Informatik
4 Experimentelle Ergebnisse<br />
4.4.3 Verwendetes Potential<br />
Diese Auswertung untersucht die durch das angepasste Potential (siehe Kapitel 3.2.1)<br />
verursachte Beschleunigung. Hierbei wurde der CT Datensatz ausgewählt, obwohl<br />
bei dem Arm Datensatz deutlich höhere Beschleunigungen <strong>von</strong> etwa 27 % gemessen<br />
wurden. Auf eine Darstellung des Speedups in Abhängigkeit <strong>von</strong> der Eigenwertanzahl<br />
wurde für den Arm Datensatz aufgrund der in Kapitel 4.4.2 genannten Sensitivität<br />
allerdings verzichtet.<br />
Das Soft Clustering wird durch das angepasste Potential nicht nennenswert beschleunigt<br />
(deutlich unter 1 %). Beim Hard Clustering wird jedoch ein zusätzlicher Speedup <strong>von</strong><br />
etwa 5 % erreicht, wobei die Nvidia Karten ein wesentlich stabileres Verhalten zeigen.<br />
1.014<br />
1.5<br />
1.012<br />
1.01<br />
1.008<br />
Nvidia GTX 560 Ti<br />
Nvidia GTX 570<br />
Radeon HD 6970<br />
Radeon HD 7970<br />
1.4<br />
1.3<br />
Nvidia GTX 560 Ti<br />
Nvidia GTX 570<br />
Radeon HD 6970<br />
Radeon HD 7970<br />
speedup<br />
1.006<br />
1.004<br />
1.002<br />
speedup<br />
1.2<br />
1.1<br />
1<br />
1<br />
0.998<br />
0.996<br />
0.9<br />
0.994<br />
0 5 10 15 20 25 30<br />
eigenvalues<br />
(a) Soft Clustering<br />
0.8<br />
0 5 10 15 20 25 30<br />
eigenvalues<br />
(b) Hard Clustering<br />
Abbildung 4.6: Speedup nach Eigenwerten [CT Datensatz, 200 Prototypen, 20.000 Iterationen, 512 Threads]<br />
4.5 Kernellaufzeiten<br />
In diesem Kapitel wird der Laufzeitanteil der verwendeten Kernel an der Gesamtlaufzeit<br />
betrachtet.<br />
Beide Plattformen weisen auf dem Arm Datensatz (Tabelle 4.4) deutliche Unterschiede<br />
auf, während sich die Laufzeitcharakteristik bei dem aufwändigeren CT Datensatz (Tabelle<br />
4.5) annähert. Beim Hard Clustering des CT Datensatzes (Tabelle 4.5) trägt die Distanzberechnung<br />
und die Adaption etwa gleichwertig zur Gesamtlaufzeit bei, die Laufzeit<br />
des Soft Clusterings wird jedoch fast ausschließlich <strong>von</strong> der Adaption bestimmt.<br />
Auffällig ist auch, dass eigentlich sehr einfache Kernel wie die Unit Reset Heuristik<br />
und das Ranking auf der AMD Plattform deutlich stärker ins Gewicht fallen.<br />
Universität Bielefeld, AG Technische Informatik 25
4 Experimentelle Ergebnisse<br />
Kernel<br />
Laufzeitanteil<br />
Nvidia GTX 570 AMD Radeon HD 7970<br />
Hard Cl. Soft Cl. Hard Cl. Soft Cl.<br />
Distanzberechnung 43,5 % 4,3 % 25,6 % 17,5 %<br />
Unit Reset 15,9 % 0,8 % 14,8 % 1,9 %<br />
Ranking + Parameterbestimmung 6,7 % 2,6 % 26,4 % 30,5 %<br />
Unit Altersupdate 2,2 % 1,4 %<br />
Adaption 31,7 % 92,2 % 31,8 % 50,0 %<br />
Tabelle 4.4: Kernellaufzeiten [Arm Datensatz, 4 Eigenwerte, 100 Prototypen, 20.000 Iterationen, 512 Threads]<br />
Kernel<br />
Laufzeitanteil<br />
Nvidia GTX 570 AMD Radeon HD 7970<br />
Hard Cl. Soft Cl. Hard Cl. Soft Cl.<br />
Distanzberechnung 48,9 % 2,8 % 34,0 % 1,4 %<br />
Unit Reset 1,2 % 0,0 % 4,1 % 0,2 %<br />
Ranking + Parameterbestimmung 1,7 % 0,2 % 7,2 % 1,4 %<br />
Unit Altersupdate 0,3 % 0,2 %<br />
Adaption 47,9 % 97,0 % 54,5 % 97,0 %<br />
Tabelle 4.5: Kernellaufzeiten [CT Datensatz, 20 Eigenwerte, 200 Prototypen, 20.000 Iterationen, 512 Threads]<br />
Besonders interessant ist, dass die Laufzeit des Soft Clusterings beim CT Datensatz fast<br />
ausschließlich <strong>von</strong> der Adaption bestimmt wird. Die Vermutung liegt nahe, dass dieses<br />
Verhalten durch die höhere Eigenwertanzahl verursacht wird, da der Aufwand für die<br />
Orthonormalisierung quadratisch mit der Anzahl der Eigenwerte steigt (Möller, 2006).<br />
Aus diesem Grund wird in Abbildung 4.7 der Anteil der Orthonormalisierung an der<br />
Gesamtlaufzeit bei variierender Eigenwertanzahl untersucht.<br />
0.9<br />
0.45<br />
0.85<br />
0.4<br />
0.8<br />
0.35<br />
orthonormalization part<br />
0.75<br />
0.7<br />
0.65<br />
0.6<br />
orthonormalization part<br />
0.3<br />
0.25<br />
0.2<br />
0.15<br />
0.55<br />
0.5<br />
Nvidia GTX 570<br />
Radeon HD 7970<br />
0.1<br />
0.05<br />
Nvidia GTX 570<br />
Radeon HD 7970<br />
0.45<br />
0 5 10 15 20 25 30<br />
eigenvalues<br />
(a) Soft Clustering<br />
0<br />
0 5 10 15 20 25 30<br />
eigenvalues<br />
(b) Hard Clustering<br />
Abbildung 4.7: Anteil der Orthonormalisierung an der Gesamtlaufzeit [CT Datensatz, 200 Prototypen, 20.000 Iterationen,<br />
512 Threads]<br />
26 Universität Bielefeld, AG Technische Informatik
5<br />
Diskussion<br />
5.1 Pre-Tests<br />
Vor der eigentlichen Implementierung wurden einige Tests durchgeführt, die die Vorund<br />
Nachteile verschiedener Verfahren evaluiert haben. In diesem Kapitel werden die<br />
Verfahren erwähnt, die aufgrund ihrer Nachteile nicht implementiert wurden.<br />
5.1.1 PCA-Verfahren<br />
Das verwendete PCA-Verfahren RRLSA (Kapitel 2.5.1) liefert nicht mehr paarweise<br />
orthonormale Vektoren, weshalb eine regelmäßige Orthonormalisierung nötig ist.<br />
Coupled PCA (Möller und Konies, 2004) ist zwar etwas aufwändiger als RRLSA, soll<br />
allerdings die Orthonormalität der Hauptachsen größtenteils beibehalten. Dies würde<br />
den zeitaufwändigen Gram-Schmidt Algorithmus überflüssig machen. Leider hat sich<br />
dies nicht hinreichend bestätigt, so dass auch mit Coupled PCA in einem gewissen<br />
Intervall orthonormalisiert werden muss.<br />
Insgesamt gesehen ist RRLSA schneller als Coupled PCA, da auch Coupled PCA nur<br />
bei Orthonormalisierung nach jeder Iteration eine zu RRLSA vergleichbare Trainingsqualität<br />
liefert.<br />
5.1.2 Orthonormalisierungsverfahren<br />
Von Hyvärinen et al. (2001) wird ein iteratives symmetrisches Orthonormalisierungsverfahren<br />
beschrieben, welches sich <strong>von</strong> der Struktur her gut für <strong>GPU</strong>s eignet (wobei<br />
W die zu orthonormalisierende Matrix ist):<br />
W (1) = W (0)/‖W (0)‖ (5.1)<br />
W (t + 1) = 3 2 W (t) − 1 2 W (t)W (t)T W (t) (5.2)<br />
Dabei konvergiert W gegen die orthonormalisierte Matrix.<br />
Universität Bielefeld, AG Technische Informatik 27
5 Diskussion<br />
Der Test auf Konvergenz war allerdings zu aufwändig, weshalb mit einer festen Iterationszahl<br />
gearbeitet werden musste. Leider war dieses Verfahren nur bei geringer Iterationszahl<br />
schneller als die in Kapitel 3.4.2 beschriebene angepasste Gram-Schmidt<br />
Orthonormalisierung. Bei einer so geringen Iterationszahl war die Qualität der Orthonormalisierung<br />
allerdings nicht zufriedenstellend.<br />
5.1.3 <strong>Implementation</strong> einer OpenCL Matrix-Bibliothek<br />
NGPCA lässt sich mit Hilfe <strong>von</strong> Matrixoperationen sehr elegant programmieren. Daher<br />
wurde zunächst der Ansatz verfolgt, eine kleine Matrix-Bibliothek für OpenCL zu<br />
schreiben. Mit dieser sollte dann der NGPCA-Algorithmus implementiert werden.<br />
Zudem könnte die OpenCL-Bibliothek für weitere Projekte genutzt werden.<br />
Dieser Ansatz funktionierte gut und ermöglichte besonders leserlichen Code. Zudem<br />
konnte man bestehende Matlab-Algorithmen 1:1 auf der <strong>GPU</strong> implementieren. Leider<br />
müssen durch diese Herangehensweise viele Zwischenergebnisse gespeichert werden,<br />
welche zu groß für den lokalen Speicher sind und deshalb im globalen Speicher der<br />
Grafikkarte abgelegt werden müssen. Dies führt zu extrem vielen Speicherzugriffen<br />
und damit zu einer schlechten Gesamtperformance.<br />
Durch das explizite Implementieren der verwendeten Algorithmen konnten die Speicherzugriffe<br />
deutlich verringert und in den Matrix-Funktionen verwendete Schleifen<br />
zusammengefasst werden.<br />
5.2 Beurteilung der Ergebnisse<br />
Sowohl beim Hard- als auch bei Soft Clustering konnte ein erheblicher Geschwindigkeitszuwachs<br />
(Abbildung 4.1 und 4.2) gegenüber der CPU-Referenzimplementierung<br />
erreicht werden. Zusätzlich wird bei hochdimensionalen Datensätzen die Lernqualität<br />
signifikant verbessert (Tabelle 4.3). Dies liegt vermutlich an den verwendeten Reduktionen,<br />
die durch viele Zwischenergebnisse die numerische Stabilität verbessern.<br />
Während der Parallelitätsgrad beim Soft Clustering durch die gleichzeitige Berechnung<br />
der Prototypen hoch genug war, musste das Hard Clustering wie in Kapitel 3.5<br />
beschrieben angepasst werden. Hierdurch konnte auch beim Hard Clustering eine hohe<br />
<strong>GPU</strong>-Auslastung und ein damit verbundener signifikanter Speedup erreicht werden.<br />
Die Trainingsqualität wurde durch dieses Verfahren nicht negativ beeinflusst (Tabelle<br />
4.2 und 4.3).<br />
Es hat sich jedoch herausgestellt, dass sich der NGPCA-Algorithmus nicht so optimal<br />
wie ursprünglich gedacht für eine <strong>GPU</strong>-Implementierung eignet. Dies liegt vor allem an<br />
der nötigen doppelten Rechengenauigkeit, wodurch bei Nvidia Karten nur 1/8 der 32<br />
Bit Rechenleistung zur Verfügung steht (bei AMD Karten 1/4). In Hardware implementierte<br />
Funktionen, z.B. für das Wurzelziehen, stehen bei 64 Bit Berechnungen ebenfalls<br />
nicht zur Verfügung. Dies konnte jedoch durch ein angepasstes Potential (siehe Kapitel<br />
3.2.1 und 5.2.1) entschärft werden, welches auf langsame Wurzeloperationen verzichtet.<br />
Des Weiteren musste zur Synchronisation zwischen den Work-Groups jede Iteration in<br />
mehrere Kernel unterteilt werden, was hohe Ansprüche an die effiziente Gestaltung der<br />
28 Universität Bielefeld, AG Technische Informatik
5 Diskussion<br />
Kernelstarts in den entsprechenden Treibern stellt (siehe Kapitel 5.2.2).<br />
Der durch die <strong>GPU</strong>-Implementierung erzielte Speedup hängt jedoch teilweise stark <strong>von</strong><br />
den gewählten NGPCA-Parametern (Kapitel 5.2.1) und der verwendeten Hardware (Kapitel<br />
5.2.2) ab.<br />
5.2.1 Einfluss der gewählten Parameter<br />
In diesem Kapitel wird der Einfluss einzelner Parameter auf den Speedup diskutiert.<br />
Insbesondere wird auf die Anzahl der Prototypen, die Anzahl der Eigenwerte und das<br />
verwendete Potential eingegangen.<br />
Anzahl der Prototypen<br />
Latency Hiding (Fatahalian und Houston, 2008) ist ein Grundkonzept <strong>von</strong> <strong>GPU</strong>s,<br />
wobei mehr Threads zur Ausführung vorgehalten werden als Hardwareressourcen<br />
zur Verfügung stehen. Sind nun einzelne Gruppen <strong>von</strong> Threads durch ausstehende<br />
Speicheranforderungen nicht ausführbar, können andere Threads bearbeitet werden.<br />
Die Grundidee der <strong>Implementation</strong> ist es, alle verwendeten Prototypen parallel auf<br />
der Grafikkarte zu berechnen. Jede Work-Group besteht dabei aus einer vordefinierten<br />
Anzahl an Threads (siehe Anhang E). Die Anzahl der <strong>von</strong> der Grafikkarte zu verarbeitenden<br />
Threads steigt somit mit der Anzahl der Units. Damit funktioniert das o.g.<br />
Latency Hiding besser, was sich positiv auf die Auslastung der Grafikkarte auswirkt.<br />
Resultat ist ein höherer Speedup.<br />
In Abbildung 4.3 und 4.4 ist eine Verbesserung des Speedup bei steigender Anzahl<br />
an Protoypen deutlich erkennbar. Die Steigung des Speedup nimmt jedoch mit zunehmenden<br />
Units ab. Ab einer gewissen Prototypanzahl bringen weitere Units bei der<br />
Betrachtung des Speedup also keinen Mehrwert, da die Grafikkarte bereits vollständig<br />
ausgelastet ist.<br />
Bei hochdimensionalen Datensätzen und Soft Clustering wird jedoch bereits bei<br />
wenigen Prototypen ein Speedup nahe des Maximums erreicht. Dies liegt an den<br />
aufwändigeren Berechnungen für hochdimensionale Vektoren, so dass die maximale<br />
Auslastung der <strong>GPU</strong> schneller erreicht wird.<br />
Generell profitiert das Hard Clustering stärker <strong>von</strong> einer höheren Prototypanzahl, was<br />
sich aufgrund des in Kapitel 3.5 beschriebenen Verfahrens erklären lässt. Während beim<br />
Soft Clustering alle Units parallel angepasst werden, werden beim Hard Clustering gerade<br />
so viele Units parallel adaptiert, dass keine Überschneidungen entstehen. Mehr<br />
Prototypen senken die Wahrscheinlichkeit, dass eine Unit doppelt angepasst werden<br />
würde, was wiederrum den Parallelitätsgrad und damit auch den Speedup erhöht.<br />
Anzahl der Eigenwerte<br />
Die Anzahl der verwendeten Eigenwerte hat ebenfalls Einfluss auf den resultierenden<br />
Speedup, allerdings besteht dieser Zusammenhang nur indirekt.<br />
Universität Bielefeld, AG Technische Informatik 29
5 Diskussion<br />
Wie in Abbildung 4.5 ersichtlich ist, fällt der Speedup beim Soft Clustering zunächst<br />
mit steigender Eigenwertanzahl ab. Nach Erreichen eines Schwellwertes bleibt er<br />
jedoch nahezu konstant. In Tabelle 4.5 ist erkennbar, dass die Laufzeit und damit<br />
auch der Speedup beim Soft Clustering mit hoher Eigenwertanzahl nur durch die<br />
Adaption bestimmt wird. Da der Aufwand für die Orthonormalisierung quadratisch<br />
mit der Anzahl der Eigenwerte steigt (Möller, 2006), steigt auch der Anteil der<br />
Orthonormalisierung an der Adaption. Folglich erhöht sich der Laufzeitanteil der<br />
Orthonormalisierung bei steigender Eigenwertanzahl, was deutlich in Abbildung 4.7a<br />
ersichtlich ist. Die Steigung des Laufzeitanteils fällt jedoch ab, was den Grenzwert in<br />
Abbildung 4.5a und 4.5b erklärt.<br />
Hieraus lässt sich schließen, dass die einzelnen Abschnitte der <strong>Implementation</strong> stark<br />
unterschiedliche Beschleunigungen des NGPCA-Algorithmus verursachen. Die nach<br />
Kapitel 3.4.2 implementierte Gram-Schmidt Orthonormalisierung hat im Vergleich<br />
zu den anderen <strong>Implementation</strong>sabschnitten einen deutlich niedrigeren Speedup, was<br />
vermutlich mit den häufigen Lese- und Schreibzugriffen auf den globalen Speicher<br />
zusammenhängt. Durch Erhöhung der Eigenwerte konvergiert der Speedup der <strong>Implementation</strong><br />
gegen den Speedup der Orthonormalisierung.<br />
Im Gegensatz zum Soft Clustering wird beim Hard Clustering pro Trainingsvektor nur<br />
eine Adaption (und somit Orthonormalisierung) durchgeführt. Hierdurch verringert sich<br />
der Speedup bei steigender Eigenwertanzahl nur gering (Nvidia GTX 570, Abb. 4.5c)<br />
bzw. steigt sogar (Radeon HD 7970, Abb. 4.5d).<br />
Verwendetes Potential<br />
Während das verwendete Potential bei der Berechnung auf der CPU nahezu keinen<br />
Einfluss auf die Laufzeit hat, konnte durch die Verwendung des in Kapitel 3.2.1<br />
beschriebenen Potentials ein teilweise deutlicher zusätzlicher Speedup erreicht werden.<br />
Dies liegt an der Architektur <strong>von</strong> <strong>GPU</strong>s, bei der Wurzeloperationen besonders “teuer”<br />
sind und den Speedup somit verschlechtern. Insbesondere trifft dies auf 64 Bit Wurzeloperationen<br />
zu, die nicht in Hardware implementiert sind und daher nochmals deutlich<br />
zeitaufwändiger sind.<br />
Eine Beschleunigung der Potentialberechnung hat natürlich nur Auswirkungen auf<br />
die Distanzberechnung. Da die Laufzeit des Soft Clusterings größtenteils <strong>von</strong> der<br />
Adaption bestimmt wird (Tabelle 4.5), erzielt das angepasste Potential hier nur eine<br />
nicht nennenswerte Beschleunigung <strong>von</strong> unter 1 % (Abb. 4.6).<br />
Beim Hard Clustering geht die Distanzberechnung mehr in die Gesamtlaufzeit ein, weshalb<br />
hier ein höherer zusätzlicher Speedup erreicht wird. Auf dem in Abbildung 4.6 benutzten<br />
CT Datensatz liegt dieser bei etwa 5 %. Bei niedrigdimensionalen Datensätzen<br />
mit geringer Eigenwertanzahl sind jedoch deutlich höhere Beschleunigungen möglich,<br />
da hier die Potentialberechnung einen höheren Laufzeitanteil an der Gesamtberechnung<br />
besitzt. Auf dem Arm Datensatz konnte ein zusätzlicher Speedup <strong>von</strong> 27 % gemessen<br />
werden.<br />
30 Universität Bielefeld, AG Technische Informatik
5 Diskussion<br />
Anzahl der Threads<br />
Die Anzahl der Threads pro Work-Group steuert den Parallelitätsgrad und hat starke<br />
Auswirkungen auf die Geschwindigkeit der <strong>GPU</strong>-Implementierung. Bei niedrigdimensionalen<br />
Datensätzen und verwendetem Soft Clustering sollte die Anzahl der verwendeten<br />
Threads nicht deutlich über der Dimension der Trainingsdaten liegen (Abb. 4.3).<br />
Ansonsten empfiehlt sich aber die Wahl einer eher hohen Threadanzahl (Abb. 4.3 und<br />
4.4).<br />
5.2.2 Wahl der Plattform<br />
Die in Kapitel 4 gezeigten experimentellen Ergebnisse zeigen ein recht unterschiedliches<br />
Laufzeitverhalten der zwei verwendeten Plattformen, während sich die<br />
Grafikkarten derselben Plattform häufig nur durch einen bestimmten konstanten Faktor<br />
im Speedup unterscheiden.<br />
Dies führt zu der Frage, welche Plattform sich für die <strong>GPU</strong>-Implementierung des<br />
NGPCA-Algorithmus am besten eignet. Eine pauschale Antwort lässt sich nicht geben,<br />
da beide Plattformen ihre Vor- und Nachteile haben. Die theoretischen Leistungsdaten<br />
(Tabelle 4.1) bescheinigen den AMD Karten einen deutlichen Vorteil bei der Berechnung<br />
<strong>von</strong> 64 Bit Fließkommazahlen, die Radeon HD 7970 hat sogar mehr als die<br />
6-fache Leistung der Nvidia GTX 570. Dennoch erzielen beide Nvidia Karten auf dem<br />
niedrigdimensionalen Arm Datensatz deutlich bessere Resultate (Abb. 4.1).<br />
Die Laufzeit der einzelnen Kernel ist auf dem Arm Datensatz aufgrund der niedrigdimensionalen<br />
Vektoren sehr gering. Folglich ist eine effiziente Verarbeitung der großen<br />
Menge an Kernelstarts besonders wichtig. Diese Aufgabe erfüllt die Nvidia Plattform<br />
scheinbar besser. Des Weiteren sind Kontrollstrukturen und Divergenz (Nischwitz<br />
et al., 2012) besonders für die AMD Plattform problematisch. Dies wird durch den im<br />
Vergleich zu Nvidia Karten sehr hohen Laufzeitanteil des Ranking-Kernels deutlich<br />
(Tabelle 4.4), der eine hohe Divergenz und relativ viele Kontrollstrukturen aufweist. Eine<br />
weitere mögliche Erklärung für das schlechte Laufzeitverhalten der AMD Plattform<br />
ist eine schlechtere Quellcode-Optimierung, denn gerade bei dem niedrigdimensionalen<br />
Datensatz lässt sich der Code durch z.B. Loop Unrolling stark optimieren.<br />
Bei aufwändigeren Berechnungen, z.B. beim Soft Clustering des CT Datensatzes mit<br />
vielen Eigenwerten (Abb. 4.2a), kann die Radeon HD 7970 ihre hohe 64 Bit Leistung<br />
nutzen. Hier ist sie der Nvidia GTX 570 deutlich überlegen. Sobald die Komplexität<br />
der Berechnung allerdings gesenkt wird, z.B. durch Verwendung <strong>von</strong> Hard Clustering<br />
(Abb. 4.2b), erreicht die Nvidia GTX 570 wieder den besten Speedup.<br />
Betrachtet man diese Ergebnisse, so ist die AMD Plattform besonders für rechenintensive<br />
Anwendungen mit wenigen Kontrollstrukturen und geringer Divergenz geeignet.<br />
Die Nvidia Architektur ist universell verwendbar, allerdings erreichen die Nvidia Karten<br />
eine deutlich geringere 64 Bit Leistung.<br />
Universität Bielefeld, AG Technische Informatik 31
6<br />
Ausblick<br />
Die im Rahmen dieser Bachelorarbeit entwickelte <strong>GPU</strong>-Implementierung konnte einen<br />
deutlichen Geschwindigkeitszuwachs gegenüber der CPU-Referenzimplementierung<br />
erreichen. Dennoch ergeben sich einige Verbesserungsmöglichkeiten, die in diesem Kapitel<br />
vorgeschlagen werden.<br />
6.1 EFORRLSA<br />
EFORRLSA (Möller, 2002) ist ein Verfahren zur Vereinheitlichung <strong>von</strong> RRLSA und<br />
Gram-Schmidt Orthonormalisierung. Für hochdimensionale Trainingsvektoren lässt<br />
sich so die Geschwindigkeit <strong>von</strong> RRLSA + Orthonormalisierung theoretisch um den<br />
Faktor 2 steigern. Zudem würde eine Verschmelzung <strong>von</strong> Hauptkomponentenanalyse<br />
und Orthonormalisierung die Zugriffe auf den globalen Speicher verringern, was sich<br />
ebenfalls positiv auswirkt.<br />
6.2 AVX, Nvidia Tesla, AMD Plattform<br />
Die CPU-Implementierung arbeitet noch nicht mit explizit implementierten AVX-<br />
Befehlen 1 , wodurch eine Geschwindigkeitssteigerung bis zu Faktor 4 erreicht werden<br />
könnte. Andererseits hätte eine Nvidia Tesla Karte mit einer 64 Bit Leistungsfähigkeit<br />
<strong>von</strong> 515 GFLOPs 2 die dreifache Leistung der Nvidia GTX 570. Viel sinnvoller erscheint<br />
jedoch eine Optimierung speziell für die AMD Plattform. Hierdurch könnte die enorme<br />
Leistungsfähigkeit der Radeon HD 7970 besser genutzt werden.<br />
1 http://software.intel.com/en-us/avx<br />
Datum: 21.09.2012<br />
2 http://www.nvidia.de/content/PDF/data-sheet/NV_DS_Tesla_C2075_<br />
Sept11_US_HR.pdf<br />
Datum: 23.09.2012<br />
32 Universität Bielefeld, AG Technische Informatik
6 Ausblick<br />
6.3 Orthonormalisierung<br />
Beim Soft Clustering nimmt der Speedup mit steigender Eigenwertanzahl ab, was<br />
durch die verwendete angepasste Gram-Schmidt Orthonormalisierung verursacht wird.<br />
Durch eine weitere Optimierung dieses Algorithmus könnte der Speedup signifikant<br />
erhöht werden. Eine andere Möglichkeit wäre der Austausch des Algorithmus durch<br />
ein besser für die <strong>GPU</strong> geeignetes Verfahren.<br />
Das klassische Gram-Schmidtsche Orthonormalisierungsverfahren lässt sich grundsätzlich<br />
besser parallelisieren als die modifizierte Variante. Zur Verbesserung der numerischen<br />
Stabilität kann das Verfahren iteriert werden. Dies vervielfacht den Berechnungsaufwand,<br />
dennoch kann das Verfahren eine höhere Performance als MGS liefern. (Lingen,<br />
2000).<br />
6.4 Adaptive Anpassung der parallelen Trainingsvektoren<br />
Das Hard Clustering würde ebenfalls <strong>von</strong> einer verbesserten Orthonormalisierung profitieren.<br />
Es bietet sich jedoch an, die relativ einfache Heuristik zur adaptiven Anpassung<br />
der parallelen Trainingsvektoren zu erweitern. Durch eine verbesserte Heuristik könnte<br />
dieser Parameter besser geschätzt werden, was die Auslastung der <strong>GPU</strong> verbessern bzw.<br />
unnötige Distanzberechnungen vermeiden würde.<br />
Universität Bielefeld, AG Technische Informatik 33
LITERATURVERZEICHNIS<br />
Literaturverzeichnis<br />
Amdahl, G. Limits of expectation. 2(1):88–97, 1988.<br />
Bishop, C. M. Natural [Neural] networks for pattern recognition. Oxford Univ. Press,<br />
Oxford [u.a.], 2008.<br />
Björck, A. Numerics of gram-schmidt orthogonalization. Linear Algebra and its Applications,<br />
197198(0):297 – 316, 1994.<br />
Fatahalian, K. und Houston, M. Gpus a closer look. In ACM SIGGRAPH 2008 classes,<br />
SIGGRAPH ’08, pages 11:1–11:11, New York, NY, USA, 2008. ACM.<br />
Giraud, L., Langou, J., und Rozloznik, M. The loss of orthogonality in the gram-schmidt<br />
orthogonalization process. Computers & Mathematics with Applications, 50(7):1069<br />
– 1075, 2005.<br />
Hoffmann, H. Unsupervised learning of visuomotor associations. 2004.<br />
Hoffmann, H., Schenck, W., und Möller, R. Learning visuomotor transformations for<br />
gaze-control and grasping. Biological Cybernetics, 93:119–130, 2005.<br />
Hyvärinen, A., Karhunen, J., und Oja, E. Independent component analysis. Wiley, New<br />
York [u.a.], 2001.<br />
Jolliffe, I. T. <strong>Principal</strong> component analysis. Springer, New York [u.a.], 1986.<br />
Kaiser, A. Implementierung und Test des Twin-Birth-Verfahrens für Neural <strong>Gas</strong> <strong>Principal</strong><br />
<strong>Component</strong> Analysis. Diplomarbeit, Technische Fakultät der Universität Bielefeld,<br />
Bielefeld, 2008.<br />
Kambhatla, N. und Leen, T. K.<br />
analysis, 1997.<br />
Dimension reduction by local principal component<br />
Lingen, F. J. Efficient gramschmidt orthonormalisation on parallel computers. Communications<br />
in Numerical Methods in Engineering, 16(1):57–66, 2000.<br />
Marsaglia, G. Xorshift rngs. Journal of Statistical Software, 08(i14), 2003.<br />
Martinetz, T., Berkovich, S., und Schulten, K. ‘neural-gas’ network for vector quantization<br />
and its application to time-series prediction. Neural Networks, IEEE Transactions<br />
on, 4(4):558 –569, jul 1993.<br />
Milde, B. und Schneider, M. Parallel implementation of classical Gram-Schmidt orthogonalization<br />
on CUDA graphics cards. 2009.<br />
34 Universität Bielefeld, AG Technische Informatik
LITERATURVERZEICHNIS<br />
Möller, R. Interlocking of learning and orthonormalization in RRLSA. Neurocomputing,<br />
49(1-4):429–433, 2002.<br />
Möller, R. First-order approximation of Gram-Schmidt orthonormalization beats deflation<br />
in coupled PCA learning rules. Neurocomputing, 69(13-15):1582–1590, 2006.<br />
Möller, R. und Hoffmann, H. An extension of neural gas to local pca. Neurocomputing,<br />
62(0):305 – 326, 2004.<br />
Möller, R. und Konies, A. Coupled principal component analysis. Neural Networks,<br />
IEEE Transactions on, 15(1):214 –222, jan. 2004.<br />
Munshi, A. OpenCL programming guide. Addison-Wesley, Upper Saddle River, NJ<br />
[u.a.], 2012.<br />
Murthy, G., Ravishankar, M., Baskaran, M., und Sadayappan, P. Optimal loop unrolling<br />
for gpgpu programs. In Parallel Distributed Processing (IPDPS), 2010 IEEE<br />
International Symposium on, pages 1 –11, april 2010.<br />
Nischwitz, A., Fischer, M., Habercker, P., Socher, G., Nischwitz, A., Fischer, M., Habercker,<br />
P., und Socher, G. Gpu programmierung mit cuda und opencl. In Computergrafik<br />
und Bildverarbeitung, pages 481–505. Vieweg+Teubner Verlag, 2012.<br />
Oh, K.-S. und Jung, K. Gpu implementation of neural networks. Pattern Recognition,<br />
37(6):1311 – 1314, 2004.<br />
Ouyang, S., Bao, Z., und Liao, G.-S. Robust recursive least squares learning algorithm<br />
for principal component analysis. Neural Networks, IEEE Transactions on, 11(1):<br />
215 –221, jan 2000.<br />
Rünger, G. und Schwind, M. Comparison of different parallel modified gram-schmidt<br />
algorithms. In Euro-Par 2005 Parallel Processing, volume 3648 of Lecture Notes in<br />
Computer Science, pages 622–622. 2005.<br />
Sanders, J. und Kandrot, E. CUDA by example. Addison-Wesley, Upper Saddle River,<br />
NJ [u.a.], 2010.<br />
Sanger, T. D. Optimal unsupervised learning in a single-layer linear feedforward neural<br />
network. Neural Networks, 2(6):459 – 473, 1989.<br />
Schenck, W. Adaptive internal models for motor control and visual prediction. MPI<br />
series in biological cybernetics ; 20. Logos-Verl., 2008.<br />
Welsch, R. Adaptive Lernratensteuerung für Neural <strong>Gas</strong> <strong>Principal</strong> <strong>Component</strong> Analysis.<br />
Bachelorarbeit, Technische Fakultät der Universität Bielefeld, 2009.<br />
Universität Bielefeld, AG Technische Informatik 35
A<br />
Verwendete Parameter<br />
A.1 Roboterarmsteuerung<br />
Parameter<br />
Wert<br />
Eigenwerte 4<br />
Iterationen 20.000<br />
Threadanzahl (Soft Clustering) 64<br />
Threadanzahl (Hard Clustering) 256<br />
A.2 CT Slices<br />
Parameter<br />
Wert<br />
Eigenwerte 20<br />
Iterationen 20.000<br />
Threadanzahl (Soft Clustering, Nvidia GTX 560 Ti) 256<br />
Threadanzahl (Soft Clustering, Nvidia GTX 570) 512<br />
Threadanzahl (Soft Clustering, AMD Radeon HD 6970) 512<br />
Threadanzahl (Soft Clustering, AMD Radeon HD 7970) 256<br />
Threadanzahl (Hard Clustering, Nvidia GTX 560 Ti) 512<br />
Threadanzahl (Hard Clustering, Nvidia GTX 570) 512<br />
Threadanzahl (Hard Clustering, AMD Radeon HD 6970) 512<br />
Threadanzahl (Hard Clustering, AMD Radeon HD 7970) 256<br />
36 Universität Bielefeld, AG Technische Informatik
B<br />
Quelltexte<br />
OpenCL Pseudozufallszahlengenerator<br />
1 / ∗ ∗<br />
2 ∗ c a l c u l a t e random v a l u e i n [ 0 . . 1 ]<br />
3 ∗ /<br />
4 i n l i n e r e a l r a n d x o r s h i f t 3 2 ( g l o b a l u i n t ∗ s t a t e ) {<br />
5 u i n t x = ∗ s t a t e ;<br />
6 x ˆ= x > 1 7 ;<br />
8 x ˆ= x
B<br />
Quelltexte<br />
OpenCL Parallel Selection Sort 1<br />
1 i n l i n e void s o r t (<br />
2 c o n s t a n t u i n t ∗ s o r t A r r I d x ,<br />
3 c o n s t a n t r e a l ∗ s o r t A r r V a l ,<br />
4 g l o b a l u i n t ∗ s o r t A r r I d x O u t ,<br />
5 g l o b a l u i n t ∗ h c I d x s )<br />
6 {<br />
7 c o n s t u i n t chunkIdx = g e t g r o u p i d ( 0 ) − 1 ;<br />
8<br />
9 # i f PARALLEL HARDCLUSTERING == 1<br />
10 / / s h i f t t o c u r r e n t chunk<br />
11 s o r t A r r I d x += PROTOTYPES ∗ chunkIdx ;<br />
12 s o r t A r r V a l += PROTOTYPES ∗ chunkIdx ;<br />
13 # e n d i f<br />
14<br />
15 f o r ( s i z e t i = g e t l o c a l i d ( 0 ) ; i < PROTOTYPES ; i +=<br />
g e t l o c a l s i z e ( 0 ) )<br />
16 {<br />
17 u i n t i D a t a = s o r t A r r I d x [ i ] ;<br />
18 r e a l iKey = s o r t A r r V a l [ i ] ;<br />
19<br />
20 / / compute u n i t r a n k i n g<br />
21 i n t rank = 0 ;<br />
22 f o r ( i n t j =0; j
B<br />
Quelltexte<br />
Verwendung der NGPCA-Klasse<br />
1 # i n c l u d e ”NGPCA.H”<br />
2<br />
3 / / . . .<br />
4<br />
5 / / params<br />
6 NGPCAParams params ;<br />
7 params . p r o t o t y p e s = 2 0 ;<br />
8 params . o u t p u t D i m e n s i o n = 2 ;<br />
9 params . l a m b d a I n i t = 1 0 ;<br />
10 params . o r t h o i n t e r v a l = 1 ;<br />
11 params . r e s e t c h e c k i n t e r v a l = 1 5 ;<br />
12<br />
13 params . p h i = 2 . 0 ;<br />
14 params . mu = 0 . 0 0 5 ;<br />
15 params . r h o i n i t = 2 ;<br />
16 params . r h o f i n a l = 0 . 0 1 ;<br />
17 params . e p s i l o n i n i t = 0 . 5 ;<br />
18 params . e p s i l o n f i n a l = 0 . 0 1 ;<br />
19 params . pcaType = RRLSA;<br />
20 params . potType = VCONST;<br />
21<br />
22 u i n t t h r e a d C o u n t = 512;<br />
23 bool h a r d C l u s t e r i n g = t r u e ;<br />
24 u i n t maxChunkSize = 2 0 ;<br />
25 bool adaptiveMaxChunkSize = t r u e ;<br />
26 u i n t a d a p t i v e M a x C h u n k S i z e I n t e r v a l = 1 5 ;<br />
27 u i n t d e v i c e I d = 0 ;<br />
28 u i n t i t e r a t i o n s = 20000;<br />
29<br />
30<br />
31 / / i n i t<br />
32 NGPCA ngpca ( params , t h r e a d C o u n t , h a r d C l u s t e r i n g , maxChunkSize<br />
, adaptiveMaxChunkSize , a d a p t i v e M a x C h u n k S i z e I n t e r v a l , d e v i c e I d ) ;<br />
33<br />
34 / / l o a d d a t a<br />
35 ngpca . l o a d F r o m F i l e ( ” i n p u t . mat ” ) ;<br />
36<br />
37 / / l e a r n<br />
38 ngpca . l e a r n ( i t e r a t i o n s ) ;<br />
39<br />
40 / / w r i t e o u t p u t<br />
41 ngpca . w r i t e ( ” i n p u t . mat . ngpca ” ) ;<br />
Listing B.3: Verwendung der NGPCA-Klasse<br />
Universität Bielefeld, AG Technische Informatik 39
B<br />
Quelltexte<br />
OpenCL Gram-Schmidt Orthonormalisierung<br />
1 i n l i n e<br />
2 void o r t h o P a r a l l e l (<br />
3 g l o b a l r e a l ∗ w,<br />
4 g l o b a l r e a l ∗ v ,<br />
5 g l o b a l r e a l ∗ l ,<br />
6 l o c a l r e a l ∗ tempBuffer , / / WORKGROUP SIZE∗WORKGROUP SIZE<br />
7 l o c a l r e a l ∗ norm ,<br />
8 l o c a l r e a l ∗ buf ) / / VEC SIZE<br />
9 {<br />
10 / ∗ ∗<br />
11 ∗ Vars<br />
12 ∗ /<br />
13 c o n s t u i n t l i n e a r L o c a l I d x = g e t l o c a l i d ( 0 ) + g e t l o c a l i d ( 1 ) ∗<br />
g e t l o c a l s i z e ( 0 ) ;<br />
14 c o n s t s i z e t t h r e a d s = g e t l o c a l s i z e ( 0 ) ∗ g e t l o c a l s i z e ( 1 ) ;<br />
15<br />
16 / ∗ ∗<br />
17 ∗ O r t h o n o r m a l i z e W<br />
18 ∗ /<br />
19 {<br />
20 / ∗ ∗<br />
21 ∗ n o r m a l i z e f i r s t column<br />
22 ∗ /<br />
23 {<br />
24 / / quadr<br />
25 t e m p B u f f e r [ l i n e a r L o c a l I d x ] = 0 ;<br />
26 f o r ( s i z e t yIdx = l i n e a r L o c a l I d x ; yIdx < VEC SIZE ; yIdx +=<br />
t h r e a d s ) {<br />
27 r e a l v a l = w[ yIdx ∗OUT DIM ] ;<br />
28<br />
29 buf [ yIdx ] = v a l ;<br />
30<br />
31 t e m p B u f f e r [ l i n e a r L o c a l I d x ] += v a l ∗ v a l ;<br />
32 }<br />
33 b a r r i e r (CLK LOCAL MEM FENCE) ;<br />
34<br />
35 / / r e d u c e quadr p e r t h r e a d<br />
36 s i z e t r e d u c t i o n I d x = t h r e a d s / 2 ;<br />
37 w h i l e ( r e d u c t i o n I d x != 0) {<br />
38 i f ( l i n e a r L o c a l I d x < r e d u c t i o n I d x ) {<br />
39 t e m p B u f f e r [ l i n e a r L o c a l I d x ] += t e m p B u f f e r [ l i n e a r L o c a l I d x +<br />
r e d u c t i o n I d x ] ;<br />
40 }<br />
41<br />
42 b a r r i e r (CLK LOCAL MEM FENCE) ;<br />
43 r e d u c t i o n I d x = r e d u c t i o n I d x / 2 ;<br />
44 }<br />
45<br />
46 / / c a l c u l a t e norm<br />
47 i f ( l i n e a r L o c a l I d x == 0) {<br />
48 ∗norm = SQRT( t e m p B u f f e r [ 0 ] ) ;<br />
49 }<br />
50 b a r r i e r (CLK LOCAL MEM FENCE) ;<br />
51<br />
52 / / n o r m a l i z e and s t o r e<br />
53 r e a l f i r s t L = l [ 0 ] ;<br />
40 Universität Bielefeld, AG Technische Informatik
B<br />
Quelltexte<br />
54 f o r ( s i z e t yIdx = l i n e a r L o c a l I d x ; yIdx < VEC SIZE ; yIdx +=<br />
t h r e a d s ) {<br />
55 r e a l n o r m a l i z e d = buf [ yIdx ] / (∗ norm ) ;<br />
56<br />
57 / / s t o r e r e s u l t<br />
58 w[ yIdx ∗OUT DIM] = n o r m a l i z e d ;<br />
59 v [ yIdx ∗OUT DIM] = n o r m a l i z e d ∗ f i r s t L ;<br />
60<br />
61 / / keep r e s u l t i n l o c a l memory<br />
62 buf [ yIdx ] = n o r m a l i z e d ;<br />
63 }<br />
64 }<br />
65<br />
66 / ∗ ∗<br />
67 ∗ c a l c u l a t e s c a l a r p r o d u c t s<br />
68 ∗ /<br />
69 f o r ( s i z e t c o l = 1 ; c o l < OUT DIM ; c o l ++) {<br />
70 b a r r i e r (CLK LOCAL MEM FENCE) ;<br />
71<br />
72 s i z e t o f f s e t = c o l ;<br />
73 s i z e t xIdx = c o l + g e t l o c a l i d ( 0 ) ;<br />
74<br />
75 w h i l e ( o f f s e t < OUT DIM) {<br />
76 / / i n i t<br />
77 t e m p B u f f e r [ l i n e a r L o c a l I d x ] = 0 ;<br />
78<br />
79 i f ( xIdx < OUT DIM) {<br />
80 / / sum up<br />
81 f o r ( s i z e t yIdx = g e t l o c a l i d ( 1 ) ; yIdx < VEC SIZE ; yIdx +=<br />
g e t l o c a l s i z e ( 1 ) ) {<br />
82 t e m p B u f f e r [ l i n e a r L o c a l I d x ] += w[ xIdx + yIdx ∗OUT DIM] ∗<br />
buf [ yIdx ] ;<br />
83 }<br />
84 }<br />
85 b a r r i e r (CLK LOCAL MEM FENCE) ;<br />
86<br />
87 / / r e d u c e<br />
88 s i z e t r e d u c t i o n I d x = t h r e a d s / 2 ;<br />
89 w h i l e ( r e d u c t i o n I d x >= g e t l o c a l s i z e ( 0 ) ) {<br />
90 i f ( l i n e a r L o c a l I d x < r e d u c t i o n I d x ) {<br />
91 t e m p B u f f e r [ l i n e a r L o c a l I d x ] += t e m p B u f f e r [ l i n e a r L o c a l I d x +<br />
r e d u c t i o n I d x ] ;<br />
92 }<br />
93<br />
94 b a r r i e r (CLK LOCAL MEM FENCE) ;<br />
95 r e d u c t i o n I d x = r e d u c t i o n I d x / 2 ;<br />
96 }<br />
97<br />
98 / / t e m p B u f f e r c o n t a i n s s c a l a r p r o d u c t s i n f i r s t<br />
WORKGROUP SIZE e l e m e n t s<br />
99<br />
100 / / s u b t r a c t<br />
101 i f ( xIdx < OUT DIM) {<br />
102 f o r ( s i z e t yIdx = g e t l o c a l i d ( 1 ) ; yIdx < VEC SIZE ; yIdx +=<br />
g e t l o c a l s i z e ( 1 ) ) {<br />
103 w[ xIdx + yIdx ∗OUT DIM] −= t e m p B u f f e r [ g e t l o c a l i d ( 0 ) ] ∗<br />
buf [ yIdx ] ;<br />
104 }<br />
Universität Bielefeld, AG Technische Informatik 41
B<br />
Quelltexte<br />
105 }<br />
106<br />
107 o f f s e t += g e t l o c a l s i z e ( 0 ) ;<br />
108 xIdx += g e t l o c a l s i z e ( 0 ) ;<br />
109 }<br />
110 b a r r i e r (CLK GLOBAL MEM FENCE) ;<br />
111<br />
112 / ∗ ∗<br />
113 ∗ c a l c u l a t e r e s u l t i n g column<br />
114 ∗ /<br />
115 / / quadr<br />
116 t e m p B u f f e r [ l i n e a r L o c a l I d x ] = 0 ;<br />
117 f o r ( s i z e t yIdx = l i n e a r L o c a l I d x ; yIdx < VEC SIZE ; yIdx +=<br />
t h r e a d s ) {<br />
118 r e a l v a l = w[ c o l + yIdx ∗OUT DIM ] ;<br />
119<br />
120 buf [ yIdx ] = v a l ;<br />
121<br />
122 t e m p B u f f e r [ l i n e a r L o c a l I d x ] += v a l ∗ v a l ;<br />
123 }<br />
124 b a r r i e r (CLK LOCAL MEM FENCE) ;<br />
125<br />
126 / / r e d u c e quadr p e r t h r e a d<br />
127 s i z e t r e d u c t i o n I d x = t h r e a d s / 2 ;<br />
128 w h i l e ( r e d u c t i o n I d x != 0) {<br />
129 i f ( l i n e a r L o c a l I d x < r e d u c t i o n I d x ) {<br />
130 t e m p B u f f e r [ l i n e a r L o c a l I d x ] += t e m p B u f f e r [ l i n e a r L o c a l I d x +<br />
r e d u c t i o n I d x ] ;<br />
131 }<br />
132<br />
133 b a r r i e r (CLK LOCAL MEM FENCE) ;<br />
134 r e d u c t i o n I d x = r e d u c t i o n I d x / 2 ;<br />
135 }<br />
136<br />
137 / / c a l c u l a t e norm<br />
138 i f ( l i n e a r L o c a l I d x == 0) {<br />
139 ∗norm = SQRT( t e m p B u f f e r [ 0 ] ) ;<br />
140 }<br />
141 b a r r i e r (CLK LOCAL MEM FENCE) ;<br />
142<br />
143 / / n o r m a l i z e & s t o r e<br />
144 r e a l c u r r L = l [ c o l ] ;<br />
145 f o r ( s i z e t yIdx = l i n e a r L o c a l I d x ; yIdx < VEC SIZE ; yIdx +=<br />
t h r e a d s ) {<br />
146 r e a l n o r m a l i z e d = w[ c o l + yIdx ∗OUT DIM] / (∗ norm ) ;<br />
147<br />
148 / / s t o r e r e s u l t<br />
149 w[ c o l + yIdx ∗OUT DIM] = n o r m a l i z e d ;<br />
150 v [ c o l + yIdx ∗OUT DIM] = n o r m a l i z e d ∗ c u r r L ;<br />
151<br />
152 / / keep r e s u l t i n l o c a l memory<br />
153 buf [ yIdx ] = n o r m a l i z e d ;<br />
154 }<br />
155 }<br />
156 }<br />
157 }<br />
Listing B.4: OpenCL Gram-Schmidt Orthonormalisierung<br />
42 Universität Bielefeld, AG Technische Informatik
C<br />
Kompilierung und Ausführung der<br />
Quelltexte<br />
Kompilierung<br />
Die Kompilierung in der PROG4 Umgebung kann einfach mittels vmk gestartet werden.<br />
Soll das Projekt separat übersetzt werden, so kann dies mit Hilfe <strong>von</strong> CMake geschehen:<br />
cmake . && make<br />
Ausführung<br />
Das Trainieren eines NGPCA-Netzwerkes mit 100 Prototypen, 20.000 Iterationszyklen<br />
und einer Ausgabedimension <strong>von</strong> 4 kann z.B. mit folgendem Kommando gestartet werden<br />
1 :<br />
gpu_ngpca \<br />
-d 4 -p 100 -i 20000 \<br />
train INPUT_FILE<br />
Bitte beachten Sie, dass die Angabe dieser Parameter obligatorisch ist, während weitere<br />
Parameter (siehe Anhang E) optional sind.<br />
1 Wobei INPUT FILE ein Platzhalter für den Pfad zur Eingabematrix ist<br />
Universität Bielefeld, AG Technische Informatik 43
D<br />
Verwendete Software-Bibliotheken<br />
Für die Umsetzung der vorliegenden Bachelorarbeit wurden folgende Software-<br />
Bibliotheken benutzt:<br />
• OpenCL 1.1 - GP<strong>GPU</strong> Schnittstelle<br />
http://www.khronos.org/opencl/<br />
• OpenCL C++ Bindings 1.1 - C++ Wrapper für OpenCL<br />
http://www.khronos.org/registry/cl/specs/<br />
opencl-cplusplus-1.1.pdf<br />
• Matrix 4-6-WS1 - Matrix Bibliothek<br />
˜/PROG4/libraries/Matrix-4-6-WS1<br />
• Boost Program Options 1.46.1 - Parser für Kommandozeilenargumente<br />
http://www.boost.org/doc/libs/1_46_1/doc/html/program_<br />
options.html<br />
• CMake - Build System (optional)<br />
http://www.cmake.org<br />
44 Universität Bielefeld, AG Technische Informatik
E<br />
Kommandozeilenparameter<br />
Die Applikation kann mittels gpu_ngpca [command] {options} gestartet werden,<br />
wobei die möglichen Kommandos und Optionen im Folgenden erläutert werden.<br />
Kommandos<br />
Befehl<br />
list-platforms<br />
list-devices<br />
train [inputFile]<br />
Wirkung<br />
Zeigt alle verfügbaren OpenCL-Plattformen an<br />
Zeigt alle verfügbaren OpenCL-Geräte an<br />
Trainiert ein NGPCA-Netzwerk<br />
Generelle Optionen<br />
Befehl<br />
Vorgabewert<br />
--help<br />
Zeigt die Hilfe an<br />
--device<br />
Auswahl des OpenCL Gerätes 0<br />
--doublePrecision<br />
Soll mit doppelter Genauigkeit gerechnet werden?<br />
1 (Ja)<br />
--threadCount<br />
Maximale Anzahl der parallelen Ausführungsstränge 512<br />
--maxChunkSize<br />
Maximale Anzahl an parallelen harten Vektorquantisierungen 20<br />
--adaptiveMaxChunkSize<br />
Soll die Anzahl an parallelen harten Vektorquantisierungen automatisch<br />
angepasst werden?<br />
1 (Ja)<br />
--adaptiveMaxChunkSizeInterval<br />
In welchem Intervall soll die automatische Anpassung durchgeführt 20<br />
werden?<br />
Universität Bielefeld, AG Technische Informatik 45
E<br />
Kommandozeilenparameter<br />
NGPCA Optionen<br />
Befehl<br />
Vorgabewert<br />
-i [ --iterations ]<br />
Anzahl der Iterationszyklen<br />
-p [ --prototypes ]<br />
Anzahl der zu verwendenden Prototypen<br />
-d [ --outputDimensions ]<br />
Ausgabedimension<br />
--lambdaInit<br />
Initiales Lambda 10<br />
--orthoInterval<br />
Intervall, in dem die Orthonormalisierung durchgeführt werden 1<br />
soll<br />
--resetCheckInterval<br />
Intervall, in dem die Prototypen überprüft und ggf. zurückgesetzt 15<br />
werden<br />
--phi<br />
Phi 2<br />
--rhoInit<br />
Rho (Anfangswert) 2<br />
--rhoFinal<br />
Rho (Endwert) 0.01<br />
--epsilonInit<br />
Epsilon (Anfangswert) 0.5<br />
--epsilonFinal<br />
Epsilon (Endwert) 0.001<br />
--hardClustering<br />
Soll harte Vektorquantisierung verwendet werden?<br />
1 (Ja)<br />
--pcaType<br />
Art der lokalen PCA (1 = RRLSA,2 = CouplePCA)<br />
1 (RRLSA)<br />
--potType<br />
Art der Potentialberechnung (1 = VConst,2 = TracePotential) 2 (TracePotential)<br />
46 Universität Bielefeld, AG Technische Informatik
Hiermit versichere ich, dass ich diese Bachelorarbeit selbständig bearbeitet habe.<br />
Ich habe keine anderen als die angegebenen Quellen und Hilfsmittel benutzt und<br />
entsprechende Zitate kenntlich gemacht.<br />
Bielefeld, den 26. September 2012<br />
Christian Menßen<br />
Universität Bielefeld, AG Technische Informatik 47