1. Введение в платформу «Эльбрус»

1.1. Предисловие

Данное руководство содержит основные материалы для обучения программированию на платформе Эльбрус.

Руководство применимо на любом варианте Linux-подобной операционной системы.

Первый блок содержит материалы, чтобы адаптировать ПО к Эльбрусу и добиться его корректной работы.

Текущая глава

содержит общие вводные данные.

Глава Работа с платформой

описывает приёмы работы на этапе компиляции программ, примеры ассемблера, отладку.

Глава Отличия в интерфейсах

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

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

Глава Введение в архитектуру «Эльбрус»

описывает теоретические основы архитектуры платформы.

Глава Анализ производительности программ

даёт инструкции о том, как оценить эффективность тех или иных преобразований над исследуемой программой.

Глава Повышение производительности

описывает техники для наиболее эффективного использования аппаратуры Эльбрус: ускорение за счёт распараллеливания исполнимого кода на уровне инструкций.

Глава Использование оптимизированных библиотек

описывает использование компонент с высокоэффективными алгоритмами для платформы.

Глава Рекомендации по оптимизации программ под архитектуру Эльбрус

описывает эмпирические правила для работы с производительностью в типовых ситуациях.

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

Интерфейсные программные соглашения

Команды микропроцессора

Планирование последовательности операций

1.2. Система программирования

Основные компоненты системы программирования:

  • lcc — оптимизирующий компилятор с языков C, C++;

  • glibc — библиотека языка Си;

  • libstdc++ — библиотека языка С++.

  • binutils — набор утилит для обращения с бинарным кодом (ar, ld, as, nm, ranlib, strip и др.);

  • gdb — отладчик.

Фундаментом программной платформы Эльбрус является оптимизирующий компилятор. Производительность достигается не только за счёт аппаратуры, но и за счёт компилятора, который строит эффективный код.

Платформы Out-Of-Order Superscalar, такие как x86 или arm, ускоряют код за счёт динамического планирования инструкций, которое выполняет аппаратура. Этот процесс практически скрыт от программиста. На данных платформах оптимизирующий компилятор не играет такой существенной роли в производительности задач, как на Эльбрусе.

Ниже перечислены основные стандарты языков, поддержанные в текущей версии lcc (1.24).

Для языка С:

  • номинальная совместимость с gcc-7.3.0;

  • стандарт C90 (ANSI/ISO 9899:1990) поддержан полностью;

  • стандарт C99 (ISO/IEC 9899:1999 as modified by Technical Corrigenda 1 through 3) поддержан полностью;

  • стандарт C11 (ISO/IEC 9899:2011) поддержан полностью, за исключением необязательного расширения _Atomic.

По умолчанию включен режим -std=gnu11 (язык C11 с gnu‑расширениями).

Для языка C++:

  • номинальная совместимость с g++-7.3.0;

  • библиотека libstdc++ от gcc-7.3.0;

  • технология zero cost exceptions (0eh);

  • стандарт C++03 (ISO/IEC 14882:2003) поддержан полностью;

  • стандарт C++11 (ISO/IEC 14882:2011) поддержан полностью;

  • стандарт C++14 (ISO/IEC 14882:2014) поддержан полностью.

По умолчанию включен режим -std=gnu++14 (язык C++14 с gnu-расширениями).

С выходом новых версий lcc повышается и версия соответствующего ему gcc. Подробное описание всех опций lcc приведено в документации, идущей вместе с компилятором:

/opt/mcst/doc/lcc_options.htm

Многие элементы тулчейна являются портом компонент GNU. Данный подход позволяет добиться максимальной совместимости со сборкой существующих программ, написанных для Linux или POSIX и тестируемых на других аппаратных платформах.

В систему программирования входит оптимизирующий компилятор lfortran.

  • номинальная совместимость с gfortran-5.5.0, есть неполная совместимость с gfortran-6.5.0 и gfortran-7.3.0;

  • стандарт Fortran 95 (final draft ISO/IEC 1539-1:1997) поддержан полностью;

  • стандарт Fortran 2003 (final draft ISO/IEC 1539-1:2004(E)) поддержка экспериментальная;

  • Стандарт Fortran 2008 (latest draft, nearly FDIS, 2010-04-27; published 2010-10-06 as ISO/IEC 1539-1:2010) поддержка экспериментальная;

  • стандарт Fortran 2018 (latest draft J3/18-007, WG5/N2146, 28th December 2017) поддержка экспериментальная.

