Архитектура процессора что это такое


Архитектура процессора: коротко о том как устроен CPU

Доброго времени суток.

В этой статье вы получите развернутый ответ на вопрос «что такое архитектура процессора». Также после ее прочтения вы узнаете о разновидностях архитектуры и научитесь различать их обозначения.

Объяснение термина

Под архитектурой процессора понимается комбинация из:

  • Микроархитектуры — способ ее реализации, то есть составные части проца и методы их взаимодействия между собой и описанными ниже компонентами;
  • АНК — набор команд, включая модель исполнения, регистры устройства, форматы данных и адресов.
  • Микрокода — делает понятными команды уровня АНК для микроархитектуры.

Если рассматривать архитектуру со стороны программистов, то его можно объяснить как совместимость с определенным набором команд (допустим, девайсы, соответствующие командам Intel x86), их структуру (например, как организована система адресации или регистровая память), а также метод исполнения (к примеру, счетчик команд).

Смотря на архитектуру как на аппаратную составляющую компьютера, мы увидим другую картину. Это определенный набор характеристик, которому соответствует целое семейство процессоров, то есть их внутренняя конструкция.

Классификация архитектур

По скорости и количеству выполняемых команд архитектуры делятся на:

  • CISC. На английском языке расшифровывается как «Complex Instruction Set Computing», то есть «Комплексный набор команд». Устройствам этого типа свойственно большое количество режимов адресации и команд разного формата и длины, а также сложная кодировка инструкции.
  • RISC. Первое слово в расшифровке заменено на «Reduced», что на нашем языке — «Сокращенный». Это значит, что все команды имеют одинаковый формат и кодировку.
  • MISC (Multipurpose — Многоцелевой ). База элементов делится на две части, которые находятся или в одном корпусе, или в отдельных. Главной выступает RISC CPU. Он дополнен другой частью — постоянным запоминающим устройством микропрограммного управления. Системе присущи характеристики CISC. Большинство команд выполняет первая часть, а команды расширения преобразуются в адрес микропрограммы.

Также существует классификация процессоров, и соответственно архитектур, по назначению:

  • Графические. Как видеокарта отвечает за визуализацию объектов на экране.
  • Математические. Нацелены на расширение набора команд, выполняемых центральным процессором, для решения различных математических задач.
  • Цифровые сигнальные. Специализированные устройства, предназначенные для обработки оцифрованных сигналов.

С физической точки зрения девайсы разделяются по количеству ядер, которые отвечают за выполнение команд. Если их больше одного, устройства называются многоядерными.

Разбор обозначений

В теме о процессорах вы можете столкнуться с их цифровыми обозначениями типа x64, x86 и пр. Давайте разберемся, что все это значит. Разложу по полочкам.

8086 и компания

В 1978 году компания Intel выпустила 16-битный процессор, получивший название 8086.

После него выходили другие модели, в наименованиях которых первые две цифры оставались прежними, а последние менялись на 88, 186, 286, 386, 486 и прочие.

Вот пример i386.

Как вы заметили, почти все имена заканчиваются одинаково, поэтому все семейство объединили под условное обозначение x86. Оно устоялось среди пользователей и применялось даже когда Интел начала давать своим продуктам словарные названия типа Пентиум, Кор, Атом и т. д. Переняли эту «моду» и другие производители устройств, совместимых с этим семейством, — IBM, VIA, AMD, Cyrix и др.

Чаще всего это обозначение сейчас используется по отношению к 32-битным процессорам. Они также могут называться, к примеру, i386, i486, i586, когда требуется дать более точные сведения о наборе инструкций.

Совершенствование до 64 бит

Компания Intel модернизировала процессоры с 16-битной шиной до 32 бит. Однако AMD приложила усилия к усовершенствованию их до х64. Первый такой продукт она выпустила в 2003 году, не став заморачиваться над названием — просто «AMD64».

Чтобы показать повышенную разрядность процессоров, стали к обозначению «x86» добавлять «64», к примеру, x86_64.

Интел решила выделиться, помечая такие устройства сначала как «IA-32e», а потом «EM64T». Но сейчас чаще можно встретить «Intel 64».

Как узнать архитектуру?

В случае с новыми ЦП прочитать их характеристики можно в инструкции или непосредственно на коробке. Но что делать, если вы берете устройство с рук? Или может быть хотите знать, какая архитектура у вашего проца? Выяснить это можно несколькими способами.

Средства системы

Выполните следующие действия:

  • Откройте командную строку через меню «Пуск — Программы — Стандартные» или другим удобным способом.
  • Впишите в нее слово systeminfo.
  • Нажмите Enter.

Перед вами появятся сведения об операционке, среди которой будет и архитектура процессора.

Другой способ:

  • Щелкните правой кнопкой мыши на значке «Мой компьютер»;
  • Откройте «Свойства»;
  • Перейдите в «Диспетчер устройств»;
  • Кликните пункт «Процессор».

И тоже получите все данные о нем.

Сторонние программы

Одной из хороших программ, помогающих узнать все о проце, является CPU-Z.

Она бесплатная и распространенная, поэтому вы без проблем ее отыщите и скачаете.

Вам нужно лишь установить и запустить ее, чтобы посмотреть необходимую информацию.

В качестве альтернативного варианта могу предложить еще одну достойную прогу — AIDA 64. Она платная (Есть триал период), зато может рассказать все о вашем железе в целом, не только о ЦП.

Получить сведения о процессоре через нее можно, перейдя по разделам «Компьютер — Системная плата — ЦП».

На этом буду заканчивать.

Чтобы не забывать заглядывать ко мне чаще и узнавать больше новой интересной информации, подписывайтесь на обновления.

До скорого.

profi-user.ru

Виды популярных архитектур процессоров

Иван Борисов

Прежде чем рассмотреть основные виды архитектур процессоров, необходимо понять, что это такое. Под архитектурой процессора обычно понимают две совершенно разные сущности.

С программной точки зрения архитектура процессора — это совместимость с определённым набором команд (Intel x86), их структуры (система адресации, набор регистров) и способа исполнения (счётчик команд).

Говоря простым языком, это способность программы, собранной для архитектуры x86, работать практически на любой x86-совместимой системе. При этом такая программа не будет работать, например, на ARM системе.

С аппаратной точки зрения архитектура процессора — это некий набор свойств и качеств, присущий целому семейству процессоров (Skylake – процессоры Intel Core 5 и 6 поколений).

Виды архитектур

В этой статье мы рассмотрим самые распространенные и актуальные архитектуры с программной точки зрения, кроме узкоспециализированных (графических, математических, тензорных).

CISC

CISC (англ. Complex Instruction Set Computer — «компьютер с полным набором команд») — тип процессорной архитектуры, в первую очередь, с нефиксированной длиной команд, а также с кодированием арифметических действий в одной команде и небольшим числом регистров, многие из которых выполняют строго определенную функцию.

Самый яркий пример CISC архитектуры — это x86 (он же IA-32) и x86_64 (он же AMD64).

В CISC процессорах одна команда может быть заменена ей аналогичной, либо группой команд, выполняющих ту же функцию. Отсюда вытекают плюсы и минусы архитектуры: высокая производительность благодаря тому, что несколько команд могут быть заменены одной аналогичной, но большая цена по сравнению с RISC процессорами из-за более сложной архитектуры, в которой многие команды сложнее раскодировать.

RISC

RISC (англ. Reduced Instruction Set Computer — «компьютер с сокращённым набором команд») — архитектура процессора, в котором быстродействие увеличивается за счёт упрощения инструкций: их декодирование становится более простым, а время выполнения — меньшим. Первые RISC-процессоры не имели даже инструкций умножения и деления и не поддерживали работу с числами с плавающей запятой.

По сравнению с CISC эта архитектура имеет константную длину команды, а также меньшее количество схожих инструкций, позволяя уменьшить итоговую цену процессора и энергопотребление, что критично для мобильного сегмента. У RISC также большее количество регистров.

Примеры RISC-архитектур: PowerPC, серия архитектур ARM (ARM7, ARM9, ARM11, Cortex).

В общем случае RISC быстрее CISC. Даже если системе RISC приходится выполнять 4 или 5 команд вместо одной, которую выполняет CISC, RISC все равно выигрывает в скорости, так как RISC-команды выполняются в 10 раз быстрее.

Отсюда возникает закономерный вопрос: почему многие всё ещё используют CISC, когда есть RISC? Всё дело в совместимости. x86_64 всё ещё лидер в desktop-сегменте только по историческим причинам. Так как старые программы работают только на x86, то и новые desktop-системы должны быть x86(_64), чтобы все старые программы и игры могли работать на новой машине.

Для Open Source это по большей части не является проблемой, так как пользователь может найти в интернете версию программы под другую архитектуру. Сделать же версию проприетарной программы под другую архитектуру может только владелец исходного кода программы.

MISC

MISC (англ. Minimal Instruction Set Computer — «компьютер с минимальным набором команд»).

Ещё более простая архитектура, используемая в первую очередь для ещё большего уменьшения итоговой цены и энергопотребления процессора. Используется в IoT-сегменте и недорогих компьютерах, например, роутерах.

Для увеличения производительности во всех вышеперечисленных архитектурах может использоваться “спекулятивное исполнение команд”. Это выполнение команды до того, как станет известно, понадобится эта команда или нет.

VLIW

VLIW (англ. Very Long Instruction Word — «очень длинная машинная команда») — архитектура процессоров с несколькими вычислительными устройствами. Характеризуется тем, что одна инструкция процессора содержит несколько операций, которые должны выполняться параллельно.

По сути является архитектурой CISC со своим аналогом спекулятивного исполнения команд, только сама спекуляция выполняется во время компиляции, а не во время работы программы, из-за чего уязвимости Meltdown и Spectre невозможны для этих процессоров. Компиляторы для процессоров этой архитектуры сильно привязаны к конкретным процессорам. Например, в следующем поколении максимальная длина «очень длинной команды» может из условных 256 бит стать 512 бит, и тут приходится выбирать между увеличением производительности путём компиляции под новый процессор и обратной совместимостью со старым процессором. Опять же, Open Sourсe позволяет простой перекомпиляцией получить программу под конкретный процессор.

Примеры архитектуры: Intel Itanium, Эльбрус-3.

Виртуальные архитектуры

Но раз нельзя запустить программу одной архитектуры на другой, то откуда берутся магические JAR-файлы, которые можно запустить на любой машине? Это пример виртуальной JVM-архитектуры, которая, по сути, эмулируется на целевой реальной машине. Поэтому достаточно JVM-машины для целевой архитектуры для запуска на ней любой Java-программы. Другим примером виртуальной архитектуры является .NET CIL.

Из минусов виртуальных архитектур можно выделить меньшую производительность по сравнению с реальными архитектурами. Этот минус нивелируется с помощью JIT- и AOT-компиляции. Однако большим плюсом будет кроссплатформенность.

Дальнейшим развитием этих архитектур стали гибридные архитектуры. Например современные x86_64 процессоры хотя и CISC-совместимы, но являются процессорами с RISC-ядром. В таких гибридных CISC-процессорах CISC-инструкции преобразовываются в набор внутренних RISC-команд. Какое дальнейшее развитие получат архитектуры процессора, покажет только время.

Не смешно? А здесь смешно: @ithumor

tproger.ru

Что такое архитектура процессора, какая бывает и используется в смартфонах

С момента изобретения первых электронно-вычислительных машин в первой половине 20 века произошла только одна истинная революция. Случилось это в 50-60-х годах, когда на смену громоздким вакуумным лампам пришли полупроводниковые технологии. Тогда в качестве основного материала для их производства были выбраны кристаллы кремния. На них, с помощью различных технологий, вытравливаются миниатюрные транзисторы и связующие их цепи. С тех пор, на протяжении полувека, меняется в сторону уменьшения только размер транзисторов (техпроцесс), и увеличивается их количество на кристалле.

В условиях использования единой технологии (и отсутствия практически применимых альтернатив, так как до массового внедрения квантовых процессоров еще далеко) единственным способом приспособить вычислительные чипы под те или иные задачи — стало изобретение различных архитектур ЦП.

Что такое архитектура процессора

Архитектура процессора — это совокупность главных принципов его конструирования, общая схема расположения деталей на кремниевом кристалле и схема взаимодействия программного обеспечения с чипом. Если еще более упрощенно, то архитектура — это схема, по которой устроен процессор.

За все время было создано много различных архитектур. Самые популярные из них — CISC, MISC, VLIW и RISC. Различия между ними касаются, главным образом, системы взаимодействия процессора с обрабатываемыми данными. Сейчас активно используются конвейерные архитектуры CISC и RISC.

Как работает архитектура процессора

В конвейерной архитектуре данные обрабатываются последовательно, переходя от одного этапа  к следующему. Например, на первом этапе процессор получает инструкцию, на втором — производится чтение данных из памяти, на третьем — осуществляется вычислительная операция, а на четвертой — выдача полученного результата. Когда первый этап конвейера освобождается — он может приступить к выполнению следующей инструкции. Этот процесс можно сравнить с работой автозавода: когда работник прикручивает последнюю ступицу колеса — конвейер двигается дальше. Второй работник прикручивает колеса на ступицы, а первый — опять прикручивает ступицы на следующей машине.

Количество стадий конвейера может быть разным. Если программа получает данные исправно, в них не содержится ошибок, то такой подход повышает производительность. Чем длиннее конвейер — тем больше операций выполняется за такт (1 герц частоты процессора). В аналогии с автозаводом, количество этапов конвейера — это количество работников за лентой, по которой двигаются кузова собираемых машин. Чем больше мегагерц — тем быстрее движется лента, тем быстрее работают сборщики. Однако если первый работник что-то сделает не так — получится брак, машину придется собирать заново.

В процессоре все аналогично: если на раннем этапе конвейера происходит ошибка — конвейер нужно перезапускать. Это замедляет производительность и приводит к пустым тратам энергии. Так как для компактных и мобильных устройств энергоэффективность очень важна — специально для них была создана архитектура RISC. От CISC она отличается упрощенным набором команд, которые принимает процессор, и укороченным конвейером. Такая особенность приводит к снижению производительности на фоне CISC (а компьютерные x86-процессоры Intel и AMD построены на ней), но позволяет минимизировать пустую трату энергии.

Архитектура процессоров ARM

Всевозможные MIPS, PowerPC, SPARC и прочие архитектуры типа RISC оставим IT-специалистам. Когда дело касается смартфонов — стоит детальнее уделить внимание ARM, Это — разновидность RISC архитектуры с коротким конвейером, которая является одной из самых распространенных и удачных. Именно ARM использует большинство производителей (Qualcomm, MediaTek, Apple, Samsung, Huawei-HiSilicon и другие). Только Intel в своих SoC атом используют x86-совместимые CISC ядра.

Особенностью ARM процессоров является использование короткого конвейера. Его длина составляет 3 и более этапов, что немного на фоне десятков стадий у CISC. За счет этого сбои в работе конвейера минимально сказываются на скорости обработки программ, максимально эффективно нагружая каждый такт. Поэтому именно ARM стала самой популярной архитектурой процессоров для смартфонов и планшетов.

Архитектура и микроархитектура процессора

Довольно часто в СМИ и интернете происходит путаница между понятиями архитектуры и микроархитектуры процессора. Чтобы внести ясность, следует установить отношение между данными терминами. Так вот, архитектура — это общий принцип устройства и работы процессора, а микроархитектура — всего лишь один из вариантов ее реализации, имеющий свои особенности, но сохранающий совместимость с базовой архитектурой.

Виды микроархитектур ARM для смартфонов

Большинство чипсетов для смартфонов содержат процессоры, созданные на ARM, а именно — микроархитектурах семейства Cortex и других. Список актуальных версий и их отличия приведены ниже.

  • Cortex A7. Устаревающая микроархитектура процессоров для смартфонов. Отличается низким энергопотреблением, имеет конвейер из 8-10 этапов. Не умеет работать с 64-битными инструкциями. Относится к семейству ARMv7.

    Cortex A7

  • Cortex A53. Актуальная микроархитектура, также имеет ковейер, состоящий из 8 стадий. Поддерживает новые инструкции и 64-битность, за счет этого работает быстрее, чем A7. Относится к семейству ARMv8.

    Cortex A53

  • Cortex A35. Модификация предыдущей микроархитектуры, отличающаяся сниженными производительностью и энергопотреблением. Принадлежит к семейству ARMv8.

    Cortex A35

  • Cortex A72. Высокопроизводительная микроархитектура ARM, сочетающая короткий конвейер и расширенный набор инструкций, а также поддерживающая увеличенный кэш. В сравнении с A53 – обеспечивает более высокую производительность, но также расходует больше энергии. Тоже принадлежит к серии ARMv8.

    Cortex A72

  • Cortex A73. Развитие предыдущей версии, сохраняет основные принципы этой архитектуры, но является более продуктивной и энергоэффективной.

    Cortex A73

  • Apple. Apple используют в своих процессорах модификации ARMv8, но усовершенствованные. Точных спецификаций американцы не раскрывают, но известно о поддержке дополнительных инструкций и удлиненном конвейере. Актуальные микроархитектуры — Zephyr и Hurricane, используемые в чипе Apple A10 Fusion.
  • Kryo. Актуальная микроархитектура, основанная на ARMv8, созданная Qualcomm. Отличается расширенным набором инструкций и удлиненным конвейером. Применяется во флагманских чипах Snapdragon, например, 821.
  • Mongoose. Еще одна микроархитектура, производная от архитектуры ARMv8. Используется Samsung в топовых процессорах семейства Exynos. В сравнении с базовой Cotrex A72 имеет небольшие отличия, касающиеся энергосбережения и производительности.

Возможно вам будет интересно:

mobcompany.info

Современные десктопные процессоры архитектуры x86

общие принципы работы (x86 CPU digest 2.0)

Этот материал представляет собой обновлённую, существенно переработанную и дополненную версию статьи 2006 года, которая называлась «Современные десктопные процессоры архитектуры x86: общие принципы работы (x86 CPU FAQ 1.0)». Правда, чтобы не вводить потенциальных читателей в заблуждение словом «FAQ», мы решили назвать новый материал более правильным, как нам кажется, термином — «дайджест». Действительно, ведь большая его часть — это не ответы на конкретные вопросы, а разъяснения и краткие выжимки из чего угодно — от технической документации до истории развития микропроцессорной отрасли. Для кого предназначен данный материал? Нам видятся две группы потенциальных читателей.

Первая — это те, кто вдруг обнаружил, что ему действительно интересно узнать, как работает современный x86-процессор. Для них мы попытались сосредоточить в рамках статьи максимальное количество полезных сведений, которые позволяют получить более-менее полное представление об этом процессе, даже не имея до этого (почти) никаких специальных знаний: здесь объясняется значение основных терминов, устройство современных CPU, принципы взаимодействия различных их составляющих между собой, а также процессора с компьютерной системой в целом.

Вторая группа — это те, кто не найдёт в статье почти ничего нового для себя — но им попросту лень писать нечто похожее самостоятельно, чтобы сосредоточить разбросанные по мозгу знания в одном месте, «причесать» их, систематизировать, упорядочить, осовременить, и так далее. Мы сами отлично понимаем, как бывает лениво писать конспекты :) (а особенно — хорошие конспекты), поэтому если наш дайджест вас устраивает — мы с радостью дарим вам возможность им пользоваться.

Ну и традиционное предупреждение: если иное не указано явно, то слово «процессор» в данном материале обозначает «x86(-64) процессор, предназначенный для установки в десктопы или (намного реже) мобильные компьютеры». Серверные процессоры, специализированные процессоры с архитектурой x86, всевозможные embedded-варианты — всё это в рамках статьи не рассматривается.ОглавлениеВведение

Общее устройство вычислительной машины

Любой компьютер как универсальный инструмент для работы с информацией устроен очень просто. Все его части можно разделить на 3 вида: устройства обработки, хранения и обмена (ввода-вывода), причём последние могут осуществлять обмен данными как между компьютером и человеком, так и между другими компьютерами. С информационной точки зрения больше ничего там нет, хотя учитывая, что компьютер — устройство электрическое, ему нужен источник питания, кабели и т.п., но это общая часть всей электроники. При этом каждый элемент сам делится на компоненты вышеперечисленных трёх видов. Например, процессор относится к устройствам обработки, но внутри себя имеет блоки собственно вычислений, локальной памяти и обмена. Большая часть пока ещё непонятных терминов именует конкретные детали процессора или методы их взаимодействий.

Код и данные: основной принцип работы процессора

Если не пытаться изложить здесь «кратенько» курс информатики для средней школы, то единственное что хотелось бы напомнить — это то, что процессор (за редкими исключениями) исполняет не программы, написанные на каком-нибудь языке программирования (один из которых, вы, возможно, даже знаете), а так называемый машинный код. Т.е. командами для него являются последовательности байтов, находящихся в памяти компьютера, не имеющие ничего общего не только с каким-то человеческим языком, но и с языком программирования высокого уровня. Каждая команда занимает до нескольких байт, в среднем — 3-5. Там же, в основной памяти (ОЗУ, RAM) находятся и данные. Они могут находиться в отдельной области, а могут и быть перемешаны с кодом. Различие между кодом и данными состоит в том, что данные — это то, над чем процессор производит операции. А код — это команды, которые ему сообщают, какую именно операцию он должен произвести. Одновременно в памяти располагаются множество программ, необходимых им данных и некоторое свободное место.

Чтобы исполнить команду, процессор должен прочитать её из памяти. Чтобы произвести операцию над данными (а этого требует почти каждая команда), процессор должен прочитать их из памяти, и, возможно, после произведения над ними определённого действия, записать их обратно в память в обновлённом (изменённом) виде. Команды и данные идентифицируются их адресом, который представляет собой порядковый номер байта в памяти, с которого эти данные начинаются (если они занимают несколько байт). Общие принципы взаимодействия процессора и ОЗУ

