Ich finde keine Verbesserung der Geschwindigkeit mit Shared Memory auf einem NVIDIA Tesla M2050 mit etwa 49K Shared Memory pro Block. Eigentlich wenn ich zuteile Ein großes Char-Array im Shared Memory verlangsamt mein Programm. Zum Beispiel
%Vor%gibt mir langsamere Laufzeiten als
%Vor%Das Programm greift nur auf die ersten 100 Zeichen der Datenbank zu, also auf den zusätzlichen Speicherplatz ist unnötig. Ich kann nicht herausfinden, warum das passiert. Jede Hilfe wäre willkommen. Danke.
Der Grund für die relativ schlechte Leistung von CUDA Shared Memory bei der Verwendung von größeren Arrays kann mit der Tatsache zu tun haben, dass jeder Multiprozessor eine begrenzte Menge an verfügbarem Shared Memory hat.
Jeder Multiprozessor beherbergt mehrere Prozessoren; für moderne Geräte, typischerweise 32, die Anzahl der Fäden in einer Kette. Dies bedeutet, dass bei Abwesenheit von Divergenz oder Speicherstörungen die durchschnittliche Verarbeitungsrate 32 Befehle pro Zyklus beträgt (die Latenz ist aufgrund des Pipelining hoch).
CUDA plant mehrere Blöcke zu einem Multiprozessor. Jeder Block besteht aus mehreren Ketten. Wenn ein Warp bei einem globalen Speicherzugriff blockiert wird (selbst zusammengewachsene Zugriffe haben eine hohe Latenz), werden andere Warps verarbeitet. Das verbirgt die Latenz effektiv, weshalb der globale Speicher mit hoher Latenz in GPUs akzeptabel ist. Um die Latenz effektiv zu verbergen, müssen Sie genügend zusätzliche Warps ausführen, bis der angehaltene Warp fortgesetzt werden kann. Wenn alle Warps bei Speicherzugriffen blockiert sind, können Sie die Latenz nicht mehr verbergen.
Shared Memory wird Blöcken in CUDA zugewiesen und auf einem einzelnen Multiprozessor auf dem GPU-Gerät gespeichert. Jeder Multiprozessor hat eine relativ kleine feste Menge an gemeinsamem Speicherraum. CUDA kann nicht mehr Blöcke an Multiprozessoren einplanen, als die Multiprozessoren in Bezug auf die gemeinsame Nutzung von Speicher und Register unterstützen können. Mit anderen Worten, wenn die Menge an gemeinsam genutztem Speicher auf einem Multiprozessor X ist und jeder Block Y gemeinsamen Speicher benötigt, plant CUDA nicht mehr als Boden- (X / Y-) Blöcke zu jedem Multiprozessor (es könnte weniger sein, da es solche gibt) andere Einschränkungen, wie z. B. die Verwendung von Registern.)
Ergo: Durch die Erhöhung der gemeinsamen Speicherbelegung eines Blocks verringern Sie möglicherweise die Anzahl der aktiven Warps - die Belegung - Ihres Kernels und beeinträchtigen dadurch die Leistung. Sie sollten in Ihren Kernel-Code schauen, indem Sie mit dem Flag -Xptxas="- v" kompilieren; Dies sollte Ihnen registrieren und geteilt & amp; Konstante Speicherbelegung für jeden Kernel. Verwenden Sie diese Daten und Ihre Kernel-Startparameter sowie andere erforderliche Informationen in der neuesten Version des CUDA-Belegungsrechners, um festzustellen, ob Sie von der Belegung betroffen sind.
BEARBEITEN:
Um den anderen Teil Ihrer Frage zu beantworten, unter der Annahme, dass keine Speicherbankkonflikte auftreten und die globalen Speicherzugriffe perfekt zusammengeführt werden, gibt es zwei Aspekte: Latenz und Bandbreite. Die Latenz des gemeinsam genutzten Speichers ist geringer als die des globalen Speichers, da der gemeinsame Speicher auf dem Chip liegt. Die Bandbreite wird sehr ähnlich sein. Ergo, wenn Sie die Latenz des globalen Speicherzugriffs durch Koaleszieren verbergen können, gibt es keine Nachteile (Hinweis: Das Zugriffsmuster ist hier wichtig, da der gemeinsam genutzte Speicher potenziell vielfältigere Zugriffsmuster mit wenig bis keinem Leistungsverlust ermöglicht Vorteile der Verwendung von gemeinsam genutztem Speicher, selbst wenn Sie die gesamte globale Speicherlatenz ausblenden können.
Die Menge der auf der GPU verfügbaren Ressourcen ist begrenzt. Die Anzahl der Blöcke, die gleichzeitig ausgeführt werden, ist in etwa proportional zur Größe des gemeinsamen Speichers pro Block.
Dies erklärt, warum die Laufzeit langsamer ist, wenn Sie den Kernel starten, der sehr viel Shared Memory verwendet.
Tags und Links cuda