2010-11-04 10 views
5

Ich habe den Programmierleitfaden und die Best Practices-Anleitung gelesen und erwähnt, dass der Global Memory-Zugriff 400-600 Zyklen benötigt. Ich habe auf den anderen Speichertypen wie Textur-Cache, Konstanten-Cache, Shared Memory nicht viel gesehen. Register haben eine Speicherwartezeit von 0.Wie viele Speicherlatenzzyklen pro Speicherzugriffstyp in OpenCL/CUDA?

Ich denke, konstante Cache ist das gleiche wie die Register, wenn alle Threads die gleiche Adresse im konstanten Cache verwenden. Im schlimmsten Fall bin ich mir nicht so sicher.

Shared Memory ist wie Register, solange keine Bankkonflikte bestehen? Wenn ja, wie entfaltet sich die Latenz?

Was ist mit Textur-Cache?

Antwort

4

Die Latenz zu den Shared/Constant/Texture-Speichern ist gering und hängt davon ab, welches Gerät Sie haben. Im Allgemeinen sind GPUs als eine Durchsatzarchitektur ausgelegt, was bedeutet, dass durch das Erzeugen von genügend Threads die Latenz zu den Speichern, einschließlich des globalen Speichers, verborgen ist.

Der Grund, warum die Guides über die Latenz zum globalen Speicher sprechen, ist, dass die Latenz um Größenordnungen höher ist als die anderer Speicher, was bedeutet, dass sie die dominierende Latenz für die Optimierung ist.

Sie erwähnten insbesondere konstanten Cache. Sie sind völlig richtig, wenn alle Threads innerhalb eines Warps (d. H. Eine Gruppe von 32 Threads) auf dieselbe Adresse zugreifen, dann gibt es keine Strafe, d. H. Der Wert wird aus dem Cache gelesen und an alle Threads gleichzeitig gesendet. Wenn Threads jedoch auf andere Adressen zugreifen, müssen die Zugriffe serialisieren, da der Cache jeweils nur einen Wert bereitstellen kann. Wenn Sie den CUDA Profiler verwenden, wird dieser unter dem Serialisierungszähler angezeigt.

Gemeinsamer Speicher kann im Gegensatz zu konstantem Cache eine viel höhere Bandbreite bereitstellen. Weitere Einzelheiten und Erläuterungen zu Bankkonflikten und deren Auswirkungen finden Sie unter CUDA Optimization.

+0

Lohnt es sich immer Konstanten-Cache zu verwenden, wenn zum Beispiel alle Threads auf 1000 Floats zugreifen? Wäre das wie ein 1000 liest aus einem Register? Der Leitfaden sagte die Verwendung von konstanten Cache auf diese Weise skaliert linear richtig? – smuggledPancakes

+0

Wenn alle Threads in einer Iteration einer Schleife auf den gleichen Wert zugreifen, können Sie den Konstantencache verwenden. Der konstante Cache wird aufgrund der räumlichen Lokalität einen gewissen Vorteil bieten (auf Fermi kann der L1-Cache das gleiche erreichen, aber dadurch bleibt L1 für andere Daten frei). Nachdem ich das gesagt habe, wende ich mich hauptsächlich an Fermi und benutze niemals "__constant__", ich benutze nur const viel und lasse den Compiler es herausfinden! In deinem Fall würde ich beispielsweise den Kernel arg als 'const float * const myfloatarray' übergeben. Ich würde empfehlen, den Visual Profiler immer auf Serialisierung zu überprüfen, nur für den Fall, dass Sie etwas übersehen haben. – Tom

+0

Man könnte hinzufügen, dass Cache-Zeilen 128 Byte (32 Byte) für L1 (L2) sind, also sprechen wir über Adressen, die in die gleichen Zeilen fallen (nicht notwendigerweise dieselben Adressen). Einige Zahlen zu anderen Latenzzeiten finden Sie [hier] (http://stackoverflow.com/questions/6744101/fermi-l2-cache-hit-latency). –

6

Für (Kepler) Tesla K20 die Latenzen sind wie folgt:

globalen Speicher: 440 Takte
Konstantenspeicher
        L1: 48 Takte
        L2: 120 Uhren
Gemeinsamer Speicher: 48 Uhren
Texturspeicher
        L1: 108 Uhren
        L2: 240 Uhren

Wie kann ich wissen? Ich habe die Microbenchmarks ausgeführt, die von den Autoren von Demystifying GPU Microarchitecture through Microbenchmarking beschrieben wurden. Sie liefern ähnliche Ergebnisse für die ältere GTX 280.

Dies wurde auf einem Linux-Cluster gemessen, der Computerknoten, auf dem ich die Benchmarks ausgeführt hatte, wurde von keinen anderen Benutzern verwendet oder führte keine anderen Prozesse aus. Es ist BULLX Linux mit einem Paar 8 Kern Xeons und 64 GB RAM, nvcc 6.5.12. Ich habe die sm_20 zu sm_35 für das Übersetzen geändert.

Es gibt auch ein operands cost Kapitel in PTX ISA, obwohl es nicht sehr hilfreich ist, es wiederholt nur, was Sie bereits erwarten, ohne genaue Zahlen zu geben.

+0

Ich benutze auch Tesla K20, und ich habe versucht, das gleiche Mikrobenzeichen zu verwenden, das Sie erwähnten. Konnten Sie 'global.cu' problemlos ausführen? Ich frage, weil ich ein Problem mit illegalen Speicherzugriffen habe - ich habe diese Frage [hier] gepostet (http://stackoverflow.com/questions/36416843/how-to-write-a-pointer-chasing-benchmark-using-) 64-Bit-Zeiger-in-Cuda). Ich habe mich gefragt, ob Sie Änderungen am Kernel-Code vorgenommen haben, damit er für Sie funktioniert? – Kajal

+0

@ kv.333 Es war vor einiger Zeit. Ich erinnere mich, dass es einige Probleme gab und nicht alle Benchmarks lief. Ich erinnere mich nicht an welche. –

Verwandte Themen