Время выполнения любой программы процессором описывается фундаментальным физико-математическим равенством:
Векторные инструкции SIMD (AVX2/AVX-512) заменяют десятки скалярных команд одной векторной.
Суперскалярность и Out-of-Order повышают IPC = 1 / CPI, запуская несколько команд за 1 такт.
Конвейеризация дробит сложные операции на короткие такты, позволяя наращивать тактовую частоту.
Разбиение исполнения каждой команды на 5 аппаратных стадий, работающих параллельно над разными инструкциями:
PC.Результат: при заполненном конвейере процессор выпускает по одной завершенной команде каждый такт (CPI = 1).
Две инструкции одновременно претендуют на один физический узел (например, память).
Решение: раздельные кэши L1i (команды) и L1d (данные) — гарвардская архитектура.
RAW (Read After Write): команда пытается прочитать операнд до записи результата предшественником.
WAR / WAW: ложные зависимости по именам регистров.
Инструкции условных и безусловных переходов нарушают линейность потока команд.
Конвейер не знает, какую команду выбирать следующей, до вычисления флагов.
Как устранить задержки RAW без остановки конвейера?
• Команда I2 ждет, пока I1 дойдет до стадии WB (такт 5).
• Конвейер вставляет 2 такта простоя (Stall/Bubble).
• Падение реальной скорости и утилизации вычислительных блоков.
• Схема Forwarding Unit берет результат прямо с выхода регистра EX/MEM (такт 3).
• Данные передаются на вход ALU команды I2 (такт 4).
• 0 тактов задержки! Непрерывный темп работы.
LW) данные готовы только в конце стадии MEM, поэтому 1 такт простоя неизбежен.
Суперскалярный процессор содержит несколько параллельных конвейеров и исполнительных портов, выбирая и исполняя несколько инструкций за один такт (IPC > 1):
Современные процессоры (Intel Raptor Lake, AMD Zen 4, Apple M2) имеют 4–6 целочисленных ALU, 2–4 векторных блока FMA, раздельные блоки Load и Store.
Если первая команда в связке заблокирована ожиданием кэша памяти, весь процессор останавливается, блокируя остальные независимые команды!
Алгоритм Роберта Томасуло динамически меняет порядок исполнения команд в зависимости от готовности данных:
Архитектурные регистры (RAX, RBX) проецируются на сотни физических регистров (PRF).
Это полностью ликвидирует ложные зависимости WAR и WAW!
Команды ждут в очередях планировщика. Как только оба операнда готовы, команда немедленно стартует на свободный порт.
Готовый результат широковещательно рассылается по процессору: все станции резервирования, ожидавшие этот результат, перехватывают его мгновенно.
Хотя команды исполняются в произвольном порядке (Out-of-Order), их завершение (Retire/Commit) обязано быть строго упорядоченным (In-Order)!
• Кольцевой буфер FIFO, куда команды поступают строго в исходном порядке программы.
• Фиксация результата в архитектурные регистры происходит строго по очереди головы буфера.
• Если команда вызвала ошибку (деление на ноль или Page Fault), все спекулятивные команды за ней просто аннулируются.
• Внешний наблюдатель видит состояние, как будто процессор работал строго последовательно.
Ветвления встречаются каждые 5–7 команд. Чтобы конвейер не простаивал, процессор угадывает направление перехода:
4 состояния: Сильно/Слабо взят, Сильно/Слабо не взят. Требует 2 ошибок подряд для смены решения.
Кэш целевых адресов переходов. Позволяет выбрать целевую инструкцию уже на стадии IF до декодирования!
Использует геометрическую историю сотен предыдущих переходов. Точность превышает 97–99%!
Процессор не просто предсказывает адрес — он спекулятивно вычисляет ветвь кода вперед до подтверждения условия:
• Конвейер загружен на 100%, устраняются простои на ветвлениях.
• При точности предсказателя 98% эффективный CPI вплотную приближается к идеальному 1.0.
• Spectre / Meltdown: спекулятивные команды оставляют микроархитектурные следы в кэше данных, позволяя читать чужую память через сайд-каналы по времени!
• Аппаратные заплатки требуют частичного отключения агрессивных спекуляций.
SIMD (Single Instruction, Multiple Data): одна инструкция обрабатывает целый массив чисел параллельно:
| Поколение SIMD | Разрядность регистров | Чисел float32 за такт | Операция FMA |
|---|---|---|---|
| SSE / SSE4.2 | 128 бит (XMM) | 4 числа float32 | Нет |
| AVX / AVX2 | 256 бит (YMM) | 8 чисел float32 | Да (2 флопа за такт) |
| AVX-512 | 512 бит (ZMM) | 16 чисел float32 | Да (маски предикатов k0–k7) |
AVX Throttle: работа с широкими 512-битными регистрами вызывает скачок тока, из-за чего процессор временно снижает частоту на 100–300 МГц (AVX Frequency Offset).
Почему частоты процессоров перестали расти после 2005 года?
Уменьшая транзистор, инженеры снижали напряжение V, сохраняя удельную тепловую мощность постоянной при росте частоты f.
При напряжении < 0.8 В токи квантовой утечки растут экспоненциально. Отводить больше 250 Вт тепла с кремния стало невозможно — частоты застыли на 3–5 ГГц.
⇒ Единственный путь дальнейшего роста производительности — архитектурный параллелизм и многоядерность!
Закон Джина Амдала определяет максимальный выигрыш в скорости от добавления параллельных ядер:
Последовательная часть = 25%
Предел ускорения: 4×
1000 ядер дадут не более 4-кратного прироста!
Последовательная часть = 10%
Предел ускорения: 10×
При 64 ядрах ускорение равно 8.77×.
Последовательная часть = 5%
Предел ускорения: 20×
Даже 5% последовательного кода ограничивают потолок ускорения 20 разами!
(1 - p).