Подтвердить что ты не робот

Понимание размеров сетки CUDA, размеров блоков и организации потоков (простое объяснение)

Как организованы потоки с помощью графического процессора?

4b9b3361

Ответ 1

Оборудование

Если у устройства GPU есть, например, 4 блока многопроцессорности, и они могут запускать 768 потоков каждый: тогда в данный момент не более 4 * 768 потоков будут выполняться параллельно (если вы планируете больше потоков, они будут ждать своей очереди).

Программное обеспечение

потоки организованы в виде блоков. Блок выполняется многопроцессорным блоком. Нити блока могут быть проиндексированы (индексированы) с использованием 1Dimension (x), 2Dimensions (x, y) или 3Dim-индексов (x, y, z), но в любом случае xyz <= 768 для нашего примера (применяются другие ограничения x, y, z, см. руководство и возможности вашего устройства).

Очевидно, что если вам нужно больше, чем те 4 * 768 потоков, вам нужно больше 4 блоков. Блоки также могут быть проиндексированы 1D, 2D или 3D. Существует очередь блоков, ожидающих входа GPU (потому что в нашем примере GPU имеет 4 многопроцессора и всего 4 блока выполняются одновременно).

Теперь простой случай: обработка изображения 512x512

Предположим, мы хотим, чтобы один поток обрабатывал один пиксель (i, j).

Мы можем использовать блоки по 64 потока каждый. Тогда нам нужно 512 * 512/64 = 4096 блоков (поэтому иметь 512x512 потоков = 4096 * 64)

Как правило, организовать (чтобы упростить индексирование изображения) потоки в 2D блоках с blockDim = 8 x 8 (64 потока на блок). Я предпочитаю называть его threadPerBlock.

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

и 2D gridDim = 64 x 64 блока (требуется 4096 блоков). Я предпочитаю называть его numBlocks.

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

Ядро запускается следующим образом:

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

Наконец: будет что-то вроде "очереди из 4096 блоков", где блок ожидает назначения одного из мультипроцессоров GPU для выполнения его 64 потоков.

В ядре пиксель (i, j), который обрабатывается потоком, вычисляется следующим образом:

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

Ответ 2

предположим, что GPU 9800GT: 14 многопроцессоров, каждая из которых имеет 8 потоковых процессоров, а warpsize - 32, что означает, что каждый потокпроцессор обрабатывает до 32 потоков. 14 * 8 * 32 = 3584 - это максимальное количество потоков culturrent для исполнительного механизма.

если вы выполняете это ядро ​​с более чем 3584 потоками (скажем, 4000 потоков, и это не важно, как вы определяете блок и сетку. gpu будет относиться к ним как к одному):

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

то порядок выполнения этих двух функций выглядит следующим образом:

1.func1 выполняется для первых 3584 потоков

2.func2 выполняется для первых 3584 потоков

3.func1 выполняется для остальных потоков

4.func2 выполняется для остальных потоков

Ответ 3

Руководство по программированию CUDA должно стать хорошим местом для этого. Я также рекомендовал бы проверить введение CUDA из здесь.