5 Stimmen

matrix-multiplikation in cuda

Sagen wir, ich möchte zwei Matrizen miteinander multiplizieren, 50 mal 50. Ich habe 2 Möglichkeiten, Threads und Blöcke anzuordnen.

a) ein Thread zur Berechnung jedes Elements der Ergebnismatrix. Ich habe also eine Schleife im Thread multipliziert eine Zeile und eine Spalte.

b) ein Thread für jede Multiplikation. Für jedes Element der Ergebnismatrix werden 50 Threads benötigt. Nachdem die Multiplikationen durchgeführt wurden, kann ich die Ergebnisse durch binäre Reduktion summieren.

Ich war mir nicht sicher, welchen Weg ich nehmen sollte, also nahm ich B. Das war nicht ideal. Es war sogar sehr langsam. Irgendeine Idee, warum? Meine Vermutung wäre, dass es einfach zu viele Threads gibt und diese die meiste Zeit auf Ressourcen warten, ist das wahr?

6voto

Jonathan Dursi Punkte 48657

Wie bei so vielen Dingen in der Hochleistungsinformatik ist auch hier der Schlüssel zum Verständnis der Leistung das Verständnis der Speichernutzung.

Wenn Sie einen Thread verwenden, um eine Multiplikation durchzuführen, müssen Sie für diesen Thread zwei Daten aus dem Speicher holen, sie multiplizieren und dann eine logarithmische Anzahl von Additionen durchführen. Das sind drei Speicherzugriffe für eine Multiplikation, eine Addition und ein Bit - die arithmetische Intensität ist sehr gering. Die gute Nachricht ist, dass es auf diese Weise viele, viele Threads mit Aufgaben gibt, von denen jede nur ein winziges Stückchen Speicher/Register benötigt, was gut für die Auslastung ist; aber das Verhältnis von Speicherzugriff zu Arbeit ist schlecht.

Der einfache Ansatz, bei dem ein Thread ein Punktprodukt ausführt, hat die gleiche Art von Problem - jede Multiplikation erfordert zwei Speicherzugriffe zum Laden. Die gute Nachricht ist, dass es nur einen Speicherzugriff auf den globalen Speicher für das gesamte Punktprodukt gibt, und Sie vermeiden die binäre Reduktion, die nicht so gut skaliert und eine Menge Synchronisation erfordert; die Kehrseite ist, dass es jetzt viel weniger Threads gibt, was zumindest Ihr (b) Ansatz für Sie getan hat.

Jetzt wissen Sie, dass es eine Möglichkeit geben sollte, mehr Operationen pro Speicherzugriff als diese zu tun; für quadratische NxN-Matrizen gibt es N^3 Arbeit, um die Multiplikation zu tun, aber nur 3xN^2 Elemente - so sollten Sie in der Lage sein, einen Weg zu finden, weit mehr als 1 Berechnung pro 2ish Speicherzugriffe zu tun.

Der Ansatz, der im CUDA SDK verfolgt wird, ist der beste Weg - die Matrizen werden in Kacheln unterteilt, und Ihr Ansatz (b) - ein Thread pro Ausgabeelement - wird verwendet. Der Schlüssel liegt jedoch darin, wie die Threads angeordnet sind. Indem man ganze kleine Teilmatrizen aus dem langsamen globalen Speicher in den gemeinsamen Speicher zieht und von dort aus Berechnungen durchführt, ist es möglich, viele Multiplikationen und Additionen mit jeder Zahl durchzuführen, die man aus dem Speicher eingelesen hat. Dieser Ansatz ist in vielen Anwendungen am erfolgreichsten, da die Datenbeschaffung - sei es über ein Netzwerk, aus dem Hauptspeicher einer CPU oder aus dem Off-Chip-Speicher einer GPU - oft viel länger dauert als die Verarbeitung der Daten.

Es gibt Dokumente auf den CUDA-Seiten von NVidia (insb. http://developer.nvidia.com/object/cuda_training.html ), die ihr SDK-Beispiel sehr gut beschreiben.

3voto

Mitch Wheat Punkte 287474

Haben Sie einen Blick in die CUDA Dokumentation geworfen: Cuda-Programmiermodell

Außerdem gibt es einen Beispiel-Quellcode: Matrix-Multiplikation

2voto

Dirk Eddelbuettel Punkte 345316

Haben Sie sich angesehen

$SDK/nvidia-gpu-sdk-3.1/C/src/matrixMul

d.h. das Beispiel für die Matrixmultiplikation im SDK?

0voto

Devin Lane Punkte 944

Wenn Sie dies nicht selbst implementieren müssen, verwenden Sie einfach eine Bibliothek - CUBLAS, MAGMA usw. bieten abgestimmte Implementierungen der Matrixmultiplikation.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X