Возможно, кого-то удивит, что достаточно большой раздел в «Дайджесте», посвящённом x86 CPU, выделен под объяснение особенностей функционирования памяти в современных системах, основанных на данном типе процессоров. Однако факты — упрямая вещь: сами x86-процессоры ныне содержат так много блоков, отвечающих именно за оптимизацию их работы с ОЗУ, что игнорировать эту тесную связь было бы совершенно нелепо. Можно сказать даже так: уж, коль решения, связанные с оптимизацией работы с памятью, стали неотъемлемой частью самих процессоров — то и саму память можно рассматривать в качестве некоего «придатка», функционирование которого оказывает непосредственное влияние на скорость работы CPU. Без понимания особенностей взаимодействия процессора с памятью, невозможно понять, за счёт чего тот или иной процессор (та или иная система) исполняет программы медленнее или быстрее.

Контроллер памяти

Итак, ранее выше мы уже говорили о том, что как команды, так и данные, попадают в процессор из оперативной памяти. На самом деле всё немного сложнее. Ещё недавно в большинстве x86-систем (т.е. компьютеров на базе x86-процессоров), процессор к памяти обращаться сам не мог, т.к. не имел в своём составе соответствующих узлов. Некоторые не самые новые, но ещё популярные линейки процессоров (Intel Core 2, Celeron и Pentium всех видов) используют такую классическую организацию и сейчас. В этой схеме процессор обращается к «промежуточному» специализированному устройству, называемому контроллером памяти, а уже тот, в свою очередь — к микросхемам ОЗУ, размещенным на модулях памяти. Модули вы наверняка видели — это такие длинные узкие текстолитовые «планочки» (фактически — небольшие платы) с несколькими микросхемами на них, вставляемые в специальные разъёмы на системной плате. Роль контроллера ОЗУ, таким образом, проста: он служит своего рода «мостом» между памятью и использующими её устройствами (а это не только процессор, но об этом — чуть позже).x86-система с внешним контроллером памяти (слева) и с контроллером памяти, встроенным в процессор (справа)

В традиционной схеме, контроллер памяти входит в состав чипсета — набора микросхем, являющегося основой системной платы. От быстродействия контроллера во многом зависит скорость обмена данными между процессором и памятью, это один из важнейших компонентов, влияющих на общую производительность компьютера. По «новой» схеме (к ней относятся процессоры Intel Core с буквой «i», и все ныне выпускаемые CPU AMD), контроллер памяти входит в состав самого процессора — теперь никаких посредников между памятью и процессором нет, так что общаться им оказывается проще и быстрее. Однако многочисленным устройствам ввода-вывода жизнь несколько усложнилась — им путь до памяти стал на один шаг длиннее, т.к. чипсет никуда не исчез (а лишь лишился контроллера памяти), и теперь обращаться к памяти требуется через процессор, отвлекая его от выполнения программ. Тем не менее, новая схема является прогрессивной, потому что процессору важнее всего получить доступ к памяти как можно быстрее, даже ценой некоторого усложнения доступа для других устройств — именно он является главным потребителем и производителем той информации, которая записана в памяти.

Процессорная шина

Любой процессор обязательно оснащён как минимум одной процессорной шиной, которую в среде x86 CPU иногда по старинке называют FSB (Front Side Bus), хотя современные процессоры имеют для неё разные названия (QPI для Intel и HyperTransport для AMD). В многопроцессорных платах таких шин несколько, и связаны они с другими процессорами и чипсетом. В домашних компьютерах, где процессор, как правило, один, шина у него единственная (не считая шины памяти, если в процессор встроен её контроллер) и связывает его с чипсетом, а через него — со всеми остальными устройствами.

Оперативная память

Разрядность шины памяти, N-канальные контроллеры памяти

На сегодняшний день вся память, используемая в современных десктопных x86-системах, имеет шину шириной 64 бита. Это означает, что за один такт по данной шине одновременно может быть передано количество информации, кратное 8 байтам (8 байт для SDR-шин, 16 байт для DDR-шин). Особняком стоит только память типа RDRAM, применявшаяся в системах на базе процессоров Intel Pentium 4 на заре становления архитектуры NetBurst, но сейчас это направление признано тупиковым для x86-ПК (к слову — руку к этому приложила всё та же компания Intel, которая в своё время активно пропагандировала данный тип памяти). Некоторую неразбериху вносят лишь многоканальные контроллеры, обеспечивающие одновременную работу с несколькими отдельными друг от друга 64-битными шинами. Применительно к 2-канальным котроллерам некоторые производители заявляют о «128-битности». Однако арифметика на уровне 1-го класса в данном случае работает с оговоркой: 2x64 равно 128 только когда все каналы работают одновременно. Т.е. N-канальный контроллер памяти теоретически может увеличить скорость работы с данными в N раз, но при этом ширина каждой шины памяти во всех современных контроллерах, применяемых в x86-системах по-прежнему равна 64 битам. На данный момент времени, одноканальный контроллер памяти можно смело назвать анахронизмом: все современные x86-системы оснащены как минимум 2-канальными контроллерами памяти, а некоторые — даже 3-канальными.

Скорость чтения и записи

Скорость чтения и записи информации в память теоретически ограничивается исключительно пропускной способностью самой памяти. Так, например, двухканальный контроллер памяти стандарта DDR2-800 теоретически способен обеспечить скорость чтения и записи информации, равную 8 байт (ширина шины) * 2 (количество каналов) * 2 (протокол DDR, обеспечивающий передачу 2 пакетов данных за 1 такт) * 400'000'000 (фактическая частота работы шины памяти равная 400 МГц, т.е. 400 млн. тактов в секунду). Упомянем, что полученное произведение измеряется не в МБ/с (ГБ/с), а млн. (млрд.) байт/с, что несколько меньше честных двоичных «мега-» и «гига-». Даже с учётом этого, значения, получаемые в результате практических тестов, как правило, чуть ниже теоретических: сказывается «неидеальность» конструкции контроллера памяти, плюс накладки (задержки), вызванные работой подсистемы кэширования самого процессора (см. ниже раздел про процессорный кэш). Однако основной «подвох» содержится даже не в накладках, а в том, что скорость «линейного» чтения или записи является вовсе не единственной характеристикой, влияющей на фактическую скорость работы процессора с ОЗУ. Необходимо кроме линейной скорости считывания или записи учитывать ещё и такую характеристику, как латентность.

Латентность

Латентность (она же — задержка) является не менее важной характеристикой с точки зрения быстродействия подсистемы памяти, чем скорость «прокачки данных». Большая скорость обмена данными хороша тогда, когда их размер относительно велик, но если нам требуется «понемногу с разных адресов» — то на первый план выходит именно латентность. Что это такое? В общем случае — время, которое требуется для того, чтобы начать считывать информацию с определённого адреса. И действительно: с момента, когда процессор посылает контроллеру памяти команду на считывание (запись), и до момента, когда эта операция осуществляется, проходит определённое время. Причём оно вовсе не равно времени, которое требуется на пересылку данных. Приняв команду на чтение или запись от процессора, контроллер памяти «указывает» ей, с каким адресом он желает работать. Доступ к любому произвольно взятому адресу не может быть осуществлён мгновенно. Возникает задержка: адрес указан, но память не готова предоставить к нему доступ, особенно если он указывает на слишком далёкое от предыдущей операции место (по разнице адресов). В общем случае, эту задержку и принято называть латентностью. У разных типов памяти она разная. Так, например, память типа DDR3 имеет в среднем большие задержки, чем DDR2 (при одинаковой частоте передачи данных). В результате, если данные в программе расположены «хаотично» и «небольшими кусками», либо метод считывания или записи совсем не последовательный, то скорость обмена становится намного менее важной, чем скорость доступа к «началу куска», т.к. задержки при переходе на очередной адрес влияют на быстродействие системы намного сильнее, чем скорость считывания или записи.

«Соревнование» между скоростью чтения (записи) и латентностью — одна из основных головных болей разработчиков современных систем: к сожалению, рост скорости чтения (записи) почти всегда приводит к увеличению латентности. Так, например, память типа DDR обладает в среднем лучшей (меньшей) латентностью, чем DDR2. В свою очередь, у DDR3 латентность ещё выше (то есть хуже), чем у DDR2. Правда, здесь следует хорошо понимать, каким образом следует правильно сравнивать латентность. Если вы интересовались данным вопросом, вам наверняка хорошо знакома строчка вида «4-4-4-12», обозначающая как раз величину задержек при выполнении некоторых операций. Задержки в данном случае указаны в тактах частоты, на которой работает память. В то же время, если нас интересует латентность как единица измерения скорости, то считать её нужно не в тактах, а в секундах. Именно на этом часто «прокалываются» не очень хорошо разбирающиеся в вопросе пользователи, не понимающие, почему латентность, к примеру, в 6 тактов, может быть меньше, чем латентность в 4 такта. А всё очень просто: например, если модуль памяти с латентностью в 6 тактов, работает на частоте 800 МГц, а модуль памяти с латентностью 4 — на частоте 400 МГц — то совершенно очевидно, что 6 тактов на частоте 800 МГц займут меньше времени, чем 4 на частоте 400.

Также следует понимать, что «общая» латентность подсистемы памяти зависит не только от неё самой, но и от контроллера памяти и места его расположения — все эти факторы тоже влияют на задержку. Именно поэтому компания AMD в процессе разработки архитектуры AMD64 решила «одним махом» решить проблему высокой латентности, интегрировав контроллер прямо в процессор — чтобы максимально «сократить дистанцию» между процессорным ядром и модулями ОЗУ. Затея удалась, но с подвохом: теперь система на базе процессора AMD может работать только с той памятью, на которую рассчитан контроллер процессора. Наверное, поэтому компания Intel долго не решалась на такой кардинальный шаг, предпочитая действовать традиционными методами: усовершенствуя контроллер памяти в чипсете и механизм предзагрузки в процессоре (про него см. ниже) — пока всё-таки не согласилась, что идея AMD выгодней.

В завершение заметим, что понятия «скорость чтения / записи» и «латентность», в общем случае, применимы к любому типу памяти — в том числе не только к классическому ОЗУ (SDR, Rambus, DDR, DDR2, DDR3, …), но и к кэшу (см. ниже). Процессор: сведения общего характера

Понятие архитектуры

Архитектура как совместимость с кодом

Наверняка вы часто встречались с термином «x86», или «Intel-совместимый процессор» (или «IBM PC compatible» — но это уже по отношению к компьютеру). Иногда также встречается термин «Pentium-совместимый» (почему именно Pentium — вы поймете сами чуть позже). Что скрывается за всеми этими названиями? На данный момент наиболее корректно с точки зрения авторов выглядит следующая простая формулировка: современный x86-процессор — это процессор, способный корректно исполнять машинный код архитектуры x86-64 (архитектура 32-битных процессоров Intel, дополненная 64-битными расширениями от AMD). В первом приближении современный x86 — это код, исполняемый процессором i80386 (известным в народе как «386-й»), окончательно же основной набор команд 32-битной архитектуры IA32 сформировался с выходом процессора Intel Pentium Pro (с очень незначительным дополнениями в следующих процессорах). Что означает «основной набор» и какие есть еще? Для начала ответим на первую часть. «Основной» в данном случае означает то, что с помощью исключительно этого набора команд может быть написана любая программа для процессора архитектуры x86.

Кроме того, у архитектуры IA32 существуют «официальные» расширения (дополнительные наборы команд) от разработчика самой архитектуры, компании Intel: MMX, многочисленные SSE (вплоть до 4.2) и AVX. Также существуют «неофициальные» (не от Intel) расширенные наборы команд: EMMX, 3DNow!, Extended 3DNow!, SSE4.a и XOP — их разработала компания AMD. Впрочем, «официальность» и «неофициальность» в данном случае понятие относительное — де-факто всё сводится к тому, что некоторые расширения набора команд Intel как разработчик изначального набора признаёт, а некоторые — нет, разработчики же программного обеспечения используют то, что им лучше всего подходит. В отношении расширенных наборов команд существует правило хорошего тона: прежде чем их использовать, программа должна проверить, поддерживает ли их процессор. Иногда отступления от этого правила встречаются (и могут приводить к неправильному функционированию программ), но объективно это является проблемой некорректно написанной программы, а не процессора.

Для чего предназначены дополнительные наборы команд? В первую очередь — для увеличения быстродействия при выполнении наиболее частых операций. Одна команда из дополнительного набора, как правило, выполняет действие, для которого понадобилась бы небольшая процедура, состоящая из команд основного набора, причём специальная команда выполняется процессором быстрее, чем заменяющая её последовательность. Однако в 99% случаев ничего такого, чего нельзя было бы сделать с помощью основных команд, команды из дополнительного набора также не делают. Таким образом, упомянутая выше программная проверка поддержки дополнительных наборов команд процессором должна выполнять очень простую функцию: если, например, процессор поддерживает SSE — значит, считать будем быстро и с помощью команд из набора SSE. Если нет — будем считать медленнее, с помощью команд из основного набора. Корректно написанная программа обязана действовать именно так. Впрочем, сейчас практически никто не проверяет у процессора наличие поддержки MMX, т.к. все CPU, вышедшие за последние 10 лет, этот набор поддерживают гарантированно. Для справки приведём табличку, на которой обобщена информация о поддержке различных расширенных наборов команд различными десктопными (предназначенными для настольных ПК) и некоторыми мобильными процессорами.

ПроцессорГод выпускаx86-64PProMMXВерсияSSE3DNow!
Процессоры Intel
Pentium1993
Pentium Pro1995x
Pentium MMX1997x
Pentium IIxx
Celeron1998xx
Pentium III1999xx1
Pentium 42000xx2
Celeronxx1
Celeron2002xx2
Pentium M2003xx2
Pentium 42004xxx3
Celeron Dxx3
Pentium D, EE2005xxx3
Celeron D
Celeron2006xxx3S
Celeron Mxx3
Core Solo, Duo
Core 2xxx3S
Core 22007xxx4.1
Celeron Mxxx3S
Pentium (DC)
Pentium (DC, M)xx3
Atom2008xxx3S
Celeron (DC)
Core i7xxx4.2
Core i3, i52009xxx4.2
Core i92010xxx4.2
Процессоры AMD
K51996
K61997x
K6-3D, K6-2+1998xx
K6-III1999xx
Athlonxxx
Duron2000xxx
Athlon XP2001xx1x
Athlon 4 (M)
Duron
Athlon 642003xxx2x
Sempron2004xx1 (2)x
Athlon XP-M2005xx2x
Sempronxxx2 (3)x
Athlon (64) X2xxx3x
Turion (M)
Sempron (M)xx3x
Phenom2007xxx4.ax
Athlon X22008xxx4.ax
Athlon Neo2009xxx3x
Phenom IIxxx4.ax
Athlon II, X3, X4

Примечания:PPro — означает наличие всех общих команд;Версия SSE — номер последней поддерживаемой версии, подразумевая и все предыдущие;Ряд SSE: SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2;Для процессоров AMD наличие SSE4.a означает поддержку только SSE, SSE2, SSE3 и SSE4.a;(M) — мобильная модель, даже если явно в имени не указано;

(DC) — двухядерный процессор, указано в индексе модели.

На данный момент всё популярное десктопное программное обеспечение (операционные системы Windows и Linux, офисные пакеты, компьютерные игры, и прочее) разрабатывается именно для x86-процессоров. Оно выполняется (за исключением «дурно воспитанных» программ) на любом x86-процессоре, независимо от того, кто его произвёл. Поэтому вместо ориентированных на разработчика изначальной архитектуры терминов «Intel-совместимый» или «Pentium-совместимый», стали употреблять нейтральное название: «x86-совместимый процессор», «процессор с архитектурой x86». В данном случае под «архитектурой» понимается архитектура системы команд (ISA, Instruction Set Architecture) — совместимость с определённым набором команд с точки зрения программиста. Есть и другая трактовка того же термина.

Архитектура как характеристика семейства процессоров

«Железячники» — люди, работающие в основном не с программным обеспечением, а с аппаратным — под «архитектурой» понимают несколько другое (правда, более корректно то, что они называют «архитектурой», называется «микроархитектурой», но приставку «микро» частенько опускают). Для них «архитектура CPU» — это некий набор свойств, присущий целому семейству процессоров, как правило, выпускаемому в течение многих лет (иначе говоря — их организация и «внутренняя конструкция»). Например, любой специалист по x86 CPU вам скажет, что процессор с ALU, работающими на удвоенной частоте, QDR-шиной, Trace cache, и, возможно, поддержкой технологии Hyper-Threading — это «процессор архитектуры NetBurst» (не пугайтесь незнакомых терминов — все нужные будут разъяснены чуть позже). Таким образом, понятие «архитектуры» применительно к процессорам двойственно: под ним может пониматься как совместимость с единым набором команд, так и совокупность аппаратных решений, присущих определённой достаточно широкой группе процессоров.

64-битные расширения классической x86 (IA32) архитектуры

В 2003 г. сначала AMD, а через год — и Intel, анонсировали практически идентичные технологии (впрочем, AMD предпочитает называть это архитектурой), благодаря которым классические x86 (IA32) CPU получили статус 64-битных. В случае с AMD данная технология получила наименование «AMD64», в случае с Intel — сначала «EM64T», а теперь Intel 64. Впрочем, сегодня часто указывают нейтральное «x86-64» — как общее обозначение всех 64-битных расширений архитектуры x86, не привязанное к зарегистрированным торговым маркам. Употребление одного из трёх приведённых наименований зависит больше от личных предпочтений употребляющего, чем от фактических различий — ибо различия между AMD64 и EM64T умещаются на кончике очень тонкой иглы. Так или иначе, всё сводится к следующему: все целочисленные регистры (общего назначения) стали вместо 32-битных 64-битными, число регистров (и общих, и векторных) удвоилось, 32-битные команды x86-кода получили свои 64-битные аналоги, а объём адресуемой памяти (и физической, и виртуальной) многократно увеличился (за счёт того, что логический адрес приобрёл вместо 32-битного 64-битный формат). Количество маркетинговых спекуляций на тему «64-битности» превысило все разумные пределы, поэтому следует рассмотреть достоинства данного нововведения.

Что не изменилось? В первую очередь — быстродействие процессоров. Вопиющей глупостью будет считать, что один и тот же процессор при переходе из привычного 32-битного в 64-битный режим (а 32-битный режим все нынешние x86 CPU поддерживают в обязательном порядке) станет работать вдвое быстрее. Разумеется, в некоторых случаях ускорение от использования 64-битной целочисленной арифметики может присутствовать — но количество этих случаев сильно ограничено, и большинства современного пользовательского программного обеспечения они никак не касаются. Кстати: а почему мы употребили термин «64-битная целочисленная арифметика»? А потому, что блоки операций с плавающей точкой (см. ниже) во всех x86-процессорах уже давным-давно не 32-битные. И даже не 64-битные. Классический вещественный вычислитель, окончательно ставший частью CPU ещё во времена старого доброго 32-битного Intel Pentium* — уже был 80-битным (и до сих пор таков). Векторные операнды команд SSE (с любой цифрой) — и вовсе 128-битные! В этом плане архитектура x86 достаточно парадоксальна: притом, что формально процессоры данной архитектуры достаточно долгое время оставались 32-битными — разрядность тех блоков, где «большая битность» была реально необходима — наращивалась совершенно независимо от остальных (более подробно о проблеме разрядности процессоров можно почитать в отдельном материале). Например, процессоры AMD Athlon XP и Intel Pentium 4 «Northwood» совмещали в себе блоки, работающие с 32-битными, 80-битными, и 128-битными операндами. 32-битными оставались лишь основной набор команд (унаследованный от первого процессора архитектуры IA32 — Intel 386) и адресация памяти (максимум 4 гигабайта, если не считать «эквилибристического выверта» от Intel — Physical Address Extension, позволявшего «32-битным» процессорам использовать 36(!)-битную адресацию).* — первым x86 CPU, в который был интегрирован FPU (ранее он устанавливался на плату в качестве отдельного чипа), стал процессор предыдущего поколения — i486DX. Но в линейке i486 всё-таки присутствовал i486SX, в состав которого FPU не входил. Начиная с Pentium, Intel больше не выпускала x86 CPU без FPU, и эту моду быстро подхватили все остальные производители.

Таким образом, то, что процессоры AMD и Intel стали «формально 64-битными», на практике принесло нам лишь три усовершенствования: появление команд для работы с 64-битными целыми числами, увеличение количества и/или разрядности регистров, и увеличение максимального объёма адресуемой памяти. Заметим: реальной пользы этих нововведений (особенно третьего!) никто не отрицает. Равно как никто не отрицает заслуг компании AMD в продвижении идеи «осовременивания» (за счёт введения 64-битности) x86-процессоров. Мы лишь хотим предостеречь от чрезмерных ожиданий: не стоит надеяться на то, что компьютер, покупавшийся «в ценовом классе ВАЗа», от установки 64-битного программного обеспечения станет «лихим Мерседесом». Чудес на свете не бывает...

Процессорное ядро

О многоядерности (многопроцессорности) как концепции

Классическая одноядерная (однопроцессорная) схема: в памяти находится код нескольких программ («кирпичики» разного цвета), но в один момент времени процессор выполняет код только одной из них

