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.
GPU-Design von Natur aus begünstigt keine Verzweigung, sollten Sie Ihre Codes an diese Eigenschaft anpassen. – tibetty