Что такое GPU и почему он параллельный

Видеокарта быстра в графике не потому, что её ядра умнее, а потому, что их тысячи и они работают одновременно.

GPU — процессор с тысячами простых ядер, выполняющих одну и ту же программу над разными данными параллельно (модель SIMT).

Зачем это знать

Шейдер пишут для одного элемента (вершины или пикселя), но исполняется он сразу на тысячах ядер для тысяч элементов. Если не понимать параллельную природу GPU, легко написать шейдер, который ломает эту модель (ветвления, зависимости между пикселями) и тормозит.

CPU против GPU

СвойствоCPUGPU
Ядерединицы–десяткитысячи
Каждое ядромощное, сложноепростое
Сильно впоследовательной логикемассовом параллелизме
Пример задачиОС, ветвистый кодцвет миллионов пикселей

Почему графика так параллельна

Цвет каждого пикселя считается независимо от соседей. Два миллиона пикселей — два миллиона независимых задач. Это идеальная пища для тысяч ядер: дай каждому ядру по пачке пикселей, и они посчитают всё разом.

# Сравним «время» работы при последовательной и параллельной модели
pixels = 2_073_600           # Full HD
work_per_pixel = 1           # условная единица работы

cpu_cores = 8
gpu_cores = 2048

cpu_time = pixels * work_per_pixel / cpu_cores
gpu_time = pixels * work_per_pixel / gpu_cores
print("Условное время CPU:", round(cpu_time))
print("Условное время GPU:", round(gpu_time))
print("Ускорение:", round(cpu_time / gpu_time), "раз")

Вывод:

Условное время CPU: 259200
Условное время GPU: 1012
Ускорение: 256 раз

При одинаковой работе на пиксель тысячи ядер дают огромный выигрыш — именно поэтому графику считает GPU, а не CPU.

Модель SIMT

SIMT — Single Instruction, Multiple Threads. Ядра объединены в группы (warp/wavefront по 32–64 потока), которые выполняют одну инструкцию синхронно, но над разными данными. Это как рота солдат, марширующая в ногу: команда одна, ног много.

SIMT: одна инструкция, много потоков

инструкция: color = texture(uv)
   поток0  поток1  поток2  ...  поток31
    uv0     uv1     uv2          uv31
все считают ОДНУ И ТУ ЖЕ строку кода одновременно

Как работает под капотом

Когда внутри warp потоки расходятся по веткам if (одни идут в then, другие в else), GPU вынужден выполнить обе ветки последовательно, маскируя неактивные потоки — это divergence, и он замедляет шейдер. Поэтому в шейдерах избегают тяжёлых расходящихся ветвлений. Память GPU тоже оптимизирована под параллелизм: соседние потоки должны читать соседние адреса (coalesced access).

Частые ошибки

  • Писать в шейдере ветвистую логику, как на CPU, — дивергенция warp'ов бьёт по скорости.
  • Думать, что GPU быстрее CPU «вообще» — он быстрее только на массово-параллельных задачах.
  • Ожидать, что один пиксель может прочитать результат соседнего в том же проходе — потоки независимы.

Итоги

  • GPU = тысячи простых ядер против единиц мощных у CPU.
  • Графика параллельна: цвет каждого пикселя независим.
  • SIMT: warp из десятков потоков исполняет одну инструкцию синхронно.
  • Расходящиеся ветвления (divergence) замедляют шейдеры.
Проверьте себя
1. В чём ключевое отличие GPU от CPU?
AGPU имеет более умные ядра
BGPU имеет тысячи простых ядер для параллельной работы
CGPU не умеет считать
DGPU работает только с текстом
2. Что означает SIMT?
AОдин поток, много инструкций
BSingle Instruction, Multiple Threads — одна инструкция на много потоков
CСлучайный доступ к памяти
DСжатие текстур
3. Почему ветвление if внутри warp может замедлить шейдер?
AОно требует больше памяти
BGPU исполняет обе ветки последовательно, маскируя неактивные потоки (divergence)
Cif запрещён в GLSL
DЭто ускоряет шейдер