Прежде, чем мы начнём описывать особенности многоядерных систем, нужно вначале объяснить, зачем вообще они нужны, и как за счёт большего количества ядер и/или процессоров может достигаться  положительный эффект. В данном случае мы для простоты считаем, что система, собранная на базе одного процессора с двумя ядрами, практически идентична по функционалу системе на базе двух процессоров с одним ядром — если ядра в обоих случаях идентичны*. Более подробное разъяснение можно прочитать в отдельном, более сложном материале, но хотя бы схематически описать ситуацию просто необходимо. Всё нижесказанное относится к концепции SMP (Symmetric Multiprocessing, cимметричная многопроцессорность), т.к. пока на x86 прижился именно этот вариант. Он требует, чтобы при любом числе процессоров (строго говоря — процессорных ядер) в системе они все были одинаковые, каждый может быть заменен любым другим, и все они осуществляют доступ к одному и тому же массиву памяти. * — pаньше многоядерный процессор на массовом рынке был мечтой практически неосуществимой, поэтому в тех отраслях, где требовалась высокая производительность в специфических задачах, использовались системы не многоядерные, а многопроцессорные. Вместо того, чтобы интегрировать N ядер в один чип — на системную плату устанавливали N разъёмов, и в них — N одноядерных процессоров. Условно, современный десктоп на N-ядерном процессоре, можно приравнять к N-процессорной системе. Впрочем, многопроцессорные системы есть и сейчас — для тех, кого не устраивает максимально возможное количество ядер в одном CPU. Так, например, если вам нужна 16-процессорная (16-ядерная) система — то ввиду отсутствия 16-ядерных x86-процессоров (пока, на 2009 г.…), вам придётся согласиться на 4-процессорную систему, в которой у каждого процессора будет по 4 ядра.4-процессорная системная плата, в каждый сокет которой можно установить 6-ядерный процессор. В результате мы получим 24-ядерную x86-систему.

Итак, наш главный вопрос: для чего всё это нужно? Каким образом за счёт увеличения количества ядер (процессоров) увеличивается быстродействие? Сразу расскажем, какой основной вопрос возникает при более детальном ознакомлении с многоядерными (многопроцессорными) системами: «Почему быстродействие увеличивается в разных случаях по-разному, а иногда не увеличивается вовсе?» Проще всего разъяснить это на примере простой и понятной аналогии с неким количеством работы, и неким количеством людей. Рассмотрим два самых распространённых варианта.

Вариант №1: несколько совершенно независимых друг от друга задач. Например, мы находимся в загородном доме, и нам необходимо наколоть дров и выкосить газон. Если у нас в распоряжении один человек — он будет вынужден сделать сначала одно дело, а потом другое, либо делать их параллельно, переключаясь между ними — но всё равно в один конкретный момент времени он будет занят чем-то одним. Если же есть два человека — то один может заняться колкой дров, а другой — косить газон. Заметьте: сами по себе задачи не стали выполняться быстрее — но мы экономим время за счёт того, что они выполняются параллельно. Продолжив аналогию, вы легко поймёте основной недостаток наращивания в данной ситуации количества людей  до бесконечности (а они у нас олицетворяют процессорные ядра или одноядерные процессоры): рано или поздно для ещё одного человека просто не найдётся работы. Или ресурсов: например, колоть дрова можно и вдвоём — но что делать, если у нас всего один топор?

Вариант №2: одна частично или полностью распараллеливаемая задача. Почти идеально распараллеливаемая задача (при условии, как уже было упомянуто выше, наличия должного количества ресурсов) — это та же колка дров, или, например, мытьё полов. Каждому в руки по швабре и ведру, каждому свой участок пола — и вперёд! Вы, правда, наверняка заметите, на основании банального житейского опыта, что ещё и задача должна быть соответствующего масштаба: хорошо мыть полы вчетвером в большом доме, но совершенно бессмысленно — в одной комнатушке. В случае с многоядерностью всё совершенно аналогично: быстро выполняемая задача, даже если она хорошо параллелится, вызывает давно известный эффект: согласование действий между выполняющими работу начинает занимать время, сопоставимое с временем выполнения самой работы каждым исполнителем. Русская пословица «у семи нянек дитя без глаза» примерно характеризует данную ситуацию.

Более сложный случай — например, варка борща. Конечно, хозяйка может поручить кому-то почистить овощи, кому-то нарезать, и т.д., но всё равно на некотором этапе у нас начнётся достаточно длительный процесс (собственно варки), в котором участие более чем одного человека совершенно не требуется. Это и есть частично распараллеливаемая задача: некоторые её этапы могут выполняться параллельно, а некоторые — нет. Совершенно очевидно, что даже если выделить на выполнение этой задачи двух людей, в 2 раза её выполнение не ускорится (а если четырёх — то в случае с борщом, четвёртый может оказаться в большинстве случаев лишним). И у многоядерных процессоров на частично распараллеливаемой задаче не все ядра могут задействоваться одновременно всё время. А значит, некоторые из них как минимум иногда будут простаивать.

Подытожим: добавление ещё одного ядра не всегда приводит к ускорению, а даже если и приводит — то не всегда настолько, сколько можно было бы ожидать в идеальном случае. Фактически, всё зависит от решаемых задач (используемых программ). Некоторые задачи параллелятся хорошо, некоторые — не очень, некоторые не параллелятся вообще. Почти идеально в большинстве случаев параллелятся две независимых задачи, но… для этого нужно, чтобы у вас достаточно часто возникала потребность решать несколько независимых задач одновременно! Говоря конкретней, двухъядерный процессор на программах обычного пользователя в среднем получит ускорение примерно раза в полтора, а 4-ядерный — примерно в два по сравнению с одноядерным. А вот при запуске «профессиональных» программ кратность ускорения часто почти равна числу ядер.

Число ядер и технология Hyper-Threading

Первое, что надо сказать о ядрах — в одном процессоре их бывает много. В вашем их, скорее всего, не менее двух, а вообще их может быть от 1 до 6 (скоро — и больше). Все ядра одинаковые, но кроме них в процессоре есть и обслуживающие их общие блоки — общий кэш, контроллер памяти и шины обмена с другими процессорами и/или с чипсетом. В новейших процессорах к этому списку скоро добавятся и специализированные ядра, например, для 3D-графики и декодирования видео. Когда говорят об устройстве ядер, то имеют ввиду каждое ядро многоядерного процессора (даже если говорится «ядро» в единственном числе).Многоядерная (многопроцессорная) система: благодаря наличию двух ядер (процессоров), можно одновременно исполнять код двух программ

Как было сказано, у многоядерности есть ограничения по увеличению производительности. Когда задачи или их части выполняются параллельно, ядра конкурируют за доступ к общим блокам. Например, если запустить две задачи, сильно зависящие от пропускной способности памяти, и которым не хватит объёма кэша каждого ядра, то производительности общего для ядер кэша, а также контроллера памяти может быть недостаточно, чтобы насытить сразу два ядра. В результате они оба будут простаивать до половины времени — реальное увеличение скорости по сравнению с однопоточным исполнением может быть околонулевым. Противоположная ситуация, когда программы оптимизированы под многоядерные процессоры и не перегружают разделяемые ресурсы, выглядит примерно так: процессор исполняет столько потоков, сколько у него ядер, причём каждый поток в основном использует блоки своего ядра, а общение ядер между собой, а также с памятью достаточно редко, чтобы даже исполнение нескольких потоков не перегружало общие элементы процессора и не приводило к задержкам работы ядер. Подобрать по такому критерию несколько разных программ весьма сложно, а вот оптимизировать одну — удаётся куда чаще. Именно в таких случаях и удаётся получить то, что называется линейным ростом производительности от числа потоков (фактически — ядер): 2 ядра работают вдвое быстрее одного, 4 — вдвое быстрее двух, и т.д.. Всё вышесказанное касается и многопроцессорных систем, где число ядер каждого CPU надо умножить на число последних.

Дополнительную сложность вносит поддержка некоторыми процессорами технологии Hyper-Threading (гиперпоточности). Она позволяет одному ядру работать за два — хотя и не так эффективно, как реально существующая пара ядер, зато куда дешевле. При этом операционная система сообщает о процессоре с вдвое большим числом ядер, поскольку видит число ядер логических (по максимальному количеству одновременно запускаемых программ), а не физических (по числу реально выполняемых). Изменение производительности может быть от почти незаметного замедления до внушительного (20-50 %) ускорения и сильно зависит от набора исполняемых программ, а в среднем же ускорение равно 10-15%. К сожалению, чем лучше программа оптимизирована под настоящую многоядерность, тем меньше она выиграет от «виртуальной» за счёт Hyper-Threading.Процессор с поддержкой Hyper-Threading: на одном физическом ядре одновременно выполняется код двух приложений

Различия между ядрами одной микроархитектуры

«Процессорное ядро» (как правило, для краткости его называют просто «ядро») — это конкретное воплощение (микро)архитектуры (т.е. архитектуры в «аппаратном» смысле), являющееся стандартом для целой серии процессоров. Например, K10 — это микроархитектура, которая лежит в основе многих сегодняшних процессоров AMD: Athlon II, Phenom, Phenom II, Opteron. Микроархитектура задаёт общие принципы: «средний» по длине конвейер, исполнение до трёх команд за такт, предсказание переходов и внеочередное исполнение, и прочие «глобальные» особенности. Ядро — более конкретное воплощение. Например, процессоры микроархитектуры К10 с двумя ядрами, без поддержки многопроцессорности и кэша L3, с шиной HyperTransport частотой в 2 ГГц — это более-менее полное описание ядра Regor для Athlon II.

Можно сказать что «ядро» — это конкретное воплощение определённой микроархитектуры «в кремнии», обладающее (в отличие от самой микроархитектуры) набором строго обусловленных характеристик. Микроархитектура — аморфна, она описывает общие принципы построения процессора. Ядро — микроархитектура, «обросшая» всевозможными параметрами и характеристиками. Чрезвычайно редки случаи, когда процессоры сменяли микроархитектуру, сохраняя название. И, наоборот, практически любое наименование процессора хотя бы несколько раз за время своего существования «меняло» ядро. Например, общее название серии процессоров AMD — «Athlon 64» — это одна микроархитектура (K8), но целых 13 ядер — от Sledgehammer (2003 г.) до Huron (2009 г.). Разные ядра, построенные на одной микроархитектуре, могут иметь в том числе разное быстродействие.

Ревизии

Ревизия — одна из модификаций ядра, крайне незначительно отличающаяся от предыдущей, почему и не заслуживает звания «нового ядра». Как правило, из выпусков очередной ревизии производители процессоров не делают большого события, это происходит «в рабочем порядке». Так что даже если вы покупаете один и тот же процессор, с полностью аналогичным названием и характеристиками, но с интервалом где-то в полгода — вполне возможно, фактически он будет уже немного другой. Выпуск новой ревизии, как правило, связан с какими-то мелкими усовершенствованиями. Например, удалось чуть-чуть снизить энергопотребление, понизить напряжение питания, что-то оптимизировать, или была устранена пара мелких (иногда не очень…) ошибок. С точки зрения производительности была всего пара примеров, когда бы одна ревизия ядра отличалась от другой настолько существенно, чтобы об этом имело смысл говорить. Хотя чисто теоретически возможен и такой вариант — например, подвергся оптимизации один из блоков процессора, ответственный за исполнение нескольких команд. Подводя итог, можно сказать что «заморачиваться» ревизиями процессоров чаще всего не стоит: в очень редких случаях изменение ревизии вносит какие-то кардинальные изменения.

Частота работы ядра

Как правило, именно этот параметр в просторечии именуют «частотой процессора». Хотя в общем случае определение «частота работы ядра» всё же более корректно, так как совершенно не обязательно все составляющие CPU функционируют на той же частоте, что и ядро (наиболее частым примером обратного являлись старые «слотовые» x86 CPU — Intel Pentium II и Pentium III для Slot 1, AMD Athlon для Slot A — у них L2-кэш функционировал на 1/2, и даже иногда на 1/3 частоты работы ядра). Примерно также сегодня в большинстве процессоров работает кэш L3 — на своей отдельной частоте, меньшей, чем у каждого ядра. Ещё одним распространённым заблуждением является уверенность в том, что частота работы ядра однозначным образом определяет производительность. Это дважды не так.

Во-первых, каждое конкретное процессорное ядро (в зависимости от того, как оно спроектировано, сколько содержит исполняющих блоков различных типов, и т.д. и т.п.) может исполнять разное число команд за один такт, частота же — это всего лишь количество таких тактов в секунду. Таким образом (приведённое далее сравнение, разумеется, очень сильно упрощено) процессор, ядро которого исполняет 3 инструкции за такт, может иметь на треть меньшую частоту, чем процессор, исполняющий 2 инструкции за такт — и при этом обладать полностью аналогичным быстродействием.

Во-вторых, даже в рамках одного и того же ядра, увеличение частоты вовсе не всегда приводит к пропорциональному увеличению быстродействия. Здесь вам очень пригодятся знания, которые вы могли почерпнуть из раздела «Общие принципы взаимодействия процессора и ОЗУ». Дело в том, что скорость исполнения команд ядром процессора — это вовсе не единственный показатель, влияющий на скорость выполнения программы. Не менее важна скорость поступления команд и данных на CPU. Представим себе чисто теоретически такую систему: быстродействие процессора — 10'000 команд в секунду, скорость работы памяти — 1000 байт в секунду. Даже если принять, что одна команда занимает не более одного байта, а данных у нас нет совсем, с какой скоростью будет исполняться программа в такой системе? Не более 1000 команд в секунду, и производительность CPU тут совершенно ни при чём: мы будем ограничены не ей, а скоростью поступления команд в процессор. Таким образом, следует понимать: невозможно непрерывно наращивать одну только частоту ядра, не ускоряя одновременно подсистему памяти, так как в этом случае начиная с определённого этапа, увеличение частоты CPU перестанет сказываться на увеличении быстродействия системы в целом.

Наконец, у компании Intel есть технология TurboBoost, особенность которой в том, что процессоры с её поддержкой вообще не имеют никакой конкретной частоты чего-либо. Смысл TurboBoost — увеличивать частоту загруженных ядер в зависимости от числа простаивающих, а также от температуры и энергопотребления всего процессора. В результате «нормальная» частота (написанная на коробке процессора или в прайс-листе) реально почти всегда будет превышена на 133-666 МГц (в мобильных процессорах серии Core i7 возможен разгон на 1333 МГц, если работает только одно ядро), причём всё время меняясь. Грубо говоря, можно сказать, что TurboBoost даст примерно +10% к скорости «за просто так».

Виртуализация

Виртуализация в вычислительной технике — это возможность запускать несколько операционных систем (и программы из-под каждой из них) так, что они будут работать будто бы на своих отдельных компьютерах (т.е. подразумевается виртуализация «железа» по отношению к програмам). Впервые она появилась аж в 60-е годы на мейнфреймах IBM и до недавнего времени была полезна лишь для программирования и высокопроизводительных сетевых серверов. Однако новая ОС фирмы Microsoft Windows 7 уже требует аппаратную поддержку виртуализации в процессоре, если предполагается запускать 32-битные программы, написанные для Windows XP и более ранних версий (т.е. читай — всегда). Так зачем нужна эта аппаратная поддержка, если ранее и программной справлялись?

Аппаратная поддержка виртуализации в процессоре фактически означает наличие дополнительного поднабора команд, который позволяет инициировать, вызвать, завершать и переключать виртуальные ОС быстрее и с более надёжной изоляцией друг от друга (что важно для устойчивости и безопасности всей системы), чем программными средствами. Как обычно, оба главных производителя CPU стараются подчеркнуть преимущества своих реализаций, так что им даны разные имена: Intel Virtualization Technology (Intel VT) и AMD Virtualization (AMD-V). Причём между ними действительно есть небольшая разница, но, опять же, крайне незначительная и не приводящая к несовместимости. С точки зрения пользователя вердикт прост — поддержку виртуализации в процессоре лучше иметь, чем не иметь, т.к. даже если она не пригодится сейчас, то, возможно, пригодится через пару лет, а разница в стоимости у процессоров с и без неё почти незаметна. Более того — в новых CPU, виртуализацию поддерживают все модели, так что «хочешь, не хочешь»…

Особенности образования названий процессоров

Раньше, когда небо было голубее, пиво — вкуснее, а девушки — красивее (прим. ред.: мнение редакции не всегда совпадает с мнением авторов, особенно насчёт девушек), процессоры называли просто: имя производителя + название модельного ряда («линейки») + частота. Например: «AMD K6-2 450 MHz». В настоящее время оба основных производителя от этой традиции отошли и вместо частоты употребляют какие-то непонятные циферки, обозначающие невесть что. В первой версии статьи на этом месте было краткое объяснение того, что же эти циферки обозначают. Однако с тех пор (а прошло всего 3 года) оба основных производителя x86 CPU неоднократно меняли и дополняли эти правила, так что фактически уследить за ними в рамках даже регулярно обновляющегося цикла статей невозможно, да и не очень требуется. Есть способы лучше. Если вам нужно узнать основные характеристики какого-то процессора, проще всего просто набрать его полное имя в Гугле или Яндексе, и среди первой десятки результатов вы наверняка найдёте краткое описание его внутренностей. Если же требуется сравнить разные процессоры, названия которых вы не помните или не знаете, подойдёт Википедия: вот список всех процессоров AMD, а вот — процессоры Intel. Для любителей экзотики есть ещё процессоры VIA. Ссылки на детальные списки процессоров по линейкам (Celeron, Sempron, Core i7, Phenom, Nano и т.п.) см. в самом внизу страницы напротив слова Lists.

Что касается общего положения, то у обоих основных производителей ситуация примерно такая (с многочисленными исключениями, разумеется). Сначала указывается название линейки процессоров. Оно говорит об общей направленности применения: бюджетные, основные (mainstream), дешёвые и экономные (для нетбуков), основные и экономные (для ноутбуков), просто быстрые и быстрые с поддержкой многопроцессорности (для рабочих станций и серверов). После указывается номер поколения этой линейки — не обязательно порядковый, но чем больше — тем «круче». Затем, на том месте, где ранее была частота — 2-4-значное число «рейтинга» производительности, обозначающее сразу несколько методов её увеличения:

  • число физических ядер (логических больше, если у процессора есть технология типа Hyper-Threading);
  • их частота (при наличии технологии Turbo Boost или ей подобной — максимальная частота продолжительной надёжной работы всех ядер с их полной загрузкой, максимальной допустимой температурой корпуса процессора и «нормальным» напряжением питания);
  • полный объём всех кэшей;
  • число контроллеров и шин памяти и чипсета;
  • частота этих шин;
  • возможность частотного разгона разными способами;
  • наличие дополнительных специализированных блоков и шин;
  • разные мелочи.

Причём это число не является оценкой самой производительности, т.е. вы не только не сможете сказать, насколько модель 2300 быстрее модели 1200, но даже и какая из них быстрее в конкретной программе. Можно лишь утверждать, что с точки зрения производителя, модель 2300 сложнее в производстве, чем модель 1200 — у неё выше некоторые технические характеристики, больше ядер или кэша, и т.д. и т.п. При этом подразумевается, что раз уж модель с более высоким номером снабдили всеми этими «наворотами» — то она и работать будет быстрее (иначе зачем было снабжать?) Однако практика свидетельствует, что сбывается это предположение отнюдь не всегда.

Также иногда к «рейтингу» спереди или сзади добавляются 1-2 буквы для обозначения класса потребления энергии: для немобильных процессоров — просто «обычный» и «экономный», а для мобильных — более детальная градация.

Измерение скорости «в мегагерцах» — как это возможно?

Никак это не возможно, потому что скорость не измеряется в мегагерцах, как не измеряется расстояние в килограммах. Однако господа маркетологи давно уже поняли, что в словесном поединке между физиком и психологом побеждает всегда последний — причём независимо от того, кто на самом деле прав (прим. маркетологов: хотите об этом поговорить?) Поэтому мы и читаем про «сверхбыструю 1066-мегагерцевую шину», мучительно пытаясь понять, как скорость может измеряться с помощью частоты. На самом деле, раз уж прижилась такая извращённая тенденция, нужно просто чётко представлять себе, что имеется в виду. А имеется в виду следующее: если мы «закрепим» ширину шины на N битах — то её пропускная способность действительно будет зависеть от того, на какой частоте данная шина функционирует, и какое количество данных она способна передавать за такт. По обычной процессорной шине с «одинарной» скоростью (такая шина была, например, у процессора Intel Pentium III) за такт передаётся 64 бита, то есть 8 байт. Соответственно, если рабочая частота шины равна 100 МГц (100'000'000 тактов в секунду) — то скорость передачи данных будет равна 8 байт * 100'000'000 герц ≈ 763 мегабайта в секунду (а если считать в «десятичных мегабайтах», в которых принято считать потоки данных, то ещё красивее — 800 мегабайт в секунду). Соответственно, если на тех же 100 мегагерцах работает DDR-шина, способная передавать за один такт удвоенный объём данных — скорость вырастет ровно вдвое. Поэтому, согласно парадоксальной логике господ маркетологов, данную шину следует именовать «200-мегагерцевой». Хотя реальная частота работы у вышеописанных шин одинаковая — 100 мегагерц. Вот так «мегагерцы» и стали синонимом скорости.

Впрочем, независимые источники также указывают производительность шины не в герцах, а в транзакциях (т.е. актах передачи данных) в секунду — МТ/s или GТ/s (с приставками мега и гига). Это число надо умножить на ширину шины в байтах. Тем не менее, главное здесь — выучить наизусть один простой принцип: если уж мы занимаемся таким извращением, как сравнение скорости двух шин между собой «в мегагерцах» — то они обязательно должны быть одинаковой ширины и одного типа передачи за такт. Иначе получается как в одном форуме, где человек всерьёз доказывал, что пропускная способность AGP2X («133-мегагерцевая», но 32-битная шина) — выше, чем пропускная способность FSB у Pentium III 800 (реальная частота 100 МГц, ширина 64 бита).

О некоторых особенностях технологий DDR и шин НТ и QPI

