Verständnis CUDA-raster, block Abmessungen und Gewinde-Organisation (einfache Erklärung) [closed]

StackOverflow https://stackoverflow.com/questions/2392250

  •  25-09-2019
  •  | 
  •  

Frage

Wie werden threads organisiert werden, ausgeführt durch einen GPU?

War es hilfreich?

Lösung

Hardware

Wenn eine GPU-Gerät hat, für Beispiel, 4 multiprocessing-Einheiten, und Sie laufen können, 768 threads jeweils:dann zu einem bestimmten Zeitpunkt nicht mehr als 4*768 threads werden wirklich parallel läuft (wenn Sie geplant haben mehrere threads, die Sie warten).

Software

threads sind in Blöcken organisiert.Ein block wird ausgeführt, indem ein multiprocessing-Einheit.Die threads eines Blocks werden kann gekennzeichnet (indiziert) mit 1Das Maß(x), 2Dimensions (x,y) oder 3Dim-Indizes (x,y,z), aber in jedem Fall xyz <= 768 für unser Beispiel (andere Einschränkungen gelten für x,y,z, finden Sie in der Anleitung und auf Ihrem Gerät-Fähigkeit).

Natürlich, wenn Sie mehr als diese 4*768 threads, brauchen Sie mehr als 4 Blöcke.Blöcke können auch indiziert 1D, 2D oder 3D.Es gibt eine Warteschlange von Blöcke warten auf Sie GPU (weil, in unserem Beispiel die GPU verfügt über 4 Multiprozessoren und nur 4 blocks sind werden gleichzeitig ausgeführt).

Nun ein einfacher Fall:Verarbeitung eine 512x512-Bild

Angenommen, wir möchten einen thread, um einen pixel (i,j).

Wir können Blöcke von 64 threads je.Dann müssen wir 512*512/64 = 4096 blocks (so haben 512x512 threads = 4096*64)

Es ist üblich, sich zu organisieren (damit die Indizierung das Bild einfacher) die Fäden in der 2D-Blöcke mit blockDim = 8 x 8 (64 threads pro block).Ich nenne es lieber threadsPerBlock.

dim3 threadsPerBlock(8, 8);  // 64 threads

- und 2D-gridDim = 64 x 64 Blöcken (4096 blocks erforderlich).Ich nenne es lieber numBlocks.

dim3 numBlocks(imageWidth/threadsPerBlock.x,  /* for instance 512/8 = 64*/
              imageHeight/threadsPerBlock.y); 

Der kernel wird wie folgt gestartet:

myKernel <<<numBlocks,threadsPerBlock>>>( /* params for the kernel function */ );       

Schließlich:es wird so etwas wie "eine Warteschlange von 4096 blocks", wo ein block ist zu warten, vergeben von der Multiprozessoren der GPU, um seine 64 threads ausgeführt.

In der kernel das pixel (i,j) verarbeitet werden, die von einem thread berechnet sich so:

uint i = (blockIdx.x * blockDim.x) + threadIdx.x;
uint j = (blockIdx.y * blockDim.y) + threadIdx.y;

Andere Tipps

eine 9800GT GPU annehmen: 14 Multiprozessoren haben jeden 8 threadprocessors und warpsize ist 32, das bedeutet, dass jeder threadprocessor Griff bis zu 32 Fäden. 14 * 8 * 32 = 3584 ist die maximale Anzahl von Threads Actuall cuncurrent.

Wenn Sie diesen Kernel mit mehr als 3584 Threads ausführen (etwa 4000 Fäden und es ist nicht wichtig, wie Sie den Block und Gitter definieren gpu sie wie die gleiche behandeln.):

func1();
__syncthreads();
func2();
__syncthreads();

dann die Reihenfolge der Ausführung dieser beiden Funktionen sind wie folgt:

1.func1 für die ersten 3584 Threads ausgeführt wird

2.func2 für die ersten 3584 Threads ausgeführt wird

3.func1 wird für die verbleibenden Fäden

ausgeführt

4.func2 wird für die verbleibenden Fäden

ausgeführt
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top