По умолчанию включен режим -std=gnu (язык Fortran 95 с gnu-расширениями).

1.3. Опции компиляции

Основная функция оптимизирующего компилятора - преобразования исходного алгоритма программы для построения наиболее эффективного исполнимого кода. Данные преобразования называются оптимизациями. Компилятор применяет оптимизации не произвольным образом, а в составе пакетных наборов, согласованных между собой. Данные наборы также называются уровнями оптимизации.

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

1.3.1. Уровни оптимизации lcc

-O0

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

-O1

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

-O2

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

-O3

Все межпроцедурные оптимизации, возможность оптимизации в режиме «вся программа», все цикловые оптимизации.

-O4

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

Для генерации кода с привязкой к исходному тексту нужно использовать опции -O0 -g.

1.3.2. Важные для lcc опции

Опции компиляции, которые присутствуют только в lcc. Их можно добавлять независимо от основных оптимизаций -O*. Они задействуют дополнительные техники оптимизации, которые налагают ограничения на исходный код либо на процесс сборки.

Опции профилирования:

-fprofile-generate[=<path>]

генерировать компиляторный профиль;

-fprofile-use[=<file>]

использовать компиляторный профиль.

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

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

Статья с большим количеством информации о профилировании в документации на компилятор: /opt/mcst/doc/profile.html

Опции режима «вся программа»:

-fwhole

опция компиляции в режиме «вся программа». Несовместима с позиционно-независимым кодом, в частности, с динамическими библиотеками .so.

-fwhole-shared

опция компиляции в режиме «вся программа», совместимая с позиционно-независимым кодом. Требует работы с -fPIC либо -fPIE.

Режим «вся программа» позволяет выполнять межпроцедурные оптимизации. В этом режиме анализируемый контекст не ограничивается единственной функцией.

Опции необходимо подавать как при генерации объектных файлов .o, так и при линковке итогового файла (исполнимого либо динамической библиотеки).

Основным требованием для данных опций является необходимость разделять цели в сборочной системе программы, и для разных целей по-своему модифицировать флаги сборки:

  • для динамических библиотек использовать -fPIC -fwhole-shared;

  • для исполнимых файлов использовать -fwhole либо -fPIE -fwhole-shared;

Если собираемый пакет содержит одновременно исполнимые файлы и библиотеки, то глобально на уровне CFLAGS возможно выставить только сочетание -fPIC -fwhole-shared.

Примечание: Опция -fwhole работает с уровнем оптимизации -O1 и выше, а также несовместима с опцией генерации отладочной информации -g .

1.3.3. Общие опции

Ниже представлены базовые опции компилятора, характерные для всех архитектур.

Опции управления процессом компиляции:

-c

компилировать до объектного файла;

-S

записать в файл сгенерированный ассемблер;

-o<file> (-o <file>)

задать название бинарного файла;

-v (--verbose)

опция подробного вывода.

Опции компиляции целевой архитектуры:

-m32

компилировать в режиме 32-битной адресации;

-m64

компилировать в режиме 64-битной адресации;

-m128

компилировать в режиме 128-битной защищённой адресации с аппаратным контролем доступа к объектам.

В данном режиме указатель на данные и функции занимает 128 бит. В нём содержится 64-разрядный адрес объекта, его размер (не более 4 GB) и позиция указателя внутри объекта. Режим усиливает контроль памяти программ при исполнении.

Опции управления режимом компиляции:

-fPIC (-fpic)

генерировать позиционно-независимый код;

-fPIE (-fpie)

генерировать позиционно-независимый код для исполнимых файлов.

Опции управления препроцессированием:

-I <dir> (-I<dir>)

указать каталог с заголовочными файлами;

-D/-U

взвести/убрать макрос;

-E

препроцессировать;

-C

сохранить комментарии при процессировании;

-H

вывести все подхваченные хедеры при компиляции файла.

Опции управления линковкой:

-L<dir> (-L <dir>)

подать каталог с библиотеками;

-l<name> (-l <name>)

подать имя конкретной библиотеки;

-shared (--shared)

генерировать динамическую (разделяемую) библиотеку;

-static

генерировать статический исполнимый файл.

1.3.4. Все опции

Все опции компилятора перечислены здесь: /opt/mcst/doc/lcc_options.html