Как уже было сказано, в режиме DDR по шине за один такт передаётся удвоенный объём информации. Правда, в документах, ориентированных больше на прославление достижений производителей, чем на объективное освещение реалий, почему-то не всегда указывают одно маленькое «но»: режимы удвоенной скорости включаются только при пакетной передаче данных, а она всегда включена не во всех типах шин. Т.е. если мы запросили из памяти парочку мегабайтов с адреса X по адрес Y — то да, эти два мегабайта будут переданы с удвоенной скоростью. А вот сам запрос на данные может быть передан по шине и с «одинарной» скоростью! Соответственно, если запросов у нас много, а размер пересылаемых данных не очень велик, то количество данных, которые «путешествуют» по шине с одинарной скоростью (а запрос — это тоже данные) будет почти равно количеству тех, которые передаются со скоростью удвоенной. Это касается шин доступа к памяти и старых шин связи с чипсетом, но новые шины включают пакетную передачу для любых видов информации. Новые — это HyperTransport (она же — НТ, но не путайте с HyperThreading) для процессоров AMD и QPI для Intel. У новичков есть четыре главных особенности, отличающие их от предыдущих решений: эти шины уже (как правило, 32 бита), в несколько раз быстрее по частоте, могут соединять только 2 устройства (на старые шины можно «повесить» и более) и, самое интересное, — они полнодуплексные. Т.е. фактически состоят из двух разнонаправленных половинок, позволяющих одновременно передавать данные в обе стороны. Так что для оценки скорости надо различать три цифры: частота работы шины (как правило, в спецификациях указывается именно она), количество передач данных в одном направлении (вдвое больше частоты за счёт DDR) и число совокупных передач данных в обоих направлениях (ещё вдвое больше). Теперь, если умножить второе или третье число на ширину шины в байтах, мы получим заветные гигабайты в секунду (точнее, млрд. байт/с) — в одном или двух направлениях.

Возможно, через несколько лет таким же изменениям подвергнется и шина между процессором и памятью — она станет узкой, сверхбыстрой и двухнаправленной. Однако возможность подключать несколько модулей памяти наверняка сохранится.

Внешние данные: корпус, разъём, охлаждение

У любого процессора есть не только интерьер, но и экстерьер — «одёжка», по которой его встречают. Не пользователи, конечно, а коллеги-компоненты по компьютеру. Чтобы процессор вообще заработал, требуется соблюсти несколько важных пунктов.

Во-первых, у процессора есть корпус определённого размера с определённым количеством выводов в определённом расположении — всё это должно точно подходить к разъёму для CPU на материнской плате (компактные процессоры для неттопов и нетбуков продаются вместе с мат. платами сразу запаянные в них). Тип разъёма (сокета) обозначается буквой или числом выводов. Для каждого процессора указывается тот разъём, который для него подходит. Причём «подходит» означает не только механическую совместимость (т.е. процессор физически умещается в разъёме в единственно верном положении, обозначенном специальной меткой-ключём), но и электрическую, силовую и интерфейсную. Последнее гарантирует, что выводы и контакты расположены в ожидаемом порядке, на выводы питания подаётся именно то напряжение и та сила тока, которая нужна, а к информационным выводам подключены нужные шины и линии управления чипсета и периферии. Впрочем, установка процессора нового поколения вместо старого даже при совпадении разъёма не всегда закончится удачно, потому что…

Во-вторых, BIOS (загрузочная программа, стартующая сразу после включения компьютера и записанная в микросхеме флеш-памяти на материнской плате) ожидает обнаружить лишь те виды процессоров, которые в него заложили разработчики системной платы. Но если ваш новый процессор вышел позже, то для поддержки всех его функций придётся обновить и сам BIOS, новую версию которого («прошивку») нужно загрузить с сайта производителя материнской платы, убедившись, что в ней есть поддержка новинки. Впрочем, иногда это не требуется — если новый CPU не сильно отличается от старого, то и обновление BIOS'а ему не нужно, но это должно быть явно сказано производителем процессора или системной платы.

В-третьих, даже если процессор точно заработал всеми своими наворотами и гигагерцами, есть ещё кое-что, без чего его работа может очень быстро закончится — охлаждение. При покупке стоит обратить внимание на то, сколько процессор выделяет энергии (эта величина почти равна её потреблению) — параметр TDP (Thermal Design Power), измеряемый в ваттах. Фактически это требование к системе охлаждения — именно столько тепла должен отводить кулер или радиатор, чтобы процессор не перегревался (для каждого процессора и вида корпуса есть своя максимально допустимая температура, гарантирующая продолжительную надёжную работу). Если перегрев всё-таки произойдёт, процессор сначала станет снижать фактическую частоту работы (причём различными программами-мониторами это не обязательно фиксируется), а затем может и вовсе подать сигнал аварийного отключения питания всего компьютера. Для этого в каждый современный CPU встроен датчик температуры, выдающий показания системной плате, а также собственным механизмам защиты, главная цель которых — не дать физически сжечь процессор (ценой потери производительности и даже данных).Процессор: детальней

Кэш

Общее описание и принцип действия

Во всех современных процессорах есть кэш (cache). Это разновидность памяти (кардинальные отличия кэша от ОЗУ — скорость работы и меньшая задержка доступа), которая является своего рода «буфером» между контроллером памяти и процессором и служит для увеличения скорости работы с ОЗУ. Каким образом? Чтобы объяснить, сразу откажемся от попахивающих детским садом сравнений, которые частенько встречаются в популяризаторской литературе на процессорную тематику (бассейны, соединённые трубами разного диаметра, и т.д. и т.п.). Всё-таки человек, который дочитал статью до этого места и не заснул (прим. ред. — а ведь авторы так старались!), наверное, способен выдержать и «переварить» чисто техническое объяснение, без бассейнов, кошечек и одуванчиков.

Итак, представим, что у нас есть много сравнительно медленной памяти (пусть это будет ОЗУ размером 1 мегабайт) и относительно мало очень быстрой (пусть это будет кэш размером всего 1 килобайт). Как нам с помощью этого несчастного килобайта увеличить скорость работы со всей памятью вообще? А вот здесь следует вспомнить, что данные в процессе работы программы, как правило, не бездумно перекидываются с места на место — они изменяются. Считали из памяти значение какой-то переменной, прибавили к нему какое-то число — записали обратно на то же место. Считали массив, отсортировали по возрастанию — опять-таки записали в память. Т.е. в каждый момент программа работает не со всей памятью, а, как правило, с относительно маленьким её фрагментом. Напрашивается решение — загрузить этот фрагмент в «быструю» память, обработать его там, а потом уже записать обратно в «медленную» (или просто удалить из кэша, если данные не изменялись). В общем случае, именно так и работает процессорный кэш: любая считываемая из памяти информация попадает не только в процессор, но и в кэш. И если эта же информация нужна снова, сначала процессор проверяет: нет ли её в кэше? Если есть (а современные кэши совершенны настолько, что это происходит в подавляющем большинстве случаев) — информация берётся оттуда, и обращения к памяти не происходит вовсе. Аналогично с записью: информация, если её объём влезает в кэш, пишется именно туда, и только потом, когда процессор закончил операцию записи, и занялся выполнением других команд, данные, записанные в кэш, параллельно с работой процессорного ядра «потихоньку» выгружаются в ОЗУ.Основной принцип работы процессорного кэша. Второй этап предусматривает два различных варианта развития событий: быстрый ответ, либо передачу запроса дальше, в память. Третий этап в случае быстрого ответа отсутствует.

Говоря по-научному, кэш использует эффекты, которые называются временной и пространственной локальностью информации. Пространственная локальность означает, что несколько обращений к памяти подряд произойдут по адресам, скорее «близким» друг к другу, чем «далёким». Дело в том, что при чтении данных, которых не оказалось в кэше, процессор из памяти получает только их, а кэш дополнительно запрашивает себе ещё несколько десятков байт «вокруг». В результате, если первое обращение закэшировано, то, скорее всего, и для всех последующих также не потребуется обращаться к памяти. А временная локальность означает, что данные, к которым недавно обращались, скорее всего в течение ближайшего времени понадобятся ещё раз или много раз. Поэтому после удачного попадания в кэш (именно так это событие и называется — кэш-попадание, а отсутствие нужных данных в кэше — кэш-промах) информация там остаётся и даже получает больший «рейтинг популярности» (зачем — см. ниже).

Разумеется, объём данных, прочитанных и записанных за всё время работы программы — намного больше объёма кэша. Поэтому некоторые из них приходится время от времени удалять, чтобы в кэш могли поместиться новые, более актуальные. Самый простой из известных механизмов обеспечения данного процесса — отслеживание времени последнего обращения к данным, находящимся в кэше. Так, если нам необходимо поместить новые данные в кэш, а он уже «забит под завязку», контроллер, управляющий кэшем, смотрит: к какому фрагменту кэша не происходило обращения дольше всего (та самая «популярность»). Этот фрагмент и является первым кандидатом на «вылет», а на его место записываются новые данные, с которыми нужно работать сейчас.

Чтобы было понятно, насколько важен кэш, приведём простой пример: скорость обмена данными современного процессора с быстрейшим из своих кэшей (подробней — абзацем ниже) в 5-10 раз превосходит скорость его работы с памятью, а задержки меньше в 50 раз! Фактически, в полную силу современные процессоры способны работать только с кэшем: как только они сталкиваются с необходимостью прочитать данные из памяти — все их хвалёные гигагерцы просто простаивают. Опять-таки, простой пример: выполнение простейшей инструкции процессором происходит за 1 такт, т.е. за секунду он может выполнить такое количество простых инструкций, какова его частота (на самом деле еще больше, но это оставим на потом…). А вот время ожидания данных из памяти может в худшем случае составить более 200 тактов! Что делает процессор, пока ждёт нужные данные? А ничего не делает. Или, в лучшем случае, при наличии технологии гиперпоточности, переключается на другой поток команд, которому без кэша также плохо, как и этому.

Многоуровневое кэширование

Специфика конструирования современных процессорных ядер привела к тому, что систему кэширования в подавляющем большинстве CPU приходится делать многоуровневой. Кэш первого уровня (самый «близкий» к ядру) традиционно разделяется на две (как правило, равные) части: кэш инструкций (L1I) и кэш данных (L1D). Это разделение предусматривается так называемой «гарвардской архитектурой» процессора, которая по состоянию на сегодня является самой популярной теоретической основой для построения современных CPU. В L1I, соответственно, аккумулируются только команды (с ним работает декодер), а в L1D — только данные (они впоследствии, как правило, попадают во внутренние регистры процессора — обо всём этом см. ниже). Иерархически «над» L1 стоит кэш второго уровня — L2. Он, как правило, в 2-8 раз больше по объёму, примерно втрое медленнее, и является уже «смешанным» — там располагаются и команды, и данные. В первых многоядерных процессорах у каждого ядра были свои L1, но общий L2. Сегодня у каждого ядра есть свой L2, зато общим для всех ядер является L3 (кэш третьего уровня), который в 4-32 раза больше, чем L2, и ещё примерно втрое медленнее (но всё ещё быстрее памяти). Алгоритм работы с многоуровневым кэшем в общих чертах не отличается от алгоритма работы с одноуровневым, просто добавляются дополнительные итерации: сначала информация ищется в L1, если там промах — в L2, потом — в L3, и уже потом, если ни на одном уровне кэша она не найдена — идёт обращение к основной памяти (ОЗУ).В новой архитектуре (К10) AMD использует общий для всех ядер кэш третьего уровня. Раньше, в AMD К8, все ядра имели только свои собственные кэши 1 и 2 уровня.

Примерно так же выглядят новая и старая архитектуры Intel.

Декодер

На самом деле, исполнительные блоки всех современных десктопных x86-процессоров вовсе не работают с кодом в стандарте x86. У каждого процессора есть своя, «внутренняя» система команд, имеющая мало общего с теми командами (тем самым «кодом»), которые поступают извне. В общем случае, команды, исполняемые ядром — намного проще, «примитивнее», чем команды стандарта x86. Чтобы процессор с точки зрения программиста или пользователя «внешне выглядел» как x86 CPU, существует декодер: этот блок отвечает за преобразование «внешнего» x86-кода во «внутренние» команды, исполняемые ядром (при этом достаточно часто одна команда x86-кода преобразуется в несколько более простых «внутренних»). Декодер является важной частью современного процессора: от его быстродействия зависит то, насколько постоянным будет поток команд, поступающих на исполняющие блоки. Ведь они не способны работать с кодом x86, поэтому будут ли они что-то делать или простаивать — во многом зависит от эффективности работы декодера.

Регистры процессора

Регистры — по сути, те же ячейки памяти, но «территориально» они расположены прямо в процессорном ядре. Разумеется, скорость работы с регистрами намного больше не только скорости работы с ОЗУ, но и с кэшами любого уровня. Поэтому большинство команд архитектуры x86 предусматривают осуществление действий именно над содержимым регистров, а не над содержимым памяти. Однако общий объём регистров процессора, как правило, очень мал — он не сравним даже с объёмом кэшей первого уровня и составляет всего сотни байт. Поэтому код программы (не на языке высокого уровня, а именно машинный) обычно содержит примерно такую последовательность операций: загрузить в регистры процессора информацию из ОЗУ, произвести некое действие над содержимым этих регистров, поместив результат туда же, в регистры, а потом снова выгрузить результат в основную память. Т.к. работа с памятью куда медленнее, было бы неплохо, чтобы объём данных в регистрах был больше — тогда промежуточные результаты вычислений можно целиком (или почти…) хранить в ядре, не обращаясь даже в кэш, что резко ускорит работу процессора. Однако увеличить размер или число регистров значительно сложнее, чем увеличить кэш и, тем более, нарастить объём памяти (это вообще любой продвинутый пользователь сделает). Тем не менее, примерно раз в 5-10 лет к стандартному на этот момент набору регистров добавляется ещё столько же новых, либо сами регистры удваиваются (а при введении x86-64 с целочисленными регистрами произошло и то, и другое).

Функциональные устройства

Пройдя через все уровни кэша, декодер и некоторые подготовительные модули, команды наконец-то попадают в те блоки, ради которых вся эта катавасия и устраивалась: функциональные (исполняющие) устройства (ФУ). По сути, именно они и являются единственно необходимым элементом процессора. Можно обойтись без кэша — скорость снизится, но программы работать будут. Можно обойтись без декодера — исполняющие устройства станут сложнее, но работать процессор будет. Более того, у процессоров с системой команд концепции RISC (с точки зрения программиста, архитектура x86 к ней не отсносится, но для примера имеет смысл заметить) декодер отсутствует принципиально. А без функциональных устройств обойтись невозможно, ибо именно они исполняют операции над данными. Разных ФУ бывает много, но самые главные из них — арифметико-логические устройства (ALU), блоки вычислений с плавающей точкой (FPU), блоки векторной обработки (SIMD — таково общее название концепции векторных вычислений, означающее «одна команда, много данных») и блоки обмена данных с памятью.  Каждое ФУ может исполнить только те команды, которые предназначены для него. Распределением команд, поступающих с декодера, по различным исполняющим устройствам занимается специальный блок-планировщик.

Арифметико-логические устройства

ALU (если не указано иное, то подразумевается именно целочисленный блок) традиционно отвечают за самые частые операции: простые арифметические действия (сложение, вычитание, сравнение) с целыми числами, логические операции («и», «или», «исключающее или» и «не»), копирование и простые преобразования чисел, а также битовые сдвиги. Блоков ALU в современных процессорах, как правило, 3. Для чего — вы поймёте позже, прочитав раздел «Суперскалярность и внеочередное исполнение команд». Внимательный читатель заметит, что выше не указаны ещё некоторые команды с целыми числами, которые, вроде бы должны быть исполнены в АЛУ. Например — умножение. Однако всё не так просто. Дело в том, что число и разнообразие функциональных устройств зависит от частоты встречи разных команд. Т.к. команды сложения, вычитания и копирования среди целых чисел наиболее «популярны», имеет смысл делать несколько АЛУ, исполняющих именно их, а вот целочисленное умножение, и, тем более, деление встречается куда реже, поэтому целочисленный умножитель почти во всех процессорах один (иногда — универсальный, в т.ч. и для вещественных чисел), а делителя нет вообще (эта операция делается в умножителе с использованием специальных таблиц констант для ускорения деления).

Блоки вычислений с плавающей запятой* и векторной обработки

FPU занимается выполнением команд, работающих с числами с плавающей запятой, кроме того, традиционно на него «вешают всех собак» в виде дополнительных наборов команд для работы с векторными данными (MMX и SSE с разными цифрами) — независимо от того, работают они с числами с плавающей запятой, или с целыми. Этих ФУ также 3-4, но тут расклад сил несколько иной — как правило, каждый блок умеет делать копирование данных, но только 2 или 3 исполняют простые команды (как у целочисленного АЛУ — их иногда называют SIMD ALU или SSE ALU), только один — умножение и деление, и ещё один — всё остальное (перетасовки элементов вектора, сложные преобразования форматов данных и пр.).* — по традиции русской математической школы, мы называем FPU «блоком вычислений с плавающей запятой», хотя буквально его название (Floating Point Unit) переводится как «…с плавающей точкой» — согласно американскому стандарту написания таких чисел.

Блоки обмена данных с памятью

Тут есть 3 вида модулей — 2-3 так называемых AGU или устройства генерации адреса, подготавливающие адрес операции обмена, и по одному блоку загрузки и сохранения (выгрузки), соединённых с кэшем данных первого уровня. Тут всё просто — готовим адрес, а затем либо пишем данные из регистра в кэш, либо наоборот — читаем из кэша в регистр.

Энергосбережение

Помимо вычислительных «наворотов», у современных CPU есть ещё и различные технологии для уменьшения потребления энергии. Причём это касается процессоров не только для мобильных устройств, но и для настольных ПК, и даже серверов. Дело в том, что уменьшение потребления электроэнергии также приводит к уменьшению тепловыделения, которое за последние годы сильно выросло — ещё 10 лет назад было трудно себе представить, что средний процессор будет потреблять электричества и выделять тепла под 100 ватт, а то и больше. Системы охлаждения всё чаще становятся слишком дорогими и шумными, притом, что это один из самых ненадёжных узлов компьютера, требующий регулярного ухода. А если охлаждение не справится — процессор (или другой чувствительный компонент) перегреется. О перегреве и защите от него уже сказано выше, но с некоторых пор не помогает и это, нужны дополнительные меры. Такими мерами стали технологии регулировки потребления энергии в зависимости от требуемой загрузки процессора. Для Intel это называется SpeedStep, для AMD — Cool'n'Quiet и PowerNow! (плюс номер версии).

Анализируя загрузку различных блоков и шин, контроллер энергосбережения может снизить их частоту работы (для компонентов, которые могут работать несинхронно) или приостановить тактирование полностью, а также указать материнской плате понизить питающее напряжение (тоже — не всего процессора, а отдельного ядра или блока, хотя и не каждого). Регулировка напряжений особенно эффективна, т.к. от него потребляемая и выделяемая мощность зависит больше. Однако и частота (за редкими исключениями) и напряжение не могут упасть до нуля: реально частота падает в 2-3 раза относительно максимума, а напряжение — процентов на 20-30. Т.е. даже при полном простое (чего в многозадачных ОС не бывает никогда) процессор всё равно будет потреблять несколько ватт, а особо энергоэффективные CPU для ноутбуков — доли ватта. Тем не менее, это на порядок меньше, чем в случае отсутствия энергосберегающих технологий. Разумеется, во всех современных материнских платах и ОС энергосбережение процессора поддерживается и включено по умолчанию. Что касается эффективности, то считается, что технологии AMD чуть отстают от Intel, но реальная разница скорее всего окажется околонулевой, т.к. процессор — не единственная часть компьютера. В частности, современная видеокарта «налегает на ватты» посильнее многих серверных CPU, даже если она в корпусе одна; аналогично и для ноутбуков.

Также заметим, что переход на новый технологический процесс при изготовлении микросхем (грубо говоря, он измеряется в нанометрах и определяет минимальный размер элемента на чипе) помимо возможности размещения большего числа транзисторов и ускорения их срабатывания также приводит и к уменьшённому энергопотреблению. Так что, например, одинаковые по устройству и частоте процессоры, изготовленные по 65-нанометровой и 45-нанометровой технологии, будут потреблять разное количество энергии — у второго будет чуть меньшее питающее напряжение и потребляемый ток. Процессор: ещё детальней

Особенности кэшей

Частота работы кэша и его шина

Во всех современных x86 CPU кэши L1 и L2 работают на той же частоте, что и процессорное ядро, но это вовсе не всегда было так (данный вопрос уже поднимался выше). Однако скорость работы с кэшем зависит не только от частоты, но и от ширины шины, с помощью которой он соединён с ядром. Как вы помните, скорость передачи данных является произведением частоты работы шины (количества тактов в секунду) на количество байт, которые передаются по шине за такт. Это количество можно увеличивать за счёт введения технологии DDR (Double Data Rate) и/или за счёт увеличения ширины шины. В случае с кэшем более популярен второй вариант — не в последнюю очередь из-за «пикантных особенностей» DDR, описанных выше. Более того, можно поставить сразу две параллельные шины, передающие данные в разные стороны — т.е. преобразовав шину в двунаправленную (полнодуплексную) удвоенной ширины. Споры о том, какой из подходов лучше (двунаправленная шина, но более узкая в каждом направлении, или однонаправленная широкая) — продолжаются до сих пор, как и множество других споров относительно технических решений, применяемых двумя основными конкурентами на рынке x86 CPU. Ранее под минимально разумной шириной шины кэша принималась разрядность внешней шины самого процессора, т.е. 64 бита. Теперь же большинство новых моделей имеют встроенный многоканальный контроллер памяти, общая эффективная ширина которого — 128 и более бит. Однако внутри процессора ширина шин между ядром и кэшем, а также самими кэшами может быть ещё шире: в большинстве случаев — 256 бит.

