03.03.2013 Aufrufe

Effizientes Lösen linearer Gleichungssysteme über GF(2) - CDC ...

Effizientes Lösen linearer Gleichungssysteme über GF(2) - CDC ...

Effizientes Lösen linearer Gleichungssysteme über GF(2) - CDC ...

MEHR ANZEIGEN
WENIGER ANZEIGEN

Erfolgreiche ePaper selbst erstellen

Machen Sie aus Ihren PDF Publikationen ein blätterbares Flipbook mit unserer einzigartigen Google optimierten e-Paper Software.

2.6. OPTIMIERTES PROGRAMMIEREN MIT CUDA 33<br />

ist auch bei der Wahl der Blockgröße wichtig. Je nach Menge des benötigten<br />

gemeinsamen Speichers und der Register kann die Dimension entsprechend<br />

angepasst werden.<br />

Größere Blöcke führen nicht automatisch zu einer höheren Auslastung. Ein<br />

Block mit 512 Threads auf einem Device mit einer Compute Capability von<br />

1.1 führt zu einer Auslastung von 66%, da bei einem Maximum von 768<br />

Threads pro Multiprozessor nur ein Block aktiv sein kann. Besteht dagegen<br />

ein Block aus 256 Threads, so beträgt die Auslastung 100%, da drei Blöcke<br />

geladen werden können (Vergleiche B.2).<br />

Die Anzahl der Threads pro Block sollte durch die Warpgröße teilbar sein<br />

um ungenutzte Berechnungsressourcen durch Unterbelegung zu vermeiden.<br />

Wenn mehrere Blöcke pro Prozessor verarbeitet werden ist es außerdem empfehlenswert,<br />

dass jeder <strong>über</strong> mindestens 64 Threads verfügt. Besser ist jedoch<br />

ein Wert zwischen 128 und 256. Die Blockbreite und Blockhöhe sollte bei<br />

Devices mit einer Compute Capability von 2.0 durch die Warpgröße und bei<br />

Grafikkarten mit einer Compute Capability von 1.x durch die halbe Warpgröße<br />

teilbar sein. Dies liegt darin begründet, dass im besten Fall der erste<br />

Thread eines aktiven Warps auf das erste Element in dem Segment des globalen<br />

Speichers zugreift (Siehe auch 2.5.4).<br />

2.6.2 Optimierung von Speicherzugriffen<br />

Das Verbessern von Zugriffen auf die jeweiligen Speicher ist eines der wichtigsten<br />

Gebiete der Optimierung. Der erste Schritt ist Datenverkehr mit einer<br />

geringen Bandbreite zu meiden. Dazu gehört zum Beispiel der Transfer zwischen<br />

CPU und GPU, welcher <strong>über</strong> einen PCI Express (PCIe) Bus läuft. Des<br />

Weiteren sollten Daten in möglichst großen Paketen <strong>über</strong>tragen werden.<br />

Die peak Bandbreite des Grafikkartenspeichers ist höher, als die zwischen<br />

Host und Device. Daher kann in einigen Fällen eine bessere Gesamtzeit erreicht<br />

werden, wenn ein Kernel auch Anweisungen bearbeitet, die nicht parallel<br />

durchgeführt werden können anstatt diese von der CPU berechnen zu<br />

lassen. Vor allem sollten Datenstrukturen auf der Grafikkarte verbleiben, die<br />

nur zum Speichern von Zwischenschritten benötigt werden.<br />

Anfragen an den globalen Speicher haben durch die auftretende Latenz eine<br />

geringe Bandbreite, wodurch es empfehlenswert ist öffter Daten in den<br />

gemeinsamen Speicher zu <strong>über</strong>tragen. Außerdem sollten so oft wir möglich<br />

Adressräume verwendet werden, die <strong>über</strong> einen Cache verfügen, wie der für<br />

Texturen und Konstanten.

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!