Что такое GPU и почему он параллельный
Видеокарта быстра в графике не потому, что её ядра умнее, а потому, что их тысячи и они работают одновременно.
GPU — процессор с тысячами простых ядер, выполняющих одну и ту же программу над разными данными параллельно (модель SIMT).
Зачем это знать
Шейдер пишут для одного элемента (вершины или пикселя), но исполняется он сразу на тысячах ядер для тысяч элементов. Если не понимать параллельную природу GPU, легко написать шейдер, который ломает эту модель (ветвления, зависимости между пикселями) и тормозит.
CPU против GPU
| Свойство | CPU | GPU |
| Ядер | единицы–десятки | тысячи |
| Каждое ядро | мощное, сложное | простое |
| Сильно в | последовательной логике | массовом параллелизме |
| Пример задачи | ОС, ветвистый код | цвет миллионов пикселей |
Почему графика так параллельна
Цвет каждого пикселя считается независимо от соседей. Два миллиона пикселей — два миллиона независимых задач. Это идеальная пища для тысяч ядер: дай каждому ядру по пачке пикселей, и они посчитают всё разом.
# Сравним «время» работы при последовательной и параллельной модели
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) замедляют шейдеры.