Эксклюзивный и не эксклюзивный кэш

Концепции эксклюзивного и не эксклюзивного кэширования очень просты: в случае не эксклюзивного кэша, информация на всех уровнях кэширования может дублироваться. Таким образом, L2 может содержать в себе данные, которые уже находятся в L1I и L1D, а L3 может содержать в себе полную копию всего содержимого L2 (и, соответственно, L1I и L1D). Эксклюзивный кэш, в отличие от не эксклюзивного, предусматривает чёткое разграничение: если информация содержится на каком-то уровне кэша — то на всех остальных она отсутствует. Плюс эксклюзивного кэша очевиден: общий размер кэшируемой информации равен суммарному объёму кэшей всех уровней — а у не эксклюзивного кэша размер кэшируемой информации (в худшем случае) равен объёму самого большого (по размеру и по номеру) уровня кэша. Минус эксклюзивного кэша менее очевиден, но он есть: необходим специальный механизм, который следит за собственно «эксклюзивностью» (например, «удаление» информации из L1 фактически инициирует процесс её копирования в L2).

Не эксклюзивный кэш традиционно использует компания Intel, эксклюзивный (с момента появления процессоров Athlon на ядре Thunderbird) — компания AMD. В целом, мы наблюдаем здесь классическое противостояние между объёмом и скоростью: за счёт эксклюзивности, при одинаковых объёмах L1/L2 у AMD общий размер кэшируемой информации получается больше — но за счёт неё же он работает медленней (задержки, вызванные наличием механизма обеспечения эксклюзивности). Следует заметить, что недостатки не эксклюзивного кэша Intel компенсирует просто, но весомо: наращивая его объёмы. Для топовых процессоров данной компании стал нормой L3-кэш объёмом 8 МБ — но AMD с её 512 КБ L2 на каждое из 2-6 ядер и максимум 6 МБ общего L3 также получает 7-9 МБ за счёт эксклюзивности.

Кроме того, увеличивать общий объём кэшируемой информации за счёт введения эксклюзивной архитектуры кэша имеет смысл только в том случае, когда выигрыш в объёме получается достаточно большим. Для AMD это актуально т.к. у её сегодняшних CPU суммарный объём L1D+L1I равен 128 КБ, а L2 — 512 КБ. Процессорам Intel, у которых оба числа вдвое меньше, введение эксклюзивной архитектуры дало бы намного меньше пользы.

А ещё есть распространённое заблуждение, что архитектура кэша у CPU компании Intel «инклюзивная». На самом деле — нет. Именно НЕ эксклюзивная. Инклюзивная архитектура предусматривает, что на «нижнем» уровне кэша не может находиться ничего, чего нет на более «верхнем». Не эксклюзивная архитектура всего лишь допускает дублирование данных на разных уровнях.

Суперскалярность и внеочередное исполнение команд

Основная черта всех современных процессоров состоит в том, что они способны запускать на исполнение не только ту команду, которую (согласно коду программы) следует исполнить в данный момент времени, но и другие «вблизи» неё. Приведём простой (канонический) пример. Пусть нам следует исполнить следующую последовательность команд:

  1. A = B + C
  2. Z = X + Y
  3. K = A + Z

Легко заметить, что команды (1) и (2) совершенно независимы друг от друга — они не пересекаются ни по исходным данным (переменные B и C в первом случае, X и Y во втором), ни по месту размещения результата (переменная A в первом случае и Z во втором). Стало быть, если на данный момент у нас есть свободные исполняющие блоки в количестве более одного, данные команды можно распределить по ним, и выполнить одновременно, а не последовательно*. Таким образом, если принять время исполнения каждой команды равным N тактов процессора, то в классическом случае исполнение всей последовательности заняло бы N*3 тактов, а в случае с параллельным исполнением — всего N*2 тактов (так как команду (3) нельзя выполнить, не дождавшись результата исполнения двух предыдущих).* — разумеется, степень параллелизма не бесконечна: команды могут быть выполнены параллельно только в том случае, когда на данный момент времени есть в наличии соответствующее количество свободных от работы блоков (ФУ), причём именно таких, которые «понимают» рассматриваемые команды. Например, ALU физически неспособно исполнить инструкцию для FPU. Обратное также верно.

На самом деле, всё ещё сложнее. Так, если у нас имеется следующая последовательность:

  1. A = B + C
  2. K = A + M
  3. Z = X + Y

То очередь исполнения команд процессором будет изменена! Т.к. команды (1) и (3) независимы друг от друга ни по исходным данным, ни по месту размещения результата, они могут быть выполнены параллельно — и будут выполнены параллельно. А вот команда (2) будет выполнена после них (хронологически третьей) — поскольку для того, чтобы результат вычислений был корректен, необходимо, чтобы перед этим была выполнена команда (1). Именно поэтому обсуждаемый в данном разделе механизм и называется «внеочередным исполнением команд» (Out-of-Order Execution или «OoO»): в тех случаях, когда очерёдность выполнения никак не может сказаться на результате, команды отправляются на исполнение не в указанной в программе последовательности, а в той, которая позволяет достичь максимального быстродействия.

Теперь вам должно стать окончательно понятно, зачем современным CPU такое количество однотипных исполняющих блоков: они обеспечивают возможность параллельного выполнения нескольких одинаковых или близких по типу команд, которые в случае с «классическим» подходом к проектированию процессора пришлось бы выполнять так, как они содержатся в исходном коде, одну за другой.«Исполнительная» часть ядра AMD Deneb в качестве наглядной иллюстрации возможностей параллельного выполнения команд

Процессоры, оснащённые механизмом параллельного исполнения нескольких подряд идущих команд, принято называть «суперскалярными». Однако не все суперскалярные процессоры поддерживают внеочередное исполнение. Так, в первом примере нам достаточно «простой суперскалярности» (выполнения двух последовательных команд одновременно) — а вот во втором примере без перестановки команд местами уже не обойтись, если мы хотим получить максимальное быстродействие. Все современные x86 CPU обладают обоими качествами: являются суперскалярными и поддерживают внеочередное исполнение команд — кроме процессора Intel Atom, который сделан с простой внутренней структурой, чтобы быть дешёвым и энергоэффективным одновременно. В то же время, были в истории x86 и «простые суперскаляры», OoO не поддерживающие. Например, классическим десктопным x86-суперскаляром без OoO был Intel Pentium (с или без MMX). Тот же Atom можно с натяжкой считать аналогом «Пентиума», хотя сильно продвинутым и по архитектуре, и по скорости.

Справедливости ради стоит заметить, что никаких заслуг в разработке концепций суперскалярности и OoO нет ни у Intel, ни у AMD, ни у какого-либо иного (в том числе из ныне почивших) производителя x86 CPU. Первый суперскалярный компьютер, поддерживающий OoO, был разработан Сеймуром Креем (Seymour Cray) ещё в 60-х годах XX века. Для сравнения: Intel свой первый суперскалярный процессор архитектуры x86 (Pentium) выпустила в 1993 г., первый суперскаляр с OoO (Pentium Pro) — в 1995 г.; первый суперскаляр с OoO от AMD (K5) увидел свет в 1996 г.. Комментарии, как говорится, излишни…

Предварительное (опережающее) декодирование и кэширование

Предсказание ветвлений

В любой более-менее сложной программе присутствуют команды условного перехода: «Если некое условие истинно — перейти к исполнению одного участка кода, если нет — другого». С точки зрения скорости выполнения кода программы современным процессором с большим числом подоготовительных стадий и собственно исполнением (так называемый исполнительный конвейер), любая команда условного перехода — воистину бич божий. Ведь до тех пор, пока не станет известно, какой участок кода после условного перехода окажется «актуальным» — его невозможно начать декодировать и исполнять. Для того чтобы как-то примирить концепцию «длинных» конвейеров с командами условного перехода, предназначается специальный блок: блок предсказания ветвлений. Занимается он, по сути, «пророчествами»: пытается предсказать, на какой участок кода укажет команда условного перехода, ещё до того, как она будет исполнена, и сработает ли переход вообще. В соответствии с указаниями «штатного внутриядерного пророка», процессором производятся вполне реальные действия: «напророченный» участок кода загружается в кэш (если он там отсутствует), и начинается декодирование и выполнение его команд. Причём среди выполняемых команд также могут содержаться инструкции условного перехода, и их результаты тоже предсказываются, что порождает целую цепочку из пока не проверенных предсказаний! Разумеется, если блок предсказания ветвлений ошибся, вся проделанная в соответствии с его предсказаниями работа просто аннулируется.

Алгоритмы, по которым работает блок предсказания ветвлений, вовсе не являются шедеврами искусственного интеллекта. Когда процессор впервые встречает условный переход, он пытается предсказать его поведение «по одёжке» — какого типа команда, куда происходит переход (вперёд по ходу исполнения программы или назад — это если он вообще произойдёт) и пр.. Точность такого предсказателя (он называется статическим) невелика. Самое интересное происходит, когда встречается уже знакомый переход. Чтобы его узнать, у предсказателя есть специальная таблица историй переходов, хранящая описание поведения нескольких сотен или тысяч последних обнаруженных в программе команд ветвления вместе с их адресами. Далее уже динамический предсказатель делает заключение о вероятном поведении команды не «по одёжке», а «по уму» — основываясь на детальной накопленной статистике поведения и этой команды перехода, и предыдущих её «коллег», исполненных до неё. Для поддержки этой статистики каждый раз, когда команда перехода доходит до исполнения, её результат попадает в предсказатель, чтобы тот скорректировал свою таблицу — перешли или нет, угадали или нет.

Несмотря на достаточно высокую эффективность алгоритмов, механизмы предсказания ветвлений в современных CPU всё равно постоянно совершенствуются и усложняются — но тут уже речь идёт о борьбе за единицы процентов: например, за то, чтобы повысить эффективность работы блока предсказания ветвлений с 95 процентов до 97, или даже с 97 до 99…

Предвыборка данных

Блок предвыборки данных (Prefetch) очень похож по принципу своего действия на блок предсказания ветвлений — но в данном случае речь идёт не о коде, а о данных. Общий принцип действия такой же: предзагрузчик (префетчер) анализирует запросы к данным, решает, что к некоему участку памяти, ещё не загруженному в кэш или ядро, скоро будет осуществлён доступ — и заранее даёт команду на загрузку данного участка ещё до того, как он понадобится программе. «Умно» (результативно) работающий блок предвыборки позволяет существенно сократить время доступа к нужным данным, и, соответственно, повысить скорость исполнения программы. Он хорошо компенсирует высокую латентность подсистемы памяти, подгружая нужные данные поближе к ядру или сразу в него, и тем самым, нивелируя задержки при доступе к ним, если бы они находились не в кэше, а в основном ОЗУ.

Разумеется, в случае предвыборки неизбежны негативные последствия: загружая ненужные (как позже окажется) данные в кэш, Prefetch вытесняет из него другие (быть может, как раз нужные). Кроме того, за счёт «предвосхищения» операции считывания, создаётся дополнительная нагрузка на контроллер памяти (причём в случае ошибки — совершенно бесполезная).

Алгоритмы Prefetch, как и алгоритмы блока предсказания ветвлений, тоже не блещут интеллектуальностью: как правило, данный блок стремится отследить, не считывается ли информация из памяти с определённым «шагом» (по адресам), и на основании этого анализа пытается предсказать, с какого адреса будут считываться данные далее. Как и в случае с блоком предсказания ветвлений, простота алгоритма вовсе не означает низкую эффективность: в среднем, блок предвыборки чаще «попадает», чем ошибается — это, как и в предыдущем случае, прежде всего связано с тем, что «массированное» чтение данных из памяти, как правило, происходит при исполнении различных циклов.Приложение: генеалогия x86-процессоров от начала и до наших времён

Также, для справки, мы решили включить в данный материал своего рода «генеалогическое древо» всех десктопных x86-процессоров, т.к. оно позволяет проследить некоторые тенденции их развития, а заодно понять, насколько «взаимопроникающим» был процесс их разработки, особенно в самом начале. :)

«Доисторическая эпоха» — от Intel 8086 до Intel Pentium

«Новейшая история» — от Intel Pentium до Intel Core i7 и AMD Phenom II

Заключение

Я — тот кролик, который не может начать жевать траву до тех пор, пока не поймёт во всех деталях, как происходит процесс фотосинтеза!

(изложение личной позиции одним из близких знакомых автора)

Вполне возможно, чувства, которые у вас возникли после прочтения данной статьи, можно описать примерно так: «Вместо того, чтобы на пальцах объяснить, какой процессор лучше — взяли и загрузили мне мозги кучей специфической информации, в которой ещё разбираться и разбираться, и конца-края не видно!» Вполне нормальная реакция, мы вас хорошо понимаем. Скажем даже больше (и пусть с головы упадёт корона!): если вы думаете, что мы сами можем ответить на этот простецкий вопрос («какой процессор лучше?») — это не так. Не можем*. Для одних задач лучше один, для других — другой, а тут ещё цена разная, доступность, симпатии конкретного пользователя к определённым маркам… Не имеет задача однозначного решения. Если бы имела — наверняка кто-то бы его нашёл, и стал бы самым знаменитым обозревателем за всю историю независимых тестовых лабораторий.* — примечание одного из авторов: «Лучший процессор — мой процессор!» :)

Хотелось бы подчеркнуть ещё раз: даже полностью усвоив и осмыслив всю информацию, изложенную в данном материале — вы по-прежнему не сможете предсказать, какой из двух процессоров будет быстрее в ваших задачах, глядя только на их характеристики. Во-первых — потому, что далеко не все характеристики процессоров здесь рассмотрены. Во-вторых — потому, что есть и такие параметры CPU, которые в числовом виде могут быть представлены только с очень большой «натяжкой». Так для кого же (и для чего) всё это написано? В основном — для тех самых «кроликов», которые непременно желают знать, что происходит внутри тех устройств, которыми они пользуются ежедневно. Зачем? Может, они просто лучше себя чувствуют, когда знают, что вокруг них происходит? :)P.S. Захотелось ещё подробнее? Вам поможет «Обзор микроархитектур современных десктопных процессоров» от Олега Бессонова. Эта серия статей хоть и вышла в 2006 году, но в части теоретических сведений и углублённого описания принципов работы x86 CPU, не устарела до сих пор.

www.ixbt.com

Архитектура микропроцессоров: основные виды, развитие, достоинства и недостатки

Архитектура микропроцессоров.

Эта глава посвящена архитектурным особенностям микропроцессоров. В ней приведены общие сведения о микропроцессорах, рассматриваются принципы структурно – функциональной организации) типы данных, регистровая память, спо­собы адресации и система команд микропроцессоров. Излагаемый материал ил­люстрируется на простейших 8– и 16–разрядных процессорах.

Основные понятия

Микропроцессор — это программно–управляемое устройство в виде интегральной микросхемы (БИС или СБИС), предназначенное для обработки цифровой информации. Поскольку все современные микро­процессоры имеют интегральное исполнение, синонимом микропроцессора стал термин процессор.

Микроконтроллер— это специализированный процессор, предназначен­ный для реализации функций управления (control— управление).

{xtypo_quote}Цифровой сигнальный процессор(Digital Signal Processor — DSP) — это специа­лизированный процессор, предназначенный для обработки цифровых сигналов. {/xtypo_quote}Микропроцессорная система представляет собой функционально законченное изделие, состоящее из нескольких цифровых устройств, включая процессор. Это понятие объединяет широкий набор законченных изделий, начиная с микроконтроллеров, выполненных на интегральных микросхемах, и кон­чая компьютерными системами, представляющими собой набор отдельных конст­руктивно оформленных устройств (системный блок, клавиатура, монитор и др.). В дальнейшем рассматриваются простейшие (однокристальные) микропроцес­сорные системы, содержащие помимо процессора основную память и устройства ввода/вывода. Такие микропроцессорные системы можно отнести к классу микро­процессоров.

Под организацией процессора понимают совокупность его узлов (устройств, блоков, модулей), связи между узлами и их функциональные характе­ристики. Организация определяет аппаратную организацию процессора, т. е. состав и взаимодействие его аппаратных средств. Выделяют два уровня организации:

● физическую организацию в виде принципиальной схемы;

● логическую организацию в виде структурно–функциональной схемы.

В дальнейшем рассматривается организация микропроцессоров на логиче­ском уровне, или структурно–функциональная организация процессоров.

Под архитектурой процессора будем понимать совокупность его программно–аппаратных средств, обеспечивающих обработку цифровой инфор­мации (выполнение программы), т. е. совокупность всех средств, доступных про­грамме (или пользователю). Это более общее понятие по сравнению с понятием организация включает в себя набор программно–доступных регистров и операци­онных устройств, систему основных команд и способов адресации, объем и орга­низацию адресуемой памяти, виды и способы обработки данных (обмен, преры­вания, примой доступ к памяти и др.).

{xtypo_quote}Например, современные 32–разрядные процессоры х86 с архитектурой IA–32 (Intel Architecture — 2 bit ) имеют стандарт­ный набор регистров, общую систему основных команд, одинаковые способы организации и адресации памяти, защиты памяти и обслуживания прерываний. Отметим, что понятие архитектуры в большей степени характеризует свойства системы, чем устройства. {/xtypo_quote}

Основные виды архитектур

По форматам используемых команд (инструкций) можно выделить:

● CISC–архитектуру, которая относится к процессорам (компьютерам) с полным набором команд (Complete Instruction Set Computer— CISC). Она реализова­на во многих типах микропроцессоров (например Pentium), выполняющих большой набор разноформатных команд с использованием многочисленных способов адресации.

Система команд процессоров с CISC–архитектурой может содержать не­сколько сотен команд разного формата (от 1 до 15 байт), или степени слож­ности, и использовать более 10 различных способов адресации, что позволя­ет программисту реализовать наиболее эффективные алгоритмы решения различных задач.

Развитие традиционных CISC

Архитектур микропроцессоров по пути рас­ширения функциональных возможностей и снижения затрат на программиро­вание привело к увеличению числа команд в наборе и числа микрокоманд в команде. Следствием этого явилось усложнение интегральных схем и сни­жение быстродействия выполнения программ. Один из возможных путей уст­ранения указанных недостатков состоит в использовании сокращенного набо­ра команд, организация которого подчинена увеличению скоростей их выпол­нения;

● RISC–архитектуру, которая относится к процессорам (компьютерам) с сокра­щенным набором команд (Reduced instruction Set Computer — RISC). Появле­ние RISC –архитектуры продиктовано тем, что многие CISC –команды и спо­собы адресации используются достаточно редко. Основная особенность RISC–архитектуры проявляется в том, что система команд состоит из неболь­шого количества часто используемых команд одинакового формата, которые могут быть выполнены за один командный цикл (такт) центрального процес­сора. Более сложные, редко используемые команды реализуются на про­граммном уровне. Однако за счет значительного повышения скорости испол­нения команд средняя производительность RISC–процессоров может оказать­ся выше, чем у процессоров с CISC–архитектурой.

{xtypo_quote}Большинство команд RISC –процессоров связано с операцией регистр–регистр. Для обращения к памяти оставлены наиболее простые с точки зре­ния временных затрат операции загрузки в регистры и записи в память. {/xtypo_quote}

Современные RISC –процессоры реализуют около 100 команд, имеющих фиксированный формат длиной 4 байта, и используют небольшое число наи­более простых способов адресации (регистровую, индексную и некоторые другие).

Для сокращения количества обращений к внешней оперативной памяти RISC –процессоры содержат десятки–сотни регистров общего назначения (РОН), тогда как в CISC–процессорах всего 8–16 регистров. Обращение к внешней памяти в RISC–процессорах используется только в операциях за­грузки данных в РОН или пересылки результатов из РОН в память. За счет со­кращения аппаратных средств, необходимых для декодирования и выполне­ния сложных команд, достигается существенное упрощение интегральных схем RISC–процессоров и снижение их стоимости. Кроме того, значительно повышается производительность. Благодаря указанным достоинствам во многих современных CI SC –процессорах (последние модели Pentium и К7) ис­пользуется RISC–ядро. При этом сложные CI SC–команды предварительно преобразуются в последовательность простых RISC–операций и быстро вы­полняются RISC–ядром;

● VLIW–архитектуру, которая относится к микропроцессорам с использованием очень длинных команд (Very Large Instruction Word— VLIW). Отдельные поля команды содержат коды, обеспечивающие выполнение различных операций. Одна VLIW –команда может выполнить сразу несколько операций одновремен­но в различных узлах микропроцессора. Формирование «длинных» VLIW – koманд производит соответствующий компилятор при трансляции программ, написанных на языке высокого уровня.

{xtypo_quote}VLIW –архитектура реализована в неко­торых типах современных микропроцессоров и является весьма перспектив­ной для создания нового поколения сверхвысокопроизводительных процес­соров. {/xtypo_quote}

По способу организации выборки команд и данных различа­ют два вида архитектур:

● принстонская архитектура, или архитектура фон–Неймана, особенностью которой является (рис. 2.1.1) использование:

• общей основной (оперативной) памяти для хранения программ и данных, что позволяет оперативно и эффективно перераспределять ее объем в за­висимости от решаемых задач в каждом конкретном случае применении микропроцессора;

• общей шины, по которой в процессор поступают команды и данные, а в опе­ративную память записываются результаты, что значительно упрощает отладку, тестирование и текущий контроль функционирования системы, повышает ее надежность. Чтобы отделить команду от данных, первым из памяти всегда поступает код выполняемой операции, а затем следуют данные. По умолчанию код операции загружается в регистр команд, а дан­ные — в блок регистров (рис. 2.1.1). Из–за ограниченного числа внешних выводов общая шина обычно работает в режиме временного мультиплек­сирования, т. е. противоположные направления обмена данными между микропроцессором, памятью или другими внешними устройствами разде­лены во времени.

