2017-08-17 3 views
4

Ich las diesen Artikel:Warum ein „if-else“ Anweisung (in GPUs Code) wird die Leistung halbiert

FPGA or GPU? - The evolution continues

Und jemand ein Kommentar, in dem fügte er schrieb:

Da GPUs SIMD sind, wird jeder Code mit einer "if-else" -Anweisung Ihre Leistung in zwei Hälften schneiden . Die Hälfte der Kerne führt den if-Teil der -Anweisung aus, während die Hälfte der Kerne im Leerlauf ist und dann die andere Hälfte Kerne die Else-Berechnungen ausführen wird, während die erste Hälfte der Kerne im Leerlauf bleiben.

Ich kann nicht verstehen warum?

Warum mit GPU (d. H. OpenCL) bei Verwendung if-else wird die Leistung in eine Hälfte geschnitten?

+0

GPU-Design von Natur aus begünstigt keine Verzweigung, sollten Sie Ihre Codes an diese Eigenschaft anpassen. – tibetty

Antwort

10

Zweige im Allgemeinen nicht die Leistung beeinflussen, aber Zweig Divergenz tut. Das heißt, zwei Threads nehmen unterschiedliche Pfade (z. B. erfüllt einer die if Bedingung, der andere nicht). Da alle Threads einer GPU dieselbe "Codezeile" ausführen, müssen einige Threads warten, während der Code, der nicht Teil ihres Pfades ist, ausgeführt wird.
Nun, das ist nicht wirklich wahr, da nur alle Threads in einem Warp (NVIDIA) oder Wavefront (AMD) dieselbe "Codezeile" ausführen. (Derzeit ist die Kettschlichte von NVIDIA GPUs 32 und die wafefront Größe von AMD GPUs ist 64.)

Also, wenn es ein if-else Block in Ihrem Kernel das Worst-Case-Szenario ist in der Tat eine 50% ige Leistungsabfall. Und noch schlimmer: Wenn es n mögliche Verzweigungen gibt, kann die Leistung bis auf 1/n der Leistung ohne Divergenz (das heißt keine Verzweigungen oder alle Threads in einer Warp/Wafefront nehmen den gleichen Pfad) verringern. Natürlich muss für solche Szenarien der gesamte Kernel in ein if-else (oder switch) Konstrukt eingebettet sein.

Aber wie oben beschrieben, geschieht dies nur, wenn die Threads, die unterschiedliche Pfade benutzen, sich in derselben Warp/Wafefront befinden. Es liegt also an Ihnen, Ihren Code zu schreiben/Daten neu anzuordnen/den Algorithmus/... auszuwählen, um Verzweigungen so weit wie möglich zu vermeiden.

Tl; DR: Es kann Verzweigungen geben, aber wenn verschiedene Threads unterschiedliche Verzweigungen haben, müssen sie sich in verschiedenen Warps/Wafefronts befinden, um Divergenz und somit Leistungsverlust zu vermeiden.

+0

Die meiste Zeit haben die Leute Angst vor Ästen auf einer GPU, sobald sie von Divergenz lesen. Die meisten Zeitkerne laufen jedoch nicht annähernd in Spitzenleistung, sind aber im Durchsatz durch Speicherbandbreite, gemeinsamen Speicher oder fehlende verfügbare Warps begrenzt. Dann hat die Divergenz nur sehr begrenzte Auswirkungen auf die Leistung. –

+0

@ JanLucas: Sie haben recht, dass fast nie Spitzenleistung erreicht wird, aber Verzweigung Divergenz macht es noch schlimmer. Natürlich würde eine Halbierung der Leistung für einen Kernel, der in der Nähe der Spitzenleistung laufen könnte, zu einem größeren Leistungsverlust führen, aber nur in absoluten Zahlen, nicht in relativen Zahlen. Ich denke, es ist ein besseres Argument, sich nicht zu sehr um Divergenzen zu kümmern, da oft der Kernel sich oft nur in einem kleinen Teil des Kerns in Zweige teilt (zB sind nur 10% von der Divergenz betroffen und somit ist der Leistungsabfall ziemlich gering) . – Shadow

+0

@JanLucas: Aber es ist nie schlecht, über Divergenz nachzudenken, da es oft mit einem schlechten Datenlayout einhergeht, das zu unkozensierten Speicherzugriffen und damit zu einer Verschwendung wertvoller Speicherbandbreite führt. – Shadow

Verwandte Themen