Со временем продавцы добавил все больше и больше инструкций в процессоры, управляющие нашими ноутбуками, серверами, телефонами и многими другими устройствами.
Добавление машинных инструкций, решающих конкретные вычислительные подзадачи, — хороший способ повысить производительность системы в целом, не усложняя конвейер и не пытаясь увеличить частоту до запредельных значений.
Одна новая инструкция, выполняющая ту же операцию, что и несколько старых, может многократно повысить производительность решения заданной задачи.
Новые инструкции, такие как Расширения Intel Software Guard (Intel SGX) И Технология Intel Control-flow Enforcement (Intel CET) , также способны предоставлять совершенно новые функциональные возможности.
Хороший вопрос заключается в том, как быстро новые инструкции, добавленные в архитектуру, доходят до конечного пользователя.
Могут ли операционные системы и другие приложения воспользоваться преимуществами новых инструкций? , учитывая, что они, как правило, обратно совместимы и могут работать независимо от установленной модели процессора? Много лет назад использование новых инструкций достигалось путем перестройки программы под новую архитектуру и добавления проверок, которые не позволяли ей запускаться на старом оборудовании и выводили что-то вроде «извините, эта программа не поддерживается на этом оборудовании».
Я использовал полноплатформенный симулятор Винд Ривер Симикс чтобы выяснить, в какой степени современное программное обеспечение может использовать новые инструкции, оставаясь при этом совместимым со старым оборудованием.
?Экспериментальная установка
Чтобы выяснить, как программное обеспечение может динамически адаптироваться к различному оборудованию, я использовал модель Simics «универсальной платформы ПК» и две разные модели процессоров: Intel Core i7 первого поколения (под кодовым названием Nehalem, выпущенный в конце 2008 года) и шестое поколение.Intel Core i7 нового поколения (кодовое название Skylake, выпущен в середине 2015 года).
Были изучены следующие сценарии загрузки ОС Linux, запущенной на описанных выше конфигурациях:
- Ubuntu 16.04, версия ядра 4.4, выпущенная в 2016 г.
,
- Yocto 1.8, версия ядра 3.14, выпущенная в 2014 г.
,
- Busybox с ядром 2.6.39, выпущенный в 2011 году.
Отличалась только конфигурация процессора в виртуальной платформе.
Ожидалось, что Linux, работающий на более новом оборудовании, будет использовать новые инструкции.
Каждая конфигурация запускалась с подключенным механизмом инструментирования, который подсчитывал количество выполнений каждой инструкции.
Существующий механизм инструментирования в Simics не меняет поведение гостевых приложений и позволяет изучать загрузку BIOS и ядра операционной системы за счет того, что он работает на уровне команд процессора.
В то же время работающее приложение не может определить, работает оно с инструментированием или без него.
Каждая конфигурация выполнялась в течение 60 секунд виртуального времени.
Этого достаточно для загрузки биоса и операционной системы.
После каждого запуска отбирались 100 наиболее часто используемых инструкций и использовались для дальнейшего анализа.
Изучение основ идентификации процессора
Эта работа основана на предположении, что программное обеспечение может динамически адаптировать исполняемый код в зависимости от используемого оборудования.То есть одна и та же двоичная структура может использовать разные инструкции на разном оборудовании.
Чтобы понять, как работает такая динамическая адаптация, нужно понять, как работает аппаратное обеспечение.
В те времена, когда процессоров было мало, а новые модели появлялись довольно редко, программное обеспечение могло легко проверить, работает ли оно на Intel 80386 или 80486 или Motorola 68020 или 68030, и соответствующим образом адаптировать свое поведение.
Сейчас существует огромное количество различных систем.
Для решения проблемы идентификации на процессорах IA-32 следует использовать Инструкция CPUID , которая сама по себе представляет собой сложную систему, описывающую различные аспекты оборудования.
Вы наверняка уже видели информацию, полученную с помощью инструкции CPUID, даже не задумываясь о ее источнике.
Например, Диспетчер задач в Microsoft Windows 8.1 показывает информацию о типе процессора и некоторых других его характеристиках, получаемую с помощью инструкции CPUID:
В Linux команда «cat /proc/cpuinfo» может показать исчерпывающую информацию о процессоре, включая флаги расширения набора команд, доступные в текущей системе.
Каждое расширение имеет свой флаг, наличие которого программа должна проверить перед началом выполнения.
Вот пример информации, собранной о процессоре Intel Core i5 четвертого поколения:
CPUID предоставляет информацию о различных расширениях набора команд, доступных в процессоре, но как программное обеспечение на самом деле использует эти флаги для выбора подходящего двоичного файла на основе аппаратного обеспечения? Было бы неразумно использовать конструкцию «если-то-иначе» везде, где будут использоваться «нестандартные» операторы.
Достаточно проверить только один раз, так как за время сеанса эти характеристики не изменятся.
Linux обычно использует указатели на функции, которые используют разные инструкции для реализации одной и той же функциональности.
Хороший пример можно найти в файле арка/x86/crypto/sha1_ssse3_glue.c (источник elixir.free-electrons.com/linux/v4.13.5/source ):
Эти функции проверяют наличие определенного функционала и регистрируют соответствующую хеш-функцию.
Порядок вызова гарантирует использование наиболее эффективной реализации.
Конкретно в этом случае лучшее решение основано на Инструкции по расширению SHA-NI , но если они недоступны, используются реализации AVX или SSE.
Результаты
На графике ниже представлены результаты запуска шести различных конфигураций (два процессора и три операционные системы).Он показывает все инструкции, которые превышают 1% от общего количества за любой запуск.
«v1» означает запуск на модели Core i7 первого поколения, «v6» — шестого.
Первый вывод, который напрашивается сам собой, заключается в том, что большинство инструкций не так уж и новы.
Они скорее относятся к базовым инструкциям, добавленным в Intel 8086: перемещение, сравнение, переход и сложение.
Для более новых инструкций в скобках пишется имя расширения, в котором они были добавлены.
В списке из 28 наиболее часто используемых инструкций всего шесть более-менее новых.
Очевидно, что помимо различий, вызванных использованием разных процессоров, существуют различия между разными версиями Linux. Например, BusyBox, настроенный на более старое ядро, использует инструкцию LEAVE, которая непопулярна в других версиях ядра, и значительно реже использует инструкцию POP. Однако это не отвечает на вопрос, как программа использует новые инструкции, когда они доступны.
Для нашей цели наиболее интересными являются изменения, вызванные сменой поколений процессоров при использовании одного и того же программного стека.
Все сценарии, изученные в данной работе, представляют собой загрузку операционной системы Linux с различными параметрами ядра.
Кроме того, разные дистрибутивы могут быть скомпилированы разными версиями компилятора с использованием разных флагов.
Таким образом, двоичный код, даже скомпилированный с использованием одних и тех же источников, может отличаться.
На примере Yocto мы видим этот эффект. Yocto использует инструкции ADCX, ADOX и MULX (включенные в расширения ADX и BMI2).
Этот пример также хорошо демонстрирует скорость, с которой в программном обеспечении могут появляться новые инструкции.
Эти три инструкции были добавлены в процессор Intel Core пятого поколения, который был выпущен примерно в то же время, что и ядро Linux, используемое в Yocto. То есть поддержка новых инструкций была добавлена с появлением процессора на рынке.
И это неудивительно, поскольку спецификация новых инструкций зачастую публикуется раньше, чем их аппаратная реализация.
То есть ПО может заранее адаптировать свое поведение (интересно статья по этой теме) для нового оборудования, часто используя виртуальные платформы для отладки и тестирования.
Однако Ubuntu 16.04 с более новым ядром не использует ADX и BMI2, что говорит о том, что она была настроена по-другому.
Это может быть связано с версией или флагами компилятора, опциями ядра или набором установленных пакетов.
Изменение потока управления
Еще одна вещь, которую было интересно изучить, — какие инструкции используются для изменения потока управления.Классическое правило, описанное в не менее классическая книга Хеннесси и Паттерсона утверждает, что каждая шестая инструкция является переходом.
Однако измерения показали, что примерно одна инструкция из пяти является инструкцией, изменяющей поток управления.
Ближе к одному из шести для Yocto.
Векторные инструкции
Пожалуй, наиболее известными расширениями набора команд являются Одна инструкция и несколько данных (SIMD) или, другими словами, векторные инструкции.Векторные инструкции присутствовали в процессорах IA-32 с тех пор, как в Intel Pentium в 1997 году было добавлено расширение MMX. Теперь доступность инструкций MMX практически гарантирована.
Вы можете видеть, что некоторые из них присутствуют на графике наиболее популярных инструкций.
Затем было добавлено множество различных инструкций Streaming SIMD Extensions (SSE) и новейшие AVX, AVX2 и AVX512. Я не ожидал большого количества векторных инструкций, учитывая, что мы рассматривали загрузку операционной системы и BIOS. Однако примерно 5-6% выполненных инструкций оказались векторными.
Количество выполненных векторных инструкций, измеренное в процентах от общего количества выполненных инструкций и сгруппированное по расширению:
Первое, что бросается в глаза, это то, что Busybox на самом деле не использует векторные инструкции.
Следующее интересное наблюдение заключается в том, что при переходе с процессора первого поколения на процессор шестого поколения количество старых инструкций уменьшается, а количество новых увеличивается.
В частности, старые инструкции SSE заменяются более новыми AVX и AVX2.
Симикс
Как уже говорилось в самом начале, провести данное исследование с помощью Simics не составило труда.Очевидно, что Simics имеет доступ ко всем инструкциям, выполняющимся на всех процессорах моделируемой системы (эти эксперименты проводились на двухъядерной системе, но второе ядро не выполняло никаких инструкций во время загрузки).
Скрипты были полностью автоматизированы, включая выбор устройства, на котором установлена ОС, ввод логина и пароля в конце загрузки.
Каждый скрипт запускался один раз, поскольку повторные запуски покажут абсолютно одинаковые результаты (мы рассматриваем повторные скрипты, начиная с одного и того же места).
Заключение
Было поучительно узнать, как программные стеки адаптируются и используют новые инструкции на новых процессорах.Современные программы адаптивны и без перекомпиляции будут выполнять разный код в зависимости от используемого оборудования.
Во всех изученных сценариях один и тот же программный стек использовался в разных моделируемых системах с использованием разных инструкций в зависимости от их доступности.
Исследование является отличным примером данных, которые можно легко получить с помощью моделирования, но вряд ли можно будет собрать на реальном оборудовании.
Теги: #linux #Виртуализация #открытый исходный код #Системное программирование #обратное проектирование #виртуализация #инструментирование #simics #simics
-
Livescribe Pulse Smartpen
19 Oct, 24 -
Советы По Планированию
19 Oct, 24 -
Путь От Проекта К Продукту
19 Oct, 24 -
Как Запустить Дата-Центр На Плаву
19 Oct, 24