Недостаток принстонской архитектуры

Использование общей шины для пе­редачи команд и данных ограничивает производительность цифровой системы;

● гарвардская архитектура (создатель Говард Айкен), особенностью которой является физическое разделение памяти команд (программ) и памяти данных (рис. 2.1.2). Это обстоятельство вызвано постоянно возрастающими требова­ниями к производительности микропроцессорных систем. Память команд и память данных соединяются с процессором отдельными шинами. Благодаря разделению потоков команд и данных, а также совмещению операций их вы­борки (и записи результатов обработки) обеспечивается более высокая про­изводительность, чем при использовании принстонской архитектуры.

Недостатки гарвардской архитектуры

Усложнение конструкции из–за ис­пользования отдельных шин для команд и данных; фиксированный объем па­мяти для команд и данных; увеличение общего объема памяти из–за невоз­можности ее оптимального перераспределения между командами и данными. Гарвардская архитектура получила широкое применение в микроконтрол­лерах — специализированных микропроцессорах для управления различными объектами, а также во внутренней структуре современных высокопроизводи­тельных микропроцессоров в кэш–памяти с раздельным хранением команд и данных.

В то же время во внешней структуре большинства микропроцессор­ных систем реализуются принципы принстонской архитектуры.

Отметим, что архитектура микропроцессора тесно связана с его структурой. Реализация тех или иных архитектурных особенностей требует введении в струк­туру микропроцессора соответствующих устройств и обеспечения механизмов их совместного функционирования.

pue8.ru

Современные десктопные процессоры архитектуры x86:

общие принципы работы (x86 CPU FAQ 1.0)Disclaimer

Наверное, наиболее точно причину появления данного материала можно сформулировать так: «даже не столько нужно, чтобы он был — сколько странно, что его до сих пор не было». И действительно: в комментариях к результатам тестов, мы постоянно оперируем такими понятиями как «ёмкость кэша», «скорость процессорной шины», «поддержка расширенных наборов инструкций», но единой статьи, в которой были бы собраны разъяснения всех этих терминов — на сайте нет. Такое упущение, разумеется, следовало устранить. Данная статья с подзаголовком «x86 CPU FAQ» и является попыткой сделать это. Разумеется, некоторые её разделы могут быть отнесены не только к процессорам архитектуры x86, и не только с десктопным (предназначенным для установки в ПК) их вариантам, однако вот уж на такой глобализм мы совершенно точно не замахиваемся. Поэтому просьба помнить, что в рамках данного материала, если в явной форме не указано иное, слово «процессор» обозначает «процессор архитектуры x86, предназначенный для установки в десктопы». Возможно, в процессе дальнейшего совершенствования и расширения, появятся в статье разделы, посвящённые серверным CPU или даже процессорам других архитектур, но это уже дело будущего… ОглавлениеВведение

Код и данные: основной принцип работы процессора

Итак, если не пытаться изложить здесь «кратенько» курс информатики для средней школы, то единственное что хотелось бы напомнить — это то, что процессор (за редкими исключениями) исполняет не программы, написанные на каком-нибудь языке программирования (один из которых, вы, возможно, даже знаете), а некий «машинный код». То есть командами для него являются последовательности байтов, находящихся в памяти компьютера. Иногда команда может быть равна одному байту, иногда она занимает несколько байт. Там же, в основной памяти (ОЗУ, RAM) находятся и данные. Они могут находиться в отдельной области, а могут и быть «перемешаны» с кодом. Различие между кодом и данными состоит в том, что данные — это то, над чем процессор производит какие-то операции. А код — это команды, которые ему сообщают, какую именно операцию он должен произвести. Для упрощения, мы можем представить себе программу и ее данные в виде последовательности байтов некой конечной длины, располагающуюся непрерывно (не будем усложнять) в общем массиве памяти. Например, у нас есть массив памяти длиной в 1’000’000 байт, а наша программа (вместе с данными) — это байты с номерами от 1000 до 20’000. Прочие байты — это другие программы или их данные, или просто свободная память, не занятая ничем полезным.

Таким образом, «машинный код» — это команды процессора, располагающиеся в памяти. Там же располагаются данные. Для того чтобы исполнить команду, процессор должен прочитать ее из памяти. Для того чтобы произвести операцию над данными, процессор должен прочитать их из памяти, и, возможно, после произведения над ними определенного действия, записать их обратно в память в обновленном (измененном) виде. Команды и данные идентифицируются их адресом, который, по сути, представляет собой порядковый номер ячейки памяти.Общие принципы взаимодействияпроцессора и ОЗУ

Возможно, кого-то удивит, что достаточно большой раздел в FAQ, посвященном x86 CPU, выделен под объяснение особенностей функционирования памяти в современных системах, основанных на данном типе процессоров. Однако факты — упрямая вещь: сами x86-процессоры ныне содержат так много блоков, отвечающих именно за оптимизацию их работы с ОЗУ, что игнорировать эту тесную связь было бы совершенно нелепо. Можно сказать даже так: уж, коль решения, связанные с оптимизацией работы с памятью, стали неотъемлемой частью самих процессоров — то и саму память можно рассматривать в качестве некоего «придатка», функционирование которого оказывает непосредственное влияние на скорость работы CPU. Без понимания особенностей взаимодействия процессора с памятью, невозможно понять, за счёт чего тот или иной процессор (та или иная система) исполняет программы медленнее или быстрее.

Контроллер памяти

Итак, ранее выше мы уже говорили о том, что как команды, так и данные, попадают в процессор из оперативной памяти. На самом деле всё немного сложнее. В большинстве современных x86-систем (то есть компьютеров на базе x86-процессоров), процессор как устройство к памяти обращаться вообще не может, так как не имеет в своем составе соответствующих узлов. Поэтому он обращается к «промежуточному» специализированному устройству, называемому контроллером памяти, а уже тот, в свою очередь — к микросхемам ОЗУ, размещенным на модулях памяти. Модули вы наверняка видели — это такие длинные узкие текстолитовые «планочки» (фактически — небольшие платы) с некоторым количеством микросхем на них, вставляемые в специальные разъемы на системной плате. Роль контроллера ОЗУ, таким образом, проста: он служит своего рода «мостом»* между памятью и использующими ее устройствами (кстати, к ним относится не только процессор, но об этом — чуть позже). Как правило, контроллер памяти входит в состав чипсета — набора микросхем, являющегося основой системной платы. От быстродействия контроллера во многом зависит скорость обмена данными между процессором и памятью, это один из важнейших компонентов, влияющих на общую производительность компьютера.

* — кстати, контроллер памяти физически находится в микросхеме чипсета, традиционно называемой «северным мостом».

Процессорная шина

Любой процессор обязательно оснащён процессорной шиной, которую в среде x86 CPU принято называть FSB (Front Side Bus). Эта шина служит каналом связи между процессором и всеми остальными устройствами в компьютере: памятью, видеокартой, жёстким диском, и так далее. Впрочем, как мы уже знаем из предыдущего раздела, между собственно памятью и процессором находится контроллер памяти. Соответственно: процессор посредством FSB связывается с контроллером памяти, а уже тот, в свою очередь, по специальной шине (назовём её, не мудрствуя лукаво, «шиной памяти») — с модулями ОЗУ на плате. Однако, повторимся: поскольку «внешняя» шина у классического x86 CPU всего одна, она используется не только для работы с памятью, но и для общения процессора со всеми остальными устройствами.

Различия между традиционной для x86 CPU архитектурой и K8/AMD64

Революционность подхода компании AMD состоит в том, что её процессоры с архитектурой AMD64 (и микроархитектурой, которую условно принято называть «K8») оснащены множеством «внешних» шин. При этом одна или несколько шин HyperTransport служат для связи со всеми устройствами кроме памяти, а отдельная группа из одной или двух (в случае двухканального контроллера) шин — исключительно для работы процессора с памятью. Преимущество интеграции контроллера памяти прямо в процессор, очевидно: «путь от ядра до памяти» становится заметно «короче», что позволяет работать с ОЗУ быстрее. Правда, имеются у данного подхода и недостатки. Так, например, если ранее устройства типа жёсткого диска или видеокарты могли работать с памятью через выделенный, независимый контроллер — то в случае с архитектурой AMD64 они вынуждены работать с ОЗУ через контроллер, размещённый на процессоре. Так как CPU в данной архитектуре является единственным устройством, имеющим прямой доступ к памяти. Де-факто, в противостоянии «внешний контроллер vs. интегрированный», сложился паритет: с одной стороны, на данный момент AMD является единственным производителем десктопных x86-процессоров с интегрированным контроллером памяти, с другой — компания вроде бы вполне довольна этим решением, и не собирается от него отказываться. С третьей — Intel тоже не собирается отказываться от внешнего контроллера, и вполне довольна «классической схемой», проверенной годами.

Оперативная память

Разрядность шины памяти, N-канальные контроллеры памяти

По состоянию на сегодняшний день, вся память, используемая в современных десктопных x86-системах имеет шину шириной 64 бита. Это означает, что за один такт по данной шине одновременно может быть передано количество информации, кратное 8 байтам (8 байт для SDR-шин, 16 байт для DDR-шин). Особняком стоит только память типа RDRAM, применявшаяся в системах на базе процессоров Intel Pentium 4 на заре становления архитектуры NetBurst, но сейчас это направление признано тупиковым для x86-ПК (к слову — руку к этому приложила всё та же компания Intel, которая в своё время активно пропагандировала данный тип памяти). Некоторую неразбериху вносят лишь двухканальные контроллеры, обеспечивающие одновременную работу с двумя отдельными друг от друга 64-битными шинами, благодаря чему некоторые производители заявляют о некой «128-битности». Это, разумеется, чистой воды профанация. Арифметика на уровне 1-го класса в данном случае, увы, не работает: 2x64 вовсе не равно 128. Почему? Да хотя бы потому, что даже самые современные x86 CPU (см. ниже раздел FAQ «64-битные расширения классической x86 (IA32) архитектуры») не могут работать со 128-битной шиной и 128-битной адресацией. Грубо говоря: две независимые параллельно идущие дороги, шириной 2 метра каждая — могут обеспечить одновременный проезд двух автомобилей, шириной 2 метра — но никоим образом не одного, шириной 4 метра. Точно так же, N-канальный контроллер памяти может увеличить скорость работы с данными в N раз (и то больше теоретически, чем практически) — но никак не способен увеличить разрядность этих данных. Ширина шины памяти во всех современных контроллерах, применяемых в x86-системах, равна 64 битам — независимо от того, находится этот контроллер в чипсете, или в самом процессоре. Некоторые контроллеры оснащены двумя независимыми 64-битными каналами, но на разрядность шины памяти это никак не влияет — только на скорость считывания и записи информации.

Скорость чтения и записи

Скорость чтения и записи информации в память теоретически ограничивается исключительно пропускной способностью самой памяти. Так, например, двухканальный контроллер памяти стандарта DDR400 теоретически способен обеспечить скорость чтения и записи информации, равную 8 байт (ширина шины) * 2 (количество каналов) * 2 (протокол DDR, обеспечивающий передачу 2 пакетов данных за 1 такт) * 200'000'000 (фактическая частота работы шины памяти равная 200 МГц, то есть 200'000'000 тактов в секунду). Значения, получаемые в результате практических тестов, как правило, чуть ниже теоретических: сказывается «неидеальность» конструкции контроллера памяти, плюс накладки (задержки), вызванные работой подсистемы кэширования самого процессора (см. ниже раздел про процессорный кэш). Однако основной «подвох» содержится даже не в накладках, связанных с работой контроллера и подсистемы кэширования, а в том, что скорость «линейного» чтения или записи является вовсе не единственной характеристикой, влияющей на фактическую скорость работы процессора с ОЗУ. Для того чтобы понять, из каких составляющих складывается фактическая скорость работы процессора с памятью, нам необходимо кроме линейной скорости считывания или записи учитывать ещё и такую характеристику, как латентность.

Латентность

Латентность является не менее важной характеристикой с точки зрения быстродействия подсистемы памяти, чем скорость «прокачки данных», но совершенно другой, по сути. Большая скорость обмена данными хороша тогда, когда их размер относительно велик, но если нам требуется «понемногу с разных адресов» — то на первый план выходит именно латентность. Что это такое? В общем случае — время, которое требуется для того, чтобы начать считывать информацию с определённого адреса. И действительно: с момента, когда процессор посылает контроллеру памяти команду на считывание (запись), и до момента, когда эта операция осуществляется, проходит определённое количество времени. Причём оно вовсе не равно времени, которое требуется на пересылку данных. Приняв команду на чтение или запись от процессора, контроллер памяти «указывает» ей, с каким адресом он желает работать. Доступ к любому произвольно взятому адресу не может быть осуществлён мгновенно, для этого требуется определённое время. Возникает задержка: адрес указан, но память ещё не готова предоставить к нему доступ. В общем случае, эту задержку и принято называть латентностью. У разных типов памяти она разная. Так, например, память типа DDR2 имеет в среднем гораздо большие задержки, чем DDR (при одинаковой частоте передачи данных). В результате, если данные в программе расположены «хаотично» и «небольшими кусками», скорость их считывания становится намного менее важной, чем скорость доступа к «началу куска», так как задержки при переходе на очередной адрес влияют на быстродействие системы намного сильнее, чем скорость считывания или записи.

«Соревнование» между скоростью чтения (записи) и латентностью — одна из основных головных болей разработчиков современных систем: к сожалению, рост скорости чтения (записи), почти всегда приводит к увеличению латентности. Так, например, память типа SDR (PC66, PC100, PC133) обладает в среднем лучшей (меньшей) латентностью, чем DDR. В свою очередь, у DDR2 латентность ещё выше (то есть хуже), чем у DDR.

Следует понимать, что «общая» латентность подсистемы памяти зависит не только от неё самой, но и от контроллера памяти и места его расположения — все эти факторы тоже влияют на задержку. Именно поэтому компания AMD в процессе разработки архитектуры AMD64 решила «одним махом» решить проблему высокой латентности, интегрировав контроллер прямо в процессор — чтобы максимально «сократить дистанцию» между процессорным ядром и модулями ОЗУ. Затея удалась, но дорогой ценой: теперь система на базе определённого CPU архитектуры AMD64 может работать только с той памятью, на которую рассчитан его контроллер. Наверное, именно поэтому компания Intel до сих пор не решилась на такой кардинальный шаг, предпочитая действовать традиционными методами: усовершенствуя контроллер памяти в чипсете и механизм Prefetch в процессоре (про него см. ниже).

В завершение, заметим, что понятия «скорость чтения / записи» и «латентность», в общем случае, применимы к любому типу памяти — в том числе не только к классической DRAM (SDR, Rambus, DDR, DDR2), но и к кэшу (см. ниже).Процессор: сведения общего характера

Понятие архитектуры

Архитектура как совместимость с кодом

Наверняка вы часто встречались с термином «x86», или «Intel-совместимый процессор» (или «IBM PC compatible» — но это уже по отношению к компьютеру). Иногда также встречается термин «Pentium-совместимый» (почему именно Pentium — вы поймете сами чуть позже). Что за всеми этими названиями скрывается на самом деле? На данный момент наиболее корректно с точки зрения автора выглядит следующая простая формулировка: современный x86-процессор — это процессор, способный корректно исполнять машинный код архитектуры IA32 (архитектура 32-битных процессоров Intel). В первом приближении это код, исполняемый процессором i80386 (известным в народе как «386-й»), окончательно же основной набор команд IA32 сформировался с выходом процессора Intel Pentium Pro. Что означает «основной набор» и какие есть еще? Для начала ответим на первую часть вопроса. «Основной» в данном случае означает то, что с помощью исключительно этого набора команд, может быть написана любая программа, которая вообще может быть написана для процессора архитектуры x86 (или IA32, если вам так больше нравится).

Кроме того, у архитектуры IA32 существуют «официальные» расширения (дополнительные наборы команд) от разработчика самой архитектуры, компании Intel: MMX, SSE, SSE2 и SSE3. Также существуют «неофициальные» (не от Intel) расширенные наборы команд: EMMX, 3DNow! и Extended 3DNow! — их разработала компания AMD. Впрочем, «официальность» и «неофициальность» в данном случае понятие относительное — де-факто все сводится к тому, что некоторые расширения набора команд Intel как разработчик изначального набора признает, а некоторые — нет, разработчики же программного обеспечения используют то, что им лучше всего подходит. В отношении расширенных наборов команд существует одно простое правило хорошего тона: прежде чем их использовать, программа должна проверить, поддерживает ли их процессор. Иногда отступления от этого правила встречаются (и могут приводить к неправильному функционированию программ), но объективно это является проблемой некорректно написанного программного обеспечения, а не процессора.

Для чего предназначены дополнительные наборы команд? В первую очередь — для увеличения быстродействия при выполнении некоторых операций. Одна команда из дополнительного набора, как правило, выполняет действие, для которого понадобилась бы небольшая программа, состоящая из команд основного набора. Опять-таки, как правило, одна команда выполняется процессором быстрее, чем заменяющая ее последовательность. Однако в 99% случаев, ничего такого, чего нельзя было бы сделать с помощью основных команд, с помощью команд из дополнительного набора сделать нельзя.

Таким образом, упомянутая выше проверка программой поддержки дополнительных наборов команд процессором, должна выполнять очень простую функцию: если, например, процессор поддерживает SSE — значит, считать будем быстро и с помощью команд из набора SSE. Если нет — будем считать медленнее, с помощью команд из основного набора. Корректно написанная программа обязана действовать именно так. Впрочем, сейчас практически никто не проверяет у процессора наличие поддержки MMX, так как все CPU, вышедшие за последние 5 лет, этот набор поддерживают гарантированно. Для справки приведем табличку, на которой обобщена информация о поддержке различных расширенных наборов команд различными десктопными (предназначенными для настольных ПК) процессорами.

Процессор

MMX

EMMX

3DNow!

SSE

E3DNow!

SSE2

SSE3

Intel Pentium II

+

Intel Celeron до 533 MHz

+

Intel Pentium III

+

+

Intel Celeron 533—1400 MHz

+

+

Intel Pentium 4

+

+

+

+/—*

Intel Celeron от 1700 MHz

+

+

+

Intel Celeron D

+

+

+

+

Intel Pentium 4 eXtreme Edition

+

+

+

+/—*

Intel Pentium eXtreme Edition

+

+

+

+

Intel Pentium D

+

+

+

+

AMD K6

+

+

AMD K6-2

+

+

+

AMD K6-III

+

+

+

AMD Athlon

+

+

+

+

AMD Duron до 900 MHz

+

+

+

+

AMD Athlon XP

+

+

+

+

+

AMD Duron от 1000 MHz

+

+

+

+

+

AMD Athlon 64 / Athlon FX

+

+

+

+

+

+

+/—*

AMD Sempron

+

+

+

+

+

+/—*

+/—*

AMD Athlon 64 X2

+

+

+

+

+

+

+

VIA C3

+

+

+/—*

+/—*

* в зависимости от модификации

На данный момент всё популярное десктопное программное обеспечение (операционные системы Windows и Linux, офисные пакеты, компьютерные игры, и прочее) разрабатывается именно для x86-процессоров. Оно выполняется (за исключением «дурно воспитанных» программ) на любом x86-процессоре, независимо от того, кто его произвел. Поэтому вместо ориентированных на разработчика изначальной архитектуры терминов «Intel-совместимый» или «Pentium-совместимый», стали употреблять нейтральное название: «x86-совместимый процессор», «процессор с архитектурой x86». В данном случае под «архитектурой» понимается совместимость с определённым набором команд, то есть, можно сказать, «архитектура процессора с точки зрения программиста». Есть и другая трактовка того же термина.

Архитектура как характеристика семейства процесcоров

«Железячники» — люди, работающие в основном не с программным обеспечением, а с аппаратным, под «архитектурой» понимают несколько другое (правда, более корректно то, что они называют «архитектурой», называется «микроархитектурой», но де-факто приставку «микро» частенько опускают). Для них «архитектура CPU» — это некий набор свойств, присущий целому семейству процессоров, как правило, выпускаемому в течение многих лет (иначе говоря — «внутренняя конструкция», «организация» этих процессоров). Так, например, любой специалист по x86 CPU вам скажет, что процессор с ALU, работающими на удвоенной частоте, QDR-шиной, Trace cache, и, возможно, поддержкой технологии Hyper-Threading — это «процессор архитектуры NetBurst» (не пугайтесь незнакомых терминов — все они будут разъяснены чуть позже). А процессоры Intel Pentium Pro, Pentium II и Pentium III — это «архитектура P6». Таким образом, понятие «архитектуры» применительно к процессорам несколько двойственно: под ним может пониматься как совместимость с неким единым набором команд, так и совокупность аппаратных решений, присущих определённой достаточно широкой группе процессоров. Разумеется, такой дуализм одного из основополагающих понятий не очень удобен, однако так уж сложилось, и вряд ли в ближайшее время что-то поменяется…

64-битные расширения классической x86 (IA32) архитектуры

