Сари Лада – От транзистора до робота (страница 3)
Это похоже на опытного официанта, который уже несёт тебе меню и воду, ещё пока ты только садишься за столик. Он не знает точно, что ты закажешь — но знает, что меню и вода нужны почти всегда.
Тактовая частота: метроном внутри
Ты наверняка видела в характеристиках компьютера что-то вроде «процессор 3,2 ГГц». Что это значит?
Внутри процессора есть генератор тактового сигнала — он похож на метроном, только вместо ударов в минуту — миллиарды ударов в секунду. Каждый «удар» — это один такт, один момент времени, когда процессор может выполнить элементарное действие.
Герц — это одно колебание в секунду. Гигагерц — миллиард. Процессор с частотой 3,2 ГГц делает 3,2 миллиарда тактов каждую секунду.
Раньше каждая инструкция требовала несколько тактов, но сегодня, благодаря конвейерной обработке, процессоры стремятся завершать в среднем больше одной инструкции за такт. Этот показатель называется IPC (instructions per cycle), и именно он, наряду с частотой, определяет реальную скорость.
Конвейер: почему процессор не ждёт
Представь автомойку. Машина въезжает, проходит несколько зон: сначала намыливание, потом щётки, потом ополаскивание, потом сушка. Если делать это последовательно для каждой машины — то есть полностью вымыть одну, потом взять следующую — большинство зон большую часть времени простаивают.
Умная автомойка работает иначе: пока первая машина на ополаскивании, вторая уже на щётках, третья намыливается, четвёртая только въезжает. Все зоны заняты одновременно. Пропускная способность резко растёт.
Процессор работает точно так же. Это называется конвейерная обработка (pipeline). Выполнение каждой инструкции разбито на несколько стадий: выборка (взять инструкцию из памяти), декодирование (понять, что делать), исполнение (сделать), запись результата. Пока одна инструкция исполняется, следующая уже декодируется, а ещё следующая — выбирается из памяти.
Современные процессоры имеют конвейеры глубиной 10–20 стадий. Это значит, что одновременно «в пути» находятся 10–20 инструкций на разных стадиях готовности. И именно поэтому предсказание переходов так важно: если программа вдруг меняет направление (условный переход), весь конвейер нужно «промыть» и начать заново — а это потеря тех самых тактов, которые уже были потрачены на неверные инструкции.
Ядра: когда одного дирижёра недостаточно
До середины 2000-х годов процессоры были одноядерными. Чтобы сделать их быстрее, инженеры повышали тактовую частоту. Это работало — до определённого предела.
Проблема в том, что чем выше частота, тем чаще переключаются транзисторы, а каждое переключение требует затрат энергии на перезарядку крошечных конденсаторов внутри них — поэтому с ростом частоты резко растёт выделение тепла. К 2004 году некоторые процессоры Intel разогревались до температур, при которых охлаждение становилось инженерным кошмаром. Гонка за гигагерцами упёрлась в тепловой предел.
Решение оказалось элегантным: вместо одного очень быстрого ядра — два умеренно быстрых. Потом четыре. Потом восемь, шестнадцать, тридцать два.
Ядро — это, грубо говоря, отдельный полноценный процессор внутри одного чипа. Каждое ядро читает свои инструкции, выполняет свои задачи, имеет свои регистры и кэш. Несколько ядер могут работать параллельно — одновременно, независимо.
Это меняет всё — но с одной оговоркой. Параллельная работа нескольких ядер даёт выигрыш только тогда, когда задачу можно разбить на независимые части. Это называется параллелизм задачи.
Хороший пример: видеоредактор применяет фильтр к миллиону пикселей. Каждый пиксель обрабатывается независимо — можно раздать работу по ядрам, и она выполнится в восемь раз быстрее на восьмиядерном процессоре.
Плохой пример: ты читаешь книгу. Каждая следующая страница зависит от предыдущей. Такая задача называется последовательной, и здесь дополнительные ядра почти не помогают.
Вот почему для разных задач нужны разные процессоры. Видеомонтаж, рендеринг, машинное обучение — любят много ядер. Однопользовательская игра, работа с базой данных в реальном времени, сложные расчёты с длинными цепочками зависимостей — предпочитают меньше ядер, но быстрее.
Кэш: память, о которой ты не думаешь
Представь, что ты работаешь за столом. На столе — несколько листов бумаги с числами, которые тебе сейчас нужны. В ящике стола — толстая папка с данными, к которым обращаешься реже. В шкафу за спиной — архив со всем остальным. На складе через улицу — старые дела, которые почти никогда не нужны.
Именно так организована память в компьютере. И именно так работает кэш.
Оперативная память (RAM) — это, грубо говоря, склад через улицу. Большая, вмещает много, но добраться до неё занимает время. В масштабах процессора — целые десятки и сотни тактов ожидания. Для процессора, который делает миллиарды операций в секунду, это катастрофически долго.
Кэш — это стол и ящики. Маленький (мегабайты против гигабайт RAM), но находится прямо на кристалле процессора и работает на его скорости.
Современные процессоры имеют несколько уровней кэша — обычно три.
L1 — самый маленький (32–64 килобайта на ядро) и самый быстрый. Доступ — 4–5 тактов. Это буквально «стол»: то, с чем процессор работает прямо сейчас.
L2 — побольше (256 килобайт — несколько мегабайт), чуть медленнее. 10–20 тактов. Ящик стола.
L3 — самый большой (8–64 мегабайта, иногда больше), общий для всех ядер. 30–50 тактов. Шкаф.
И только если данных нет ни в одном кэше — процессор идёт в RAM. Это называется промах кэша, и это дорого: 100–300 тактов ожидания, в течение которых процессор фактически стоит на месте.
Вся архитектура кэша построена на принципе локальности: если процессор обратился к какому-то куску памяти, он, скорее всего, скоро обратится к соседнему куску. Поэтому кэш загружает не один байт, а целую «строку» — 64 байта подряд. Это работает, потому что программы действительно обрабатывают данные последовательно — массивы, строки текста, кадры видео.
Кстати, именно поэтому хорошие программисты думают о кэше. Код, который обращается к памяти последовательно, работает в разы быстрее кода, который «прыгает» по случайным адресам — даже если количество операций одинаково. Разница в производительности может быть десятикратной просто за счёт того, попадают ли данные в кэш или нет.
Процессор и тепло: почему ноутбук греется
Вернёмся к тому, с чего начали: горячий ноутбук.
Каждый переключающийся транзистор потребляет крошечное количество энергии. Умножь крошечное на миллиарды — получишь заметное. Умножь заметное на миллиарды переключений в секунду — получишь тепло.
Это фундаментальная физика: электрический ток в проводнике всегда порождает тепло. Избежать этого нельзя — можно только управлять им.
Именно поэтому в компьютерах есть системы охлаждения: радиаторы, вентиляторы, тепловые трубки, а в дорогих игровых системах — жидкостное охлаждение. Тепло от процессора нужно отвести, иначе он перегреется и начнёт замедляться или вовсе выключится — это встроенная защита.
Современные процессоры умеют динамически менять свою частоту и напряжение в зависимости от нагрузки. Когда ты читаешь статью — частота низкая, тепла мало, батарея расходуется медленно. Открыла тяжёлое приложение — частота растёт, тепло растёт, вентилятор начинает шуметь. Это называется динамическое масштабирование частоты (DVFS — Dynamic Voltage and Frequency Scaling).
В смартфонах та же история, только охлаждение пассивное — радиатор без вентилятора. Поэтому телефон при долгой нагрузке может заметно нагреваться и замедляться: это не поломка, а тепловой троттлинг — осознанное снижение частоты, чтобы не перегреться.
Apple несколько лет назад произвела впечатление на всю индустрию своими чипами серии M. Секрет не только в высокой производительности — а в том, что такую производительность удалось получить при очень низком энергопотреблении. MacBook на M-чипе работает тихо, почти не греется и держит заряд весь день. Это результат нескольких архитектурных решений сразу: эффективные ядра для простых задач, производительные — для сложных, единая память для процессора и графики. Об этом — чуть ниже.
CPU против GPU: два разных подхода к скорости
Мы много говорили о центральном процессоре — CPU. Но в современных устройствах почти всегда есть ещё один процессор — графический, GPU (Graphics Processing Unit). И разница между ними — отличная иллюстрация того, что «быстрее» значит разное для разных задач.
CPU — это несколько очень умных и очень быстрых ядер. Современный топовый настольный процессор имеет 8–24 производительных ядра. Каждое ядро может быстро выполнять сложные, разветвлённые последовательности инструкций, справляться с непредсказуемыми задачами, обрабатывать ошибки, управлять другими компонентами. CPU — это универсальный солдат.
GPU — это тысячи маленьких, простых ядер. Видеокарта NVIDIA RTX 4090 содержит 16 384 шейдерных ядра. Каждое из них значительно проще и медленнее одного ядра CPU. Но когда им дают задачу, которую можно разбить на тысячи независимых маленьких подзадач — GPU сокрушает CPU.