Zweidimensionale Organisation von Threads

Bei parallelisierten Operationen auf Matrizen liegt es nahe, die Blöcke auf der CUDA so zweidimensional zu organisieren, dass jeder CUDA-Block sich mit einem entsprechenden Teilblock der Matrix beschäftigt.

Bei der zweidimensionalen Block-Aufteilung sollte beachtet werden,

Entsprechend bietet sich nur eine Aufteilung \(16 \times 16\) oder \(32 \times 32\) an. Bei \(32 \times 32\) bleibt wenig Spielraum für Register, so dass \(16 \times 16\) gerne verwendet wird.

Die Spezifikation mehrdimensionaler Aufteilungen erfolgt mit Hilfe von dim3-Objekten. So könnte eine Matrix aufgeteilt werden in \(16 \times 16\)-Blöcke:

unsigned int dim_per_block = 16;
unsigned int num_blocks_per_row = (A.numRows + dim_per_block - 1) /
   dim_per_block;
unsigned int num_blocks_per_col = (A.numCols + dim_per_block - 1) /
   dim_per_block;
dim3 block(dim_per_block, dim_per_block);
dim3 grid(num_blocks_per_row, num_blocks_per_col);
kernel_function<<grid, block>>>(/* ... */);

Aufgabe

Entwickeln Sie eine Kernel-Funktion gescal, die \(A \leftarrow \alpha A\) berechnet, d.h. alle Elemente mit \(\alpha\) skaliert. Um diese zu testen, empfiehlt es sich, die für CUDA angepasste Klasse hpc::cuda::GeMatrix aus <hpc/cuda/gematrix.h> und die copy-Operationen aus <hpc/cuda/copy.h> zu verwenden.