Ich erinnere mich, dass ich den Hinweis bekommen habe, dass ich vermeiden sollte, Chars in CUDA-Kernen zu verwenden, weil die SMs 32-Bit-Ganzzahlen mögen. Gibt es eine Geschwindigkeitsbeschränkung für die Verwendung? Zum Beispiel, ist es langsamer
%Vor%als
%Vor%im Kernel-Code?
Hinweise:
Kurz notiert: In C / C ++ ist die Signiertheit von char
Implementierung definiert. Bei der Verwendung von char
zur 8-Bit-Ganzzahlarithmetik ist es daher sehr ratsam, signed char
oder unsigned char
speziell zu verwenden, wie es für die Berechnung erforderlich ist.
Ein negativer Leistungseinfluss durch die Verwendung von char
-Typen in CUDA ist wahrscheinlich . Ich würde die Verwendung von char
-Typen nicht empfehlen, es sei denn, Speichergrößenbeschränkungen (einschließlich Größenbeschränkungen für den gemeinsamen Speicher) oder die Art der Berechnung erfordern dies speziell.
CUDA ist eine C ++ - abgeleitete Sprache, die grundlegenden C ++ - Sprachspezifikationen folgt. C ++ (und C) gibt an, dass in einem Ausdruck Daten eines Typs, der enger als int
ist, vor dem Eingeben der Berechnung auf int
erweitert werden müssen. Sofern die Integer-Anweisungen der zugrunde liegenden Hardware nicht mit einer integrierten Konvertierung geliefert werden, bedeutet dies, dass zusätzliche Konvertierungsinstruktionen erforderlich sind, die die Anzahl der dynamischen Anweisungen erhöhen und wahrscheinlich die Leistung verringern.
Beachten Sie, dass Compiler von dem abstrakten C ++ - Ausführungsmodell unter der "Als-ob" -Regel abweichen dürfen: Solange sich der resultierende Code so verhält, als ob er dem abstrakten Modell folgt, dh seine Semantik identisch ist, ist er erlaubt um diese Umwandlungsvorgänge zu eliminieren. Meine jüngsten Experimente legen nahe, dass der CUDA 6.5-Compiler solche Optimierungen aggressiv anwendet und daher in der Lage ist, die meisten Konvertierungsoperationen entweder direkt zu eliminieren oder sie in andere Anweisungen zusammenzufassen.
Dies ist jedoch nicht immer möglich. Ein einfaches konstruiertes Beispiel ist der folgende Kernel, der bei der Instanziierung mit I2I.S32.S8
gegen T = char
eine zusätzliche Konvertierungsinstruktion T = int
enthält. Ich habe dies überprüft, indem ich cuobjdump --dump-sass
auf der ausführbaren Datei ausgeführt habe, um den Maschinencode auszugeben.
Neben der Erhöhung der Anzahl der Instruktionen kann auch eine negative Auswirkung auf die Performance durch die Verwendung von char
-Typen aufgrund der geringeren Speicherbandbreite auftreten. Das Design des Speicher-Subsystems der GPU ist derart, dass die insgesamt erreichbare globale Speicherbandbreite im Allgemeinen mit der Breite der Zugriffe zunimmt. Eine mögliche Erklärung dafür ist die endliche Tiefe der internen Warteschlangen, die Speicherzugriffe verfolgen, aber es können andere Faktoren am Werk sein.
Wenn char
-Typen auf Grund der Art eines Anwendungsfalls wie der Bildverarbeitung natürlich vorkommen, sollte man sich die Verwendung von 32-Bit-Verbindungstypen wie uchar4
ansehen. Die Verwendung des breiteren Typs während Lade- und Speicheroperationen ermöglicht eine verbesserte Speicherbandbreite. CUDA hat SIMD intrinsics , um gepackte char
-Daten zu manipulieren und diese zu verwenden reduzieren Sie dynamisch die Anzahl der dynamischen Befehle. Beachten Sie, dass die SIMD-Eigen- schaften nur auf Kepler-GPUs vollständig von Hardware unterstützt werden, auf Fermi-CPUs vollständig emuliert sind und teilweise auf Maxwell-GPUs emuliert werden. Ich habe anekdotische Beweise gesehen, dass selbst die emulierten Versionen immer noch einen Leistungsvorteil bieten, verglichen mit der separaten Verarbeitung jedes Bytes. Ich würde vorschlagen, dies im Zusammenhang mit einem bestimmten Anwendungsfall zu überprüfen.
Es gibt auch eine sehr kurze Referenz zu diesem Thema in Abschnitt 11.1.3 des CUDA Best Practices Guide :
Der Compiler muss gelegentlich Konvertierungsanweisungen einfügen und zusätzliche hinzufügen Ausführungszyklen. Dies ist der Fall für ...
- Funktionen, die auf char oder short funktionieren und deren Operanden im Allgemeinen in int konvertiert werden müssen.
- ...
Es ist nicht möglich, im allgemeinen Sinn zu sagen, ob es schneller / langsamer / unverändert ist, obwohl ich normalerweise keinen großen Unterschied erwarten würde. Sie haben recht, wenn Sie sagen, dass die Arithmetik für Zeichen in 32-Bit ist, aber ob dies eine Typumwandlung erfordert, hängt von dem Problem ab. Im Beispiel der Frage würde ich erwarten, den Compiler-Speicher a
und b
in 32-Bit-Registern zu sehen, und in meinen Experimenten um dieses Problem (beachte, ohne eine vollständige Reproduktion Fall ist es schwer, dies zu garantieren) Ich didn sehe keinen Unterschied in SASS . Für den Bereich des Codes, in dem alles in Registern ausgeführt wird, würde ich keinen Performance-Treffer erwarten.
Es gibt jedoch eine Auswirkung, wenn die Variablen char
aus dem Speicher verschoben werden. Da der char
vor der Verwendung in ein 32-Bit-Register umgewandelt werden muss, werden zusätzliche Anweisungen benötigt. Dies kann eine erhebliche Auswirkung haben oder nicht sein.
Nun gibt es auch einige Randfälle, die einen Unterschied machen können. Der Compiler könnte in der Lage sein, mehrere char
s in ein Register zu packen und sie mit Arithmetik zu extrahieren (Registereinsparung gegenüber arithmetischen Kosten). Sie können dieses Verhalten möglicherweise sogar mithilfe von Unionen erzwingen. Ob das Sparen die Anweisungen wert ist, variiert von Fall zu Fall. Ich kann mir keine anderen vorstellen, die im Moment einen erheblichen Casting Overhead verursachen würden.
Es ist offensichtlich, wenn Sie Variablen in 1 statt in 4 Byte speichern können, erhalten Sie eine 4x Speicher- und Bandbreiteneinsparung. Es gibt Dinge zu beachten:
Ich kenne keine wesentlichen Gründe, char
nach Möglichkeit anstelle von int
für Arithmetik zu verwenden, wo alles in Registern liegt, obwohl Sie beim Lesen / Schreiben in den Speicher einen Umwandlungsaufwand bezahlen müssen. Wenn Sie ein Array als char
statt als int
speichern, sollten Sie, wenn Sie vorsichtig sind, sowohl Bandbreite als auch Platz einsparen.
Tags und Links c c++ performance types cuda