Не так давно оба ведущих производителя x86 CPU анонсировали две практически идентичных* технологии (впрочем, AMD предпочитает называть это архитектурой), благодаря которым классические x86 (IA32) CPU получили статус 64-битных. В случае с AMD данная технология получила наименование «AMD64» (64-битная архитектура AMD), в случае с Intel — «EM64T» (расширенная 64-битная технология работы с памятью). Также почтенные аксакалы, знакомые с историей вопроса, иногда употребляют наименование «x86-64» — как общее обозначение всех 64-битных расширений архитектуры x86, не привязанное к зарегистрированным торговым маркам какого-либо производителя. Де-факто, употребление одного из трёх, приведенных выше, наименований, зависит больше от личных предпочтений употребляющего, чем от фактических различий — ибо различия между AMD64 и EM64T умещаются на кончике очень тонкой иглы. К тому же, сама AMD ввела «фирменное» наименование «AMD64» лишь незадолго до анонса собственных процессоров на основе данной архитектуры, а до этого совершенно спокойно употребляла в собственных документах более нейтральное «x86-64». Однако так или иначе, всё сводится к одному: некоторые внутренние регистры процессоров стали вместо 32-битных 64-битными, 32-битные команды x86-кода получили свои 64-битные аналоги, кроме того, объём адресуемой памяти (включая не только физическую, но и виртуальную) многократно увеличился (за счёт того, что адрес приобрёл вместо 32-битного 64-битный формат). Количество маркетинговых спекуляций на тему «64-битности» превысило все разумные пределы, поэтому нам следует рассмотреть достоинства данного нововведения особенно пристально. Итак: что же на самом деле изменилось, а что — нет?

* — Доводы о том, что Intel, дескать, «нагло скопировала EM64T с AMD64» не выдерживают никакой критики. И вовсе не потому, что это не так — а потому, что вовсе не «нагло». Есть такое понятие: «кросс-лицензионное соглашение». Если таковое соглашение имеет место быть, это означает, что все разработки одной компании в определённой области, становятся автоматически доступными другой, равно как и разработки другой автоматически становятся доступны первой. Intel воспользовалась кросс-лицензированием для разработки EM64T, взяв за основу AMD64 (чего никто никогда не отрицал). AMD воспользовалась тем же соглашением для введения в свои процессоры поддержки наборов дополнительных инструкций SSE2 и SSE3, разработанных Intel. И ничего в этом постыдного нет: раз договорились «делиться» разработками — значит, надо делиться.

Что не изменилось? В первую очередь — быстродействие процессоров. Вопиющей глупостью будет считать, что один и тот же процессор при переходе из привычного 32-битного в 64-битный режим (а 32-битный режим все нынешние x86 CPU поддерживают в обязательном порядке) станет работать в 2 раза быстрее. Разумеется, в некоторых случаях некое ускорение от использования 64-битной целочисленной арифметики может присутствовать — но количество этих случаев сильно ограничено, и большинства современного пользовательского программного обеспечения они никак не касаются. Кстати: а почему мы употребили термин «64-битная целочисленная арифметика»? А потому, что блоки операций с плавающей точкой (см. ниже) во всех x86-процессорах уже давным-давно не 32-битные. И даже не 64-битные. Классический x87 FPU (см. ниже), окончательно ставший частью CPU ещё во времена старого доброго 32-битного Intel Pentium — уже был 80-битным. Операнды команд SSE и SSE2/3 — и вовсе 128-битные! В этом плане архитектура x86 достаточно парадоксальна: при всём притом, что формально процессоры данной архитектуры достаточно долгое время оставались 32-битными — разрядность тех блоков, где «большая битность» была реально необходима — наращивалась совершенно независимо от остальных. Например, процессоры AMD Athlon XP и Intel Pentium 4 «Northwood» совмещали в себе блоки, работающие с 32-битными, 80-битными, и 128-битными операндами. 32-битными оставались лишь основной набор команд (унаследованный от первого процессора архитектуры IA32 — Intel 386) и адресация памяти (максимум 4 гигабайта, если не считать «извращений» типа Intel PAE).

Таким образом, то, что процессоры AMD и Intel стали «формально 64-битными», на практике принесло нам лишь три усовершенствования: появление команд для работы с 64-битными целыми числами, увеличение количества и/или разрядности регистров, и увеличение максимального объёма адресуемой памяти. Заметим: реальной пользы этих нововведений (особенно третьего!) никто не отрицает. Равно как никто не отрицает заслуг компании AMD в продвижении идеи «осовременивания» (за счёт введения 64-битности) x86-процессоров. Мы лишь хотим предостеречь от чрезмерных ожиданий: не стоит надеяться на то, что компьютер, покупавшийся «в ценовом классе ВАЗа», от установки 64-битного программного обеспечения станет «лихим Мерседесом». Чудес на свете не бывает…

Процессорное ядро

Различия между ядрами одной микроархитектуры

«Процессорное ядро» (как правило, для краткости его называют просто «ядро») — это конкретное воплощение [микро]архитектуры (т.е. «архитектуры в аппаратном смысле этого слова»), являющееся стандартом для целой серии процессоров. Например, NetBurst — это микроархитектура, которая лежит в основе многих сегодняшних процессоров Intel: Celeron, Pentium 4, Xeon. Микроархитектура задает общие принципы: длинный конвейер, использование определенной разновидности кэша кода первого уровня (Trace cache), прочие «глобальные» особенности. Ядро — более конкретное воплощение. Например, процессоры микроархитектуры NetBurst с шиной 400 МГц, кэшем второго уровня 256 килобайт, и без поддержки Hyper-Threading — это более-менее полное описание ядра Willamette. А вот ядро Northwood имеет кэш второго уровня уже 512 килобайт, хотя также основано на NetBurst. Ядро AMD Thunderbird основано на микроархитектуре K7, но не поддерживает набор команд SSE, а вот ядро Palomino — уже поддерживает.

Таким образом, можно сказать что «ядро» – это конкретное воплощение определенной микроархитектуры «в кремнии», обладающее (в отличие от самой микроархитектуры) определенным набором строго обусловленных характеристик. Микроархитектура — аморфна, она описывает общие принципы построения процессора. Ядро — конкретно, это микроархитектура, «обросшая» всевозможными параметрами и характеристиками. Чрезвычайно редки случаи, когда процессоры сменяли микроархитектуру, сохраняя название. И, наоборот, практически любое наименование процессора хотя бы несколько раз за время своего существования «меняло» ядро. Например, общее название серии процессоров AMD — «Athlon XP» — это одна микроархитектура (K7), но целых четыре ядра (Palomino, Thoroughbred, Barton, Thorton). Разные ядра, построенные на одной микроархитектуре, могут иметь, в том числе разное быстродействие.

Ревизии

Ревизия — одна из модификаций ядра, крайне незначительно отличающаяся от предыдущей, почему и не заслуживает звания «нового ядра». Как правило, из выпусков очередной ревизии производители процессоров не делают большого события, это происходит «в рабочем порядке». Так что даже если вы покупаете один и тот же процессор, с полностью аналогичным названием и характеристиками, но с интервалом где-то в полгода — вполне возможно, фактически он будет уже немного другой. Выпуск новой ревизии, как правило, связан с какими-то мелкими усовершенствованиями. Например, удалось чуть-чуть снизить энергопотребление, или понизить напряжение питания, или еще что-то оптимизировать, или была устранена пара мелких ошибок. С точки зрения производительности мы не помним ни одного примера, когда бы одна ревизия ядра отличалась от другой настолько существенно, чтобы об этом имело смысл говорить. Хотя чисто теоретически возможен и такой вариант — например, подвергся оптимизации один из блоков процессора, ответственный за исполнение нескольких команд. Подводя итог, можно сказать что «заморачиваться» ревизиями процессоров чаще всего не стоит: в очень редких случаях изменение ревизии вносит какие-то кардинальные изменения в процессор. Достаточно просто знать, что есть такая штука — исключительно для общего развития.

Частота работы ядра

Как правило, именно этот параметр в просторечии именуют «частотой процессора». Хотя в общем случае определение «частота работы ядра» всё же более корректно, так как совершенно не обязательно все составляющие CPU функционируют на той же частоте, что и ядро (наиболее частым примером обратного являлись старые «слотовые» x86 CPU — Intel Pentium II и Pentium III для Slot 1, AMD Athlon для Slot A — у них L2-кэш функционировал на 1/2, и даже иногда на 1/3 частоты работы ядра). Ещё одним распространённым заблуждением является уверенность в том, что частота работы ядра однозначным образом определяет производительность. На самом деле это дважды не так: во-первых, каждое конкретное процессорное ядро (в зависимости от того, как оно спроектировано, сколько содержит исполняющих блоков различных типов, и т.д. и т.п.) может исполнять различное количество команд за один такт, частота же — это всего лишь количество таких тактов в секунду. Таким образом (приведенное далее сравнение, разумеется, очень сильно упрощено и поэтому весьма условно) процессор, ядро которого исполняет 3 инструкции за такт, может иметь на треть меньшую частоту, чем процессор, исполняющий 2 инструкции за такт — и при этом обладать полностью аналогичным быстродействием.

Во-вторых, даже в рамках одного и того же ядра, увеличение частоты вовсе не всегда приводит к пропорциональному увеличению быстродействия. Здесь вам очень пригодятся знания, которые вы могли почерпнуть из раздела «Общие принципы взаимодействия процессора и ОЗУ». Дело в том, что скорость исполнения команд ядром процессора — это вовсе не единственный показатель, влияющий на скорость выполнения программы. Не менее важна скорость поступления команд и данных на CPU. Представим себе чисто теоретически такую систему: быстродействие процессора — 10'000 команд в секунду, скорость работы памяти — 1000 байт в секунду. Вопрос: даже если принять, что одна команда занимает не более одного байта, а данных у нас нет совсем, с какой скоростью будет исполняться программа в такой системе? Правильно: не более 1000 команд в секунду, и производительность CPU тут совершенно ни при чём: мы будем ограничены не ей, а скоростью поступления команд в процессор. Таким образом, следует понимать: невозможно непрерывно наращивать одну только частоту ядра, не ускоряя одновременно подсистему памяти, так как в этом случае начиная с определённого этапа, увеличение частоты CPU перестанет сказываться на увеличении быстродействия системы в целом.

Особенности образования названий процессоров

Раньше, когда небо было голубее, пиво — вкуснее, а девушки — красивее, процессоры называли просто: имя производителя + название модельного ряда + частота. Например: «AMD K6-2 450 MHz». В настоящее время уже оба основных производителя от этой традиции отошли, и вместо частоты употребляют какие-то непонятные циферки, обозначающие невесть что. Краткому объяснению того, что же на самом деле эти циферки обозначают, и посвящены следующие два раздела.

Рейтинги от AMD

Причина, по которой компания AMD «изъяла» частоту из наименования своих процессоров, и заменила её некой абстрактной цифрой — общеизвестна: после появления процессора Intel Pentium 4, который работает на очень высоких частотах, процессоры AMD рядом с ним стали «плохо выглядеть на витрине» — покупатель не верил, что CPU с частотой, например, 1500 МГц, может обогнать CPU с частотой 2000 МГц. Поэтому частоту в наименовании заменили рейтингом. Формальная («де-юре», так сказать) трактовка этого рейтинга в устах AMD в разные времена звучала немного по-разному, но ни разу не прозвучала в том виде, в каком её воспринимали пользователи: процессор AMD с неким рейтингом, должен быть как минимум не медленнее процессора Intel Pentium 4 с соответствующей данному рейтингу частотой. Между тем, ни для кого не являлось особенным секретом, что именно такая трактовка и являлась конечной целью введения рейтинга. В общем, все всё прекрасно понимали, но AMD старательно делала вид, что она тут ни при чём :). Пенять ей за это не стоит: в конкурентной борьбе применяются совсем другие правила, чем в рыцарских поединках. Тем более что результаты независимых тестов демонстрировали: в целом, рейтинги своим процессорам AMD назначает достаточно справедливые. Собственно, именно до тех пор, пока это так — вряд ли имеет смысл протестовать против использования рейтинга. Правда, остаётся открытым один вопрос: а к чему же (нас интересует, понятное дело, состояние де-факто, а не разъяснения маркетингового отдела) будет привязан рейтинг процессоров AMD чуть позже, когда вместо Pentium 4 Intel начнёт выпускать какой-нибудь другой процессор?

Processor Number от Intel

Что нужно запомнить сразу: Processor Number (далее PN) у процессоров Intel — это не рейтинг. Не рейтинг производительности, и не рейтинг чего-либо другого. Фактически, это просто «артикул», элемент строчки в складской ведомости, единственная задача которого — сделать так, чтобы строчка, обозначающая один процессор, отличалась от строчки, обозначающей другой. В рамках серии (первая цифра PN), две остальные цифры, в принципе, кое о чём могут сказать, но, учитывая наличие таблиц, в которых приведено полное соответствие между PN и реальными параметрами, мы не видим особого смысла в том, чтобы заучивать какие-то промежуточные соответствия. Мотивация, которой руководствовалась Intel, вводя PN (вместо опять-таки указания частоты CPU) — более сложная, чем у AMD. Необходимость введения PN (как её объясняет сама Intel) связана, прежде всего, с тем, что два основных конкурента по-разному подходят к вопросу об уникальности наименования CPU. Например, у AMD название «Athlon 64 3200+» может обозначать сразу четыре процессора с несколько различными техническими характеристиками (но одинаковым «рейтингом»). Intel придерживается мнения, что наименование процессора должно быть уникальным, в связи с чем ранее компании приходилось «изворачиваться», добавляя к значению частоты в наименовании различные буквы, и это приводило к путанице. По идее, PN должен был эту путаницу устранить. Трудно сказать, была ли достигнута поставленная цель: всё равно номенклатура процессоров Intel осталась достаточно сложной. С другой стороны, это неизбежно, так как ассортимент продуктов уж больно велик. Однако независимо от всего прочего, одного эффекта де-факто добиться точно удалось: теперь только разбирающиеся в вопросе специалисты могут по названию процессора быстро и точно «по памяти» сказать, что он собой представляет, и какова будет его производительность в сравнении с другими CPU. Насколько это хорошо? Сложно сказать. Мы предпочтём воздержаться от комментариев.

Измерение скорости «в мегагерцах» — как это возможно?

Никак это невозможно, потому что скорость не измеряется в мегагерцах, как не измеряется расстояние в килограммах. Однако господа маркетологи давно уже поняли, что в словесном поединке между физиком и психологом побеждает всегда последний — причём независимо от того, кто на самом деле прав. Поэтому мы и читаем про «сверхбыструю 1066 MHz FSB», мучительно пытаясь понять, как скорость может измеряться с помощью частоты. На самом деле, раз уж прижилась такая извращённая тенденция, нужно просто чётко представлять себе, что имеется в виду. А имеется в виду следующее: если мы «закрепим» ширину шины на N битах — то её пропускная способность действительно будет зависеть от того, на какой частоте данная шина функционирует, и какое количество данных она способна передавать за такт. По обычной процессорной шине с «одинарной» скоростью (такая шина была, например, у процессора Intel Pentium III) за такт передаётся 64 бита, то есть 8 байт. Соответственно, если рабочая частота шины равна 100 МГц (100'000'000 тактов в секунду) — то скорость передачи данных будет равна 8 байт * 100'000'000 герц ~= 763 мегабайта в секунду (а если считать в «десятичных мегабайтах», в которых принято считать потоки данных, то ещё красивее — 800 мегабайт в секунду). Соответственно, если на тех же 100 мегагерцах работает DDR-шина, способная передавать за один такт удвоенный объём данных — скорость вырастет ровно вдвое. Поэтому, согласно парадоксальной логике господ маркетологов, данную шину следует именовать «200-мегагерцевой». А если это ещё и QDR (Quad Data Rate) шина — то она и вовсе «400-мегагерцевая» получается, так как за один такт передаёт четыре пакета данных. Хотя реальная частота работы у всех трёх вышеописанных шин одинаковая — 100 мегагерц. Вот так «мегагерцы» и стали синонимом скорости.

Таким образом, QDR-шина (с «учетверённой» скоростью), работающая на реальной частоте 266 мегагерц, волшебным образом оказывается у нас «1066-мегагерцевой». Цифра «1066» в данном случае олицетворяет то, что её пропускная способность ровно в 4 раза больше «односкоростной» шины, работающей на той же самой частоте. Вы ещё не запутались?.. Привыкайте! Это вам не какая-нибудь теория относительности, тут всё намного сложней и запущенней… Впрочем, самое главное здесь — выучить наизусть один простой принцип: если уж мы занимаемся таким извращением, как сравнение скорости двух шин между собой «в мегагерцах» — то они обязательно должны быть одинаковой ширины. Иначе получается как в одном форуме, где человек всерьёз доказывал, что пропускная способность AGP2X («133-мегагерцевая», но 32-битная шина) — выше, чем пропускная способность FSB у Pentium III 800 (реальная частота 100 МГц, ширина 64 бита).

Пара слов о некоторых пикантных особенностях DDR и QDR протоколов

Как уже было сказано выше, в режиме DDR по шине за один такт передаётся удвоенный объём информации, а в режиме QDR — учетверённый. Правда, в документах, ориентированных больше на прославление достижений производителей, чем на объективное освещение реалий, почему-то всегда забывают указать одно маленькое «но»: режимы удвоенной и учетверённой скорости включаются только при пакетной передаче данных. То есть, если мы запросили из памяти парочку мегабайтов с адреса X по адрес Y — то да, эти два мегабайта будут переданы с удвоенной/учетверённой скоростью. А вот сам запрос на данные посылается по шине с «одинарной» скоростью — всегда! Соответственно, если запросов у нас много, а размер пересылаемых данных не очень велик, то количество данных, которые «путешествуют» по шине с одинарной скоростью (а запрос — это тоже данные) будет почти равно количеству тех, которые передаются со скоростью удвоенной или учетверённой. Вроде бы нам никто открыто не врал, вроде бы DDR и QDR действительно работают, но… как говорится в одном старом анекдоте: «то ли он у кого-то украл шубу, то ли у него кто-то украл шубу, но что-то там с шубой не то…» ;)Процессор «крупноблочно»

Кэш

Общее описание и принцип действия

Во всех современных процессорах есть кэш (по-английски — cache). Кэш — это некая особенная разновидность памяти (основная особенность, кардинально отличающая кэш от ОЗУ — скорость работы), которая является своего рода «буфером» между контроллером памяти и процессором. Служит этот буфер для увеличения скорости работы с ОЗУ. Каким образом? Сейчас попытаемся объяснить. При этом мы решили отказаться от попахивающих детским садом сравнений, которые частенько встречаются в популяризаторской литературе на процессорную тематику (бассейны, соединённые трубами разного диаметра, и т.д. и т.п.). Всё-таки человек, который дочитал статью до этого места, и не заснул — наверное, способен выдержать и «переварить» чисто техническое объяснение, без бассейнов, кошечек и одуванчиков.

Итак, представим, что у нас есть много сравнительно медленной памяти (пусть это будет ОЗУ размером 10'000'000 байт) и относительно мало очень быстрой (пусть это будет кэш размером всего 1024 байта). Как нам с помощью этого несчастного килобайта увеличить скорость работы со всей памятью вообще? А вот здесь следует вспомнить, что данные в процессе работы программы, как правило, не бездумно перекидываются с места на место — они изменяются. Считали из памяти значение какой-то переменной, прибавили к нему какое-то число — записали обратно на то же место. Считали массив, отсортировали по возрастанию — опять-таки записали в память. То есть в один какой-то момент программа работает не со всей памятью целиком, а, как правило, с относительно маленьким её фрагментом. Какое решение напрашивается? Правильно: загрузить этот фрагмент в «быструю» память, обработать его там, а потом уже записать обратно в «медленную» (или просто удалить из кэша, если данные не изменялись). В общем случае, именно так и работает процессорный кэш: любая считываемая из памяти информация попадает не только в процессор, но и в кэш. И если эта же информация (тот же адрес в памяти) нужна снова, сначала процессор проверяет: а нет ли её в кэше? Если есть — информация берётся оттуда, и обращения к памяти не происходит вовсе. Аналогично с записью: информация, если её объём влезает в кэш — пишется именно туда, и только потом, когда процессор закончил операцию записи, и занялся выполнением других команд, данные, записанные в кэш, параллельно с работой процессорного ядра «потихоньку выгружаются» в ОЗУ.

Разумеется, объём данных, прочитанных и записанных за всё время работы программы — намного больше объёма кэша. Поэтому некоторые из них приходится время от времени удалять, чтобы в кэш могли поместиться новые, более актуальные. Самый простой из известных механизмов обеспечения данного процесса — отслеживание времени последнего обращения к данным, находящимся в кэше. Так, если нам необходимо поместить новые данные в кэш, а он уже «забит под завязку», контроллер, управляющий кэшем, смотрит: к какому фрагменту кэша не происходило обращения дольше всего? Именно этот фрагмент и является первым кандидатом на «вылет», а на его место записываются новые данные, с которыми нужно работать сейчас. Вот так, в общих чертах, работает механизм кэширования в процессорах. Разумеется, приведенное выше объяснение весьма примитивно, на самом деле всё ещё сложнее, но, надеемся, общее представление о том, зачем процессору нужен кэш и как он работает, вы получить смогли.

А для того чтобы было понятно, насколько важен кэш, приведем простой пример: скорость обмена данными процессора Pentium 4 со своим кэшам более чем в 10 раз (!) превосходит скорость его работы с памятью. Фактически, в полную силу современные процессоры способны работать только с кэшем: как только они сталкиваются с необходимостью прочитать данные из памяти — все их хваленые мегагерцы начинают просто «греть воздух». Опять-таки, простой пример: выполнение простейшей инструкции процессором происходит за один такт, то есть за секунду он может выполнить такое количество простых инструкций, какова его частота (на самом деле еще больше, но это оставим на потом…). А вот время ожидания данных из памяти может в худшем случае составить более 200 тактов! Что делает процессор, пока он ждет нужных данных? А ничего он не делает. Просто стоит и ждет…

Многоуровневое кэширование

