Фон Нейман и Гарвардская архитектура
Урок разбирает две фундаментальные схемы организации памяти и команд, на которых стоят все компьютеры.
Архитектура фон Неймана — модель, где команды и данные хранятся в одной общей памяти. Гарвардская архитектура — память команд и память данных раздельны, с отдельными шинами.
Революция «хранимой программы»
Ранние машины «перепрограммировали» физически — перекоммутируя провода. Прорыв фон Неймана (1945): команды — это тоже данные, и их можно хранить в той же памяти. Тогда программа загружается как обычные числа, а смена задачи — это загрузка другой программы, а не пересборка машины. Эта идея «хранимой программы» сделала компьютеры универсальными.
Четыре части машины фон Неймана
┌──────────────────────────────────┐
│ ПАМЯТЬ (команды + данные) │
└───────────────┬────────────────────┘
│ одна общая шина
┌───────────┴───────────┐
│ │
┌────┴────┐ ┌──────┴──────┐
│ УУ │ процессор │ АЛУ │
│(управл.)│ │ (вычисления) │
└─────────┘ └──────────────┘
│ │
┌────┴───────────────────────┴───┐
│ ВВОД / ВЫВОД │
└────────────────────────────────┘
Это: память, устройство управления (УУ), арифметико-логическое устройство (АЛУ) и ввод-вывод. УУ + АЛУ образуют процессор. Главное — единая память для всего.
Узкое место фон Неймана
У единой памяти есть цена: и команды, и данные ходят по одной шине. Процессор не может в один момент и читать команду, и читать/писать данные — они конкурируют за шину. Это узкое место фон Неймана (von Neumann bottleneck): пропускная способность памяти ограничивает скорость. Гарвардская архитектура решает это раздельными шинами.
| Свойство | Фон Нейман | Гарвардская |
| Память команд и данных | общая | раздельная |
| Шины | одна | две (параллельно) |
| Доступ за такт | либо команда, либо данные | команда и данные одновременно |
| Гибкость | выше (код = данные) | ниже |
| Где применяется | ПК, серверы (внешне) | микроконтроллеры, DSP, кэши CPU |
Как работает под капотом: гибрид
Современные процессоры — гибрид. Снаружи они выглядят как фон-неймановские (одна память для всего), но внутри кэш первого уровня разделён на кэш команд (L1i) и кэш данных (L1d) — то есть по-гарвардски. Так получают и гибкость хранимой программы, и параллельный доступ. Промоделируем разницу в «тактах» доступа:
def cycles_von_neumann(n_instr, n_data):
# одна шина: команды и данные по очереди
return n_instr + n_data
def cycles_harvard(n_instr, n_data):
# две шины: идут параллельно, время = максимум из двух
return max(n_instr, n_data)
ni, nd = 100, 80
print("Доступы: команд =", ni, ", данных =", nd)
print("фон Нейман:", cycles_von_neumann(ni, nd), "тактов (по очереди)")
print("Гарвард: ", cycles_harvard(ni, nd), "тактов (параллельно)")Вывод:
Доступы: команд = 100 , данных = 80 фон Нейман: 180 тактов (по очереди) Гарвард: 100 тактов (параллельно)
Глубже в тему
Чтобы оценить, насколько революционной была идея хранимой программы, стоит представить, как программировали до неё. Машину ENIAC «перепрограммировали» физически — переставляя сотни проводов и переключателей, и на смену задачи уходили дни. Прорыв, зафиксированный в отчёте фон Неймана 1945 года (опиравшемся в том числе на идеи Тьюринга и команды ENIAC), звучит обманчиво просто: команды — это тоже числа, и их можно держать в той же памяти, что и данные. С этого момента смена задачи стала загрузкой другой последовательности чисел, а не пересборкой машины. Именно эта идея сделала компьютер универсальным устройством, а не специализированным калькулятором, и заодно открыла дорогу таким вещам, как компиляторы и операционные системы, которые порождают и переписывают код как обычные данные.
Узкое место фон Неймана стоит понимать не как «дефект проектирования», а как фундаментальное следствие единой памяти. Раз и команды, и данные живут в одной памяти и ходят по одной шине, процессор в каждый момент может делать что-то одно: либо выбирать команду, либо читать или писать данные. Они конкурируют за единственный канал, и пропускная способность этого канала ставит потолок скорости. С годами разрыв только рос: производительность процессоров десятилетиями увеличивалась быстрее, чем пропускная способность памяти, так что «голодание» процессора в ожидании памяти стало одной из главных проблем архитектуры. Многое из того, что мы изучим дальше — кэши, конвейер, предвыборка, — это во многом ответы именно на это узкое место.
Гарвардская архитектура атакует проблему в лоб: память команд и память данных физически разделены, у каждой своя шина, и за один такт можно одновременно выбирать команду и обращаться к данным. Имя пришло от компьютера Harvard Mark I, где программа хранилась на перфоленте отдельно от данных. Платой становятся жёсткость и стоимость: раздельные памяти труднее перераспределять, а самомодифицирующийся код (когда программа меняет собственные команды) в чистой гарвардской модели затруднён, потому что путь записи данных не ведёт в память команд. Поэтому в чистом виде гарвардская архитектура прижилась там, где гибкость не критична, а скорость и предсказуемость важны: в микроконтроллерах и сигнальных процессорах (DSP).
Самое интересное, что современные процессоры — гибрид, и понимание этого снимает кажущееся противоречие двух моделей. Снаружи ПК выглядит чисто фон-неймановским: одна общая память для всего, код и данные адресуются единообразно, самомодификация и компиляция возможны. Но внутри, на уровне кэша первого уровня, он разделён на кэш команд (L1i) и кэш данных (L1d) — то есть устроен по-гарвардски. Так инженеры получают и то и другое сразу: гибкость хранимой программы снаружи и параллельный доступ к командам и данным внутри, на самом горячем уровне, где это даёт максимальный выигрыш в скорости. Это образцовый пример того, как реальная архитектура не выбирает между двумя «чистыми» идеями, а комбинирует их по уровням.
Частые ошибки
- Считать ПК «чисто фон-неймановским». Внутри кэшей он гарвардский (раздельные L1i/L1d).
- Думать, что Гарвард всегда лучше. Раздельная память дороже и менее гибка; для микроконтроллеров — да, для ПК внешне — нет.
- Забывать суть фон Неймана. Главное — команды хранятся как данные в общей памяти (хранимая программа).
Итог
- Фон Нейман: единая память для команд и данных — идея хранимой программы.
- Узкое место фон Неймана: одна шина ограничивает скорость обмена с памятью.
- Гарвардская архитектура (раздельные шины) живёт внутри кэшей современных CPU.