Специфика конструирования современных процессорных ядер привела к тому, что систему кэширования в подавляющем большинстве CPU приходится делать многоуровневой. Кэш первого уровня (самый «близкий» к ядру) традиционно разделяется на две (как правило, равные) половины: кэш инструкций (L1I) и кэш данных (L1D). Это разделение предусматривается так называемой «гарвардской архитектурой» процессора, которая по состоянию на сегодня является самой популярной теоретической разработкой для построения современных CPU. В L1I, соответственно, аккумулируются только команды (с ним работает декодер, см. ниже), а в L1D — только данные (они впоследствии, как правило, попадают во внутренние регистры процессора). «Над L1» стоит кэш второго уровня — L2. Он, как правило, больше по объёму, и является уже «смешанным» — там располагаются и команды, и данные. L3 (кэш третьего уровня), как правило, полностью повторяет структуру L2, и в современных x86 CPU встречается редко. Чаще всего, L3 — это плод компромисса: за счёт использование более медленной и узкой шины, его можно сделать очень большим, но при этом скорость L3 всё равно остаётся более высокой, чем скорость памяти (хотя и не такой высокой, как у L2-кэша). Тем не менее, алгоритм работы с многоуровневым кэшем в общих чертах не отличается от алгоритма работы с одноуровневым, просто добавляются лишние итерации: сначала информация ищется в L1, если её там нет — в L2, потом — в L3, и уже потом, если ни на одном уровне кэша она не найдена — идёт обращение к основной памяти (ОЗУ).

Декодер

На самом деле, исполнительные блоки всех современных десктопных x86-процессоров… вовсе не работают с кодом в стандарте x86. У каждого процессора есть своя, «внутренняя» система команд, не имеющая ничего общего с теми командами (тем самым «кодом»), которые поступают извне. В общем случае, команды, исполняемые ядром — намного проще, «примитивнее», чем команды стандарта x86. Именно для того, чтобы процессор «внешне выглядел» как x86 CPU, и существует такой блок как декодер: он отвечает за преобразование «внешнего» x86-кода во «внутренние» команды, исполняемые ядром (при этом достаточно часто одна команда x86-кода преобразуется в несколько более простых «внутренних»). Декодер является очень важной частью современного процессора: от его быстродействия зависит то, насколько постоянным будет поток команд, поступающих на исполняющие блоки. Ведь они неспособны работать с кодом x86, поэтому то, будут они что-то делать, или простаивать — во многом зависит от скорости работы декодера. Достаточно необычный способ ускорить процесс декодирования команд реализовала в процессорах архитектуры NetBurst компания Intel — см. ниже про Trace cache.

Исполняющие (функциональные) устройства

Пройдя через все уровни кэша и декодер, команды наконец-то попадают на те блоки, ради которых вся эта катавасия и устраивалась: исполняющие устройства. По сути, именно исполняющие устройства и являются единственно необходимым элементом процессора. Можно обойтись без кэша — скорость снизится, но программы работать будут. Можно обойтись без декодера — исполняющие устройства станут сложнее, но работать процессор будет. В конце концов, ранние процессоры архитектуры x86 (i8086, i80186, 286, 386, 486, Am5x86) — как-то без декодера обходились. Без исполняющих устройств обойтись невозможно, ибо именно они исполняют код программы. В самом первом приближении они традиционно делятся на две больших группы: арифметико-логические устройства (ALU) и блок вычислений с плавающей точкой (FPU).

Арифметико-логические устройства

ALU традиционно отвечают за два типа операций: арифметические действия (сложение, вычитание, умножение, деление) с целыми числами, логические операции с опять-таки целыми числами (логическое «и», логическое «или», «исключающее или», и тому подобные). Что, собственно, и следует из их названия. Блоков ALU в современных процессорах, как правило, несколько. Для чего — вы поймёте позже, прочитав раздел «Суперскалярность и внеочередное исполнение команд». Понятно, что ALU может исполнить только те команды, которые предназначены для него. Распределением команд, поступающих с декодера, по различным исполняющим устройствам, занимается специальный блок, но это уже, как говорится, «слишком сложные материи», и их вряд ли имеет смысл разъяснять в материале, который посвящен лишь поверхностному ознакомлению с основными принципами работы современных x86 CPU.

Блок вычислений с плавающей запятой*

FPU занимается выполнением команд, работающих с числами с плавающей запятой, кроме того, традиционно на него «вешают всех собак» в виде всяческих дополнительных наборов команд (MMX, 3DNow!, SSE, SSE2, SSE3…) — независимо от того, работают они с числами с плавающей запятой, или с целыми. Как и в случае с ALU, отдельных блоков в FPU может быть несколько, и они способны работать параллельно.

* — согласно традиций русской математической школы, мы называем FPU «блоком вычислений с плавающей запятой», хотя буквально его название (Floating Point Unit) переводится как «…с плавающей точкой» — согласно американскому стандарту написания таких чисел.

Регистры процессора

Регистры — по сути, те же ячейки памяти, но «территориально» они расположены прямо в процессорном ядре. Разумеется, скорость работы с регистрами во много раз превосходит как скорость работы с ячейками памяти, расположенными в основном ОЗУ (тут вообще на порядки…), так и с кэшами любого уровня. Поэтому большинство команд архитектуры x86 предусматривают осуществление действий именно над содержимым регистров, а не над содержимым памяти. Однако общий объём регистров процессора, как правило, очень мал — он не сравним даже с объёмом кэшей первого уровня. Поэтому де-факто код программы (не на языке высокого уровня, а именно бинарный, «машинный») часто содержит следующую последовательность операций: загрузить в один из регистров процессора информацию из ОЗУ, загрузить в другой регистр другую информацию (тоже из ОЗУ), произвести некое действие над содержимым этих регистров, поместив результат в третий — а потом снова выгрузить результат из регистра в основную память. Процессор в подробностях

Особенности кэшей

Частота работы кэша и его шина

Во всех современных x86 CPU все уровни кэша работают на той же частоте, что и процессорное ядро, но это вовсе не всегда было так (данный вопрос уже поднимался выше). Однако скорость работы с кэшем зависит не только от частоты, но и от ширины шины, с помощью которой он соединён с процессорным ядром. Как вы (надеемся) помните из ранее прочитанного, скорость передачи данных является, по сути, произведением частоты работы шины (количества тактов в секунду) на количество байт, которые передаются по шине за один такт. Количество передаваемых за такт байтов можно увеличивать за счёт введения DDR и QDR (Double Data Rate и Quad Data Rate) протоколов — или просто за счёт увеличения ширины шины. В случае с кэшем более популярен второй вариант — не в последнюю очередь из-за «пикантных особенностей» DDR/QDR, описанных выше. Разумеется, минимально разумной шириной шины кэша является ширина внешней шины самого процессора, то есть, по состоянию на сегодняшний день — 64 бита. Именно так, в духе здорового минимализма, и поступает компания AMD: в её процессорах ширина шины L1 L2 равна 64 битам, но при этом она двунаправленная, то есть, способна работать одновременно на передачу и приём информации. В духе «здорового гигантизма» в очередной раз поступила компания Intel: в её процессорах, начиная с Pentium III «Coppermine», шина L1 L2 имеет ширину… 256 бит! По принципу «кашу маслом не испортишь», как говорится. Правда, шина эта однонаправленная, то есть в один момент времени работает либо только на передачу, либо только на приём. Споры о том, какой из подходов лучше (двунаправленная шина, но более узкая, или однонаправленная широкая) — продолжаются до сих пор… впрочем, равно как и множество других споров относительно технических решений, применяемых двумя основными конкурентами на рынке x86 CPU.

Концепции эксклюзивного и не эксклюзивного кэширования очень просты: в случае не эксклюзивного кэша, информация на всех уровнях кэширования может дублироваться. Таким образом, L2 может содержать в себе данные, которые уже находятся в L1I и L1D, а L3 (если он есть) может содержать в себе полную копию всего содержимого L2 (и, соответственно, L1I и L1D). Эксклюзивный кэш, в отличие от не эксклюзивного, предусматривает чёткое разграничение: если информация содержится на каком-то уровне кэша — то на всех остальных она отсутствует. Плюс эксклюзивного кэша очевиден: общий размер кэшируемой информации в данном случае равен суммарному объёму кэшей всех уровней — в отличие от не эксклюзивного кэша, где размер кэшируемой информации (в худшем случае) равен объёму самого большого уровня кэша. Минус эксклюзивного кэша менее очевиден, но он есть: необходим специальный механизм, который следит за собственно «эксклюзивностью» (так, например, при удалении информации из L1-кэша, перед этим автоматически инициируется процесс её копирования в L2).

Не эксклюзивный кэш традиционно использует компания Intel, эксклюзивный (с момента появления процессоров Athlon на ядре Thunderbird) — компания AMD. В целом, мы наблюдаем здесь классическое противостояние между объёмом и скоростью: за счёт эксклюзивности, при одинаковых объёмах L1/L2 у AMD общий размер кэшируемой информации получается больше — но за счёт неё же он работает медленней (задержки, вызванные наличием механизма обеспечения эксклюзивности). Следует, наверное, заметить, что недостатки не эксклюзивного кэша компания Intel в последнее время компенсирует просто, тупо, но весомо: наращивая его объёмы. Для топовых процессоров данной компании стал уже почти что нормой L2-кэш объёмом 2 МБ — и AMD с её 128 КБ L1С+L1D и максимум 1 МБ L2 пока «не переплюнуть» эти 2 МБ даже за счёт эксклюзивности.

Кроме того, увеличивать общий объём кэшируемой информации за счёт введения эксклюзивной архитектуры кэша имеет смысл только в том случае, когда выигрыш в объёме получается достаточно большим. Для компании AMD это актуально т.к. у её сегодняшних CPU суммарный объём L1D+L1I равен 128 КБ. Процессорам Intel, у которых объём L1D равен максимум 32 КБ, а L1I иногда имеет совсем другую структуру (см. про Trace cache), введение эксклюзивной архитектуры дало бы намного меньше пользы.

А ещё есть такое распространённое заблуждение, что архитектура кэша у CPU компании Intel «инклюзивная». На самом деле — нет. Именно НЕ эксклюзивная. Инклюзивная архитектура предусматривает, что на «нижнем» уровне кэша не может находиться ничего, чего нет на более «верхнем». Не эксклюзивная архитектура всего лишь допускает дублирование данных на разных уровнях.

Trace cache

Концепция Trace cache, состоит в том, чтобы сохранять в кэше инструкций первого уровня (L1I) не те команды, которые считаны из памяти, а уже декодированные последовательности (см. декодер). Таким образом, если некая x86-команда исполняется повторно, и она всё ещё находится в L1I, декодеру процессора не нужно снова преобразовывать её в последовательность команд «внутреннего кода», так как L1I содержит данную последовательность в уже декодированном виде. Концепция Trace cache очень удачно вписывается в общую концепцию архитектуры Intel NetBurst, ориентированную на создание процессоров с очень высокой частотой работы ядра. Однако полезность Trace cache для [относительно] менее высокочастотных CPU до сих пор находится под вопросом, так как сложность организации Trace cache становится сопоставима с задачей конструирования обычного быстрого декодера. Поэтому, отдавая должное оригинальности идеи, мы всё же сказали бы, что универсальным решением «на все случаи жизни» Trace cache считать нельзя.

Суперскалярность и внеочередное исполнение команд

Основная черта всех современных процессоров состоит в том, что они способны запускать на исполнение не только ту команду, которую (согласно коду программы) следует исполнить в данный момент времени, но и другие, следующие после неё. Приведём простой (канонический) пример. Пусть нам следует исполнить следующую последовательность команд:

1) A = B + C 2) Z = X + Y

3) K = A + Z

Легко заметить, что команды (1) и (2) совершенно независимы друг от друга — они не пересекаются ни по исходным данным (переменные B и C в первом случае, X и Y во втором), ни по месту размещения результата (переменная A в первом случае и Z во втором). Стало быть, если на данный момент у нас есть свободные исполняющие блоки в количестве более одного, данные команды можно распределить по ним, и выполнить одновременно, а не последовательно*. Таким образом, если принять время исполнения каждой команды равным N тактов процессора, то в классическом случае исполнение всей последовательности заняло бы N*3 тактов, а в случае с параллельным исполнением — всего N*2 тактов (так как команду (3) нельзя выполнить, не дождавшись результата исполнения двух предыдущих).

* — разумеется, степень параллелизма не бесконечна: команды могут быть выполнены параллельно только в том случае, когда на данный момент времени есть в наличии соответствующее количество свободных от работы блоков (ФУ), причём именно таких, которые «понимают» рассматриваемые команды. Самый простой пример: блок, относящийся к ALU, физически неспособен исполнить инструкцию, предназначенную для FPU. Обратное также верно.

На самом деле всё ещё сложнее. Так, если у нас имеется следующая последовательность:

1) A = B + C 2) K = A + M

3) Z = X + Y

То очередь исполнения команд процессором будет изменена! Так как команды (1) и (3) независимы друг от друга (ни по исходным данным, ни по месту размещения результата), они могут быть выполнены параллельно — и будут выполнены параллельно. А вот команда (2) будет выполнена после них (третьей) — поскольку для того, чтобы результат вычислений был корректен, необходимо, чтобы перед этим была выполнена команда (1). Именно поэтому обсуждаемый в данном разделе механизм и называется «внеочередным исполнением команд» (Out-of-Order Execution, или сокращённо «OoO»): в тех случаях, когда очерёдность выполнения никак не может сказаться на результате, команды отправляются на исполнение не в той последовательности, в которой они располагаются в коде программы, а в той, которая позволяет достичь максимального быстродействия.

Теперь вам должно стать окончательно понятно, зачем современным CPU такое количество однотипных исполняющих блоков: они обеспечивают возможность параллельного выполнения нескольких команд, которые в случае с «классическим» подходом к проектированию процессора пришлось бы выполнять в той последовательности, в которой они содержатся в исходном коде, одну за другой.

Процессоры, оснащённые механизмом параллельного исполнения нескольких подряд идущих команд, принято называть «суперскалярными». Однако не все суперскалярные процессоры поддерживают внеочередное исполнение. Так, в первом примере нам достаточно «простой суперскалярности» (выполнения двух последовательных команд одновременно) — а вот во втором примере без перестановки команд местами уже не обойтись, если мы хотим получить максимальное быстродействие. Все современные x86 CPU обладают обоими качествами: являются суперскалярными, и поддерживают внеочередное исполнение команд. В то же время, были в истории x86 и «простые суперскаляры», OoO не поддерживающие. Например, классическим десктопным x86-суперскаляром без OoO был Intel Pentium [MMX].

Справедливости ради, стоит заметить, что никаких заслуг в разработке концепций суперскалярности и OoO — нет ни у Intel, ни у AMD, ни у какого-либо иного (в том числе из ныне почивших) производителя x86 CPU. Первый суперскалярный компьютер, поддерживающий OoO, был разработан Сеймуром Креем (Seymour Cray) ещё в 60-х годах XX века. Для сравнения: Intel свой первый суперскалярный процессор (Pentium) выпустила в 1993 году, первый суперскаляр с OoO (Pentium Pro) — в 1995 году; первый суперскаляр с OoO от AMD (K5) увидел свет в 1996 году. Комментарии, как говорится, излишни…

Предварительное (опережающее) декодированиеи кэширование

Предсказание ветвлений

В любой более-менее сложной программе присутствуют команды условного перехода: «Если некое условие истинно — перейти к исполнению одного участка кода, если нет — другого». С точки зрения скорости выполнения кода программы современным процессором, поддерживающим внеочередное исполнение, любая команда условного перехода — воистину бич божий. Ведь до тех пор, пока не станет известно, какой участок кода после условного перехода окажется «актуальным» — его невозможно начать декодировать и исполнять (см. внеочередное исполнение). Для того чтобы как-то примирить концепцию внеочередного исполнения с командами условного перехода, предназначается специальный блок: блок предсказания ветвлений. Как понятно из его названия, занимается он, по сути, «пророчествами»: пытается предсказать, на какой участок кода укажет команда условного перехода, ещё до того, как она будет исполнена. В соответствии с указаниями «штатного внутриядерного пророка», процессором производятся вполне реальные действия: «напророченный» участок кода загружается в кэш (если он там отсутствует), и даже начинается декодирование и выполнение его команд. Причём среди выполняемых команд также могут содержаться инструкции условного перехода, и их результаты тоже предсказываются, что порождает целую цепочку из пока не проверенных предсказаний! Разумеется, если блок предсказания ветвлений ошибся, вся проделанная в соответствии с его предсказаниями работа просто аннулируется.

На самом деле, алгоритмы, по которым работает блок предсказания ветвлений, вовсе не являются шедеврами искусственного интеллекта. Преимущественно они просты… и тупы. Ибо чаще всего команда условного перехода встречается в циклах: некий счётчик принимает значение X, и после каждого прохождения цикла значение счётчика уменьшается на единицу. Соответственно, до тех пор, пока значение счётчика больше нуля — осуществляется переход на начало цикла, а после того, как он становится равным нулю — исполнение продолжается дальше. Блок предсказания ветвлений просто анализирует результат выполнения команды условного перехода, и считает, что если N раз подряд результатом стал переход на определённый адрес — то и в N+1 случае будет осуществлён переход туда же. Однако, несмотря на весь примитивизм, данная схема работает просто замечательно: например, в случае, если счётчик принимает значение 100, а «порог срабатывания» предсказателя ветвлений (N) равен двум переходам подряд на один и тот же адрес — легко заметить, что 97 переходов из 98 будут предсказаны правильно!

Разумеется, несмотря на достаточно высокую эффективность простых алгоритмов, механизмы предсказания ветвлений в современных CPU всё равно постоянно совершенствуются и усложняются — но тут уже речь идёт о борьбе за единицы процентов: например, за то, чтобы повысить эффективность работы блока предсказания ветвлений с 95 процентов до 97, или даже с 97% до 99…

Предвыборка данных

Блок предвыборки данных (Prefetch) очень похож по принципу своего действия на блок предсказания ветвлений — с той только разницей, что в данном случае речь идёт не о коде, а о данных. Общий принцип действия такой же: если встроенная схема анализа доступа к данным в ОЗУ решает, что к некоему участку памяти, ещё не загруженному в кэш, скоро будет осуществлён доступ — она даёт команду на загрузку данного участка памяти в кэш ещё до того, как он понадобится исполняемой программе. «Умно» (результативно) работающий блок предвыборки позволяет существенно сократить время доступа к нужным данным, и, соответственно, повысить скорость исполнения программы. К слову: грамотный Prefetch очень хорошо компенсирует высокую латентность подсистемы памяти, подгружая нужные данные в кэш, и тем самым, нивелируя задержки при доступе к ним, если бы они находились не в кэше, а в основном ОЗУ.

Однако, разумеется, в случае ошибки блока предвыборки данных, неизбежны негативные последствия: загружая де-факто «ненужные» данные в кэш, Prefetch вытесняет из него другие (быть может, как раз нужные). Кроме того, за счёт «предвосхищения» операции считывания, создаётся дополнительная нагрузка на контроллер памяти (де-факто, в случае ошибки — совершенно бесполезная).

Алгоритмы Prefetch, как и алгоритмы блока предсказания ветвлений, тоже не блещут интеллектуальностью: как правило, данный блок стремится отследить, не считывается ли информация из памяти с определённым «шагом» (по адресам), и на основании этого анализа пытается предсказать, с какого адреса будут считываться данные в процессе дальнейшей работы программы. Впрочем, как и в случае с блоком предсказания ветвлений, простота алгоритма вовсе не означает низкую эффективность: в среднем, блок предвыборки данных чаще «попадает», чем ошибается (и это, как и в предыдущем случае, прежде всего связано с тем, что «массированное» чтение данных из памяти, как правило происходит в процессе исполнения различных циклов).Заключение

Я — тот кролик, который не может начать жевать траву до тех пор, пока не поймёт во всех деталях, как происходит процесс фотосинтеза!

(изложение личной позиции одним из близких знакомых автора)

Вполне возможно, те чувства, которые у вас возникли после прочтения данной статьи, можно описать примерно следующим образом: «Вместо того чтобы на пальцах объяснить, какой процессор лучше — взяли и загрузили мне мозги кучей специфической информации, в которой ещё разбираться и разбираться, и конца-края не видно!» Вполне нормальная реакция: поверьте, мы вас хорошо понимаем. Скажем даже больше (и пусть с головы упадёт корона!): если вы думаете, что мы сами можем ответить на этот простецкий вопрос («какой процессор лучше?») — то вы очень сильно заблуждаетесь. Не можем. Для одних задач лучше один, для других — другой, а тут ещё цена разная, доступность, симпатии конкретного пользователя к определённым маркам… Не имеет задача однозначного решения. Если бы имела — наверняка кто-то бы его нашёл, и стал бы самым знаменитым обозревателем за всю историю независимых тестовых лабораторий.

Хотелось бы подчеркнуть ещё раз: даже полностью усвоив и осмыслив всю информацию, изложенную в данном материале — вы по-прежнему не сможете предсказать, какой из двух процессоров будет быстрее в ваших задачах, глядя только на их характеристики. Во-первых — потому, что далеко не все характеристики процессоров здесь рассмотрены. Во-вторых — потому, что есть и такие параметры CPU, которые в числовом виде могут быть представлены только с очень большой «натяжкой». Так для кого же (и для чего) всё это написано? В основном — для тех самых «кроликов», которые непременно желают знать, что происходит внутри тех устройств, которыми они пользуются ежедневно. Зачем? Может, они просто лучше себя чувствуют, когда знают, что вокруг них происходит? :)

В ближайших планах на расширение FAQ:

  1. Раздел, посвящённый многопроцессорным системам: объяснение понятия SMP, технология Hyper-Threading, N-процессорность, N-ядерность.
  2. Раздел, посвящённый физическим характеристикам CPU: типы корпусов, сокеты, энергопотребление, и т.п.

www.ixbt.com


Смотрите также