Эльбрус/портирование — различия между версиями

Материал из ALT Linux Wiki
Перейти к: навигация, поиск
м (Ссылки: +эльбрус/lcc)
м (+div)
(не показаны 34 промежуточные версии 3 участников)
Строка 3: Строка 3:
 
При сборке существующих программ порой возникает ряд типичных проблем и вопросов, которые отчасти систематизированы ниже (см. тж. [[эльбрус/lcc|страничку по компилятору]]).
 
При сборке существующих программ порой возникает ряд типичных проблем и вопросов, которые отчасти систематизированы ниже (см. тж. [[эльбрус/lcc|страничку по компилятору]]).
  
 +
В [[spec|ALT RPM]] реализован макрос <tt>%e2k</tt>, рекомендуемый к применению в <tt>%ifarch</tt>.
 +
 +
<div id="configure"></div>
 
== configure: error: cannot guess build type; you must specify one ==
 
== configure: error: cannot guess build type; you must specify one ==
  
В архив исходников программы включены устаревшие копии этих файлов, [[эльбрус/upstream|поддержка e2k]] добавлена в [https://lists.gnu.org/archive/html/config-patches/2015-03/msg00000.html gnu-config] в 2015 году; достаточно обновить их вручную из свежей системной версии этого пакета:
+
В архив исходников программы включены устаревшие копии этих файлов, [[эльбрус/upstream|поддержка e2k]] добавлена в [https://lists.gnu.org/archive/html/config-patches/2015-03/msg00000.html gnu-config] в 2015 году; достаточно обновить их вручную из свежей системной версии этого пакета или {{pkg|automake}} (который с большей вероятностью окажется под рукой) либо выполнить {{cmd|autoreconf -fisv}}:
 +
 
 +
cp -aLt . -- /usr/share/automake/config.{guess,sub}
 +
 
 +
В %changelog можно добавить, например<ref>поскольку затрагивает и riscv64, и обычно aarch64</ref>:
  
  cp -at . -- /usr/share/gnu-config/config.{guess,sub}
+
  - fix build on newer arches
  
 +
<div id="64LE"></div>
 
== тесты на порядок байтов/битность ==
 
== тесты на порядок байтов/битность ==
  
Нередко попадаются программы, которые интересует только длина указателей (размер integer) и, возможно, endianness; поскольку e2k -- 64-битная LE-архитектура, ищем подстроку вроде <tt>__amd64__</tt>, читаем контекст, добавляем аналогично <tt>__e2k__</tt>.
+
Нередко попадаются программы, которые интересует только длина указателей (размер integer) и, возможно, endianness; поскольку e2k -- [[эльбрус/архитектура|64-разрядная LE-архитектура]], ищем подстроку вроде <tt>__amd64__</tt>, читаем контекст, добавляем аналогично <tt>__e2k__</tt>.
 +
 
 +
В альтовых пакетах на cmake исправления проверок битности порой выглядят примерно так<ref>либо можно задействовать <tt>%_libsuff</tt></ref>:
 +
 
 +
-%ifarch x86_64
 +
+%if "%_lib" == "lib64"
 +
  export LIB_SUFFIX=64
 +
  %endif
 +
 
 +
- fixed build on 64-bit architectures
  
Где-то будет достаточно
+
В проектах на boost порой попадается тот [https://www.gnu.org/software/autoconf-archive/ax_boost_base.html {{path|ax_boost_base.m4}}], где в тест на lib64 забит список архитектур; его придётся поправить перед запуском {{cmd|autoreconf}}<ref>или найти этот фрагмент в уже сгенерированном configure, что несколько сложней</ref> как-то так:
  
  export LIB_SUFFIX=64
+
  %ifarch %e2k ppc64le riscv64
 +
sed -i 's,aarch64,&|riscv64|ppc64le|e2k,' m4/ax_boost_base.m4
 +
%endif
  
Про невыровненный доступ к памяти на версиях архитектуры до пятой включительно ("Эльбрус-8СВ") известно, что он достаточно дорогой, поэтому про unaligned access интересующемуся коду можно сообщить, что таковой отсутствует.
+
Про невыровненный доступ к памяти на версиях архитектуры [http://ftp.altlinux.org/pub/people/mike/elbrus/docs/elbrus_prog/html/chapter6.html#reference-prefetch до пятой включительно] ("Эльбрус-8СВ"<!-- http://sdelanounas.ru/blogs/136426/ -->) известно, что он [http://ftp.altlinux.org/pub/people/mike/elbrus/docs/elbrus_prog/html/chapter9.html#id6 достаточно дорогой]; поэтому про unaligned access интересующемуся коду можно сообщить, что таковой отсутствует.
  
 
== SIMD ==
 
== SIMD ==
 
<!-- 2291, А.Т. -->
 
<!-- 2291, А.Т. -->
 
Алгоритм портирования таких программ простой:
 
Алгоритм портирования таких программ простой:
# ищем в исходниках макрос <tt>__x86_64__</tt> или на худой конец <tt>i386</tt>; если они покрывают фрагменты кода с SIMD-интринсиками (функции, имена которых начинаются на <tt>_mm_</tt>), то нам повезло;
+
# ищем в исходниках макрос <tt>__x86_64__</tt><ref>или же <tt>__amd64__</tt></ref> или на худой конец <tt>i386</tt>; если они покрывают фрагменты кода с SIMD-интринсиками (функции, имена которых начинаются на <tt>_mm_</tt>), то нам повезло;
 
# заменяем <tt>defined __x86_64__</tt> на <tt>defined __x86_64__ || defined __e2k__</tt>;
 
# заменяем <tt>defined __x86_64__</tt> на <tt>defined __x86_64__ || defined __e2k__</tt>;
# если попадается динамическая проверка наличия MMX/SSE, то указываем, что у нас всё есть до SSE4.1 (расширения системы команд SSE4.2 и AVX1 в каком-то виде также поддержаны в компиляторе, но, возможно, быстрее не будет);
+
# если попадается динамическая проверка наличия MMX/SSE, то указываем, что у нас всё есть до SSE4.1<ref>расширения системы команд SSE4.2 и AVX1 в каком-то виде также поддержаны в компиляторе, но, возможно, быстрее не будет</ref>;
# к asm-вставкам нужно творчески подходить, но чаще проще готовый generic-вариант кода использовать.  
+
# к asm-вставкам нужно творчески подходить, но чаще проще готовый generic-вариант кода использовать.
 +
{{note|несмотря на некоторую аппаратную поддержку выполнения SIMD-инструкций, по сути они реализуются в компиляторе и осмысленность задействования может отличаться от проекта к проекту -- возможно замедление, особенно на AVX* и [[эльбрус/архитектура|архитектурах]] ранее e2kv5.}}
 +
== компилятор/архитектура==
 +
Имейте в виду при выписывании <tt>#ifdef</tt>:
 +
* __e2k__  — это архитектура,
 +
* __LCC__  — компилятор.
 +
 
 +
Во-первых, lcc есть не только для e2k (привет sparc), поэтому если делается патч под особенности lcc (и, вероятнее всего, фроентенда edg), то правильнее использовать __LCC__ .
 +
 
 +
Во-вторых, со временем на e2k могут появится и другие компиляторы, например, clang через соответствующий бэкенд на основе lcc. И у них уже может не быть макроса __LCC__ , а вот __e2k__ будет.
 +
 
 +
Поэтому мне представляется правильным архитектурно-зависимые изменения в e2k заворачивать, а компиляторо-зависимые в LCC. Понятно, что в реальной жизни их отличить не всегда просто. - @bircoph
 +
<!-- А мб лучше не __LCC__ , а __LCC_MCST__ ) // ну это точно не сюда... mike@ -->
  
 +
<div id="makecontext"></div>
 
== отсутствие makecontext() ==
 
== отсутствие makecontext() ==
 
<!-- 2320, А.Ф. -->
 
<!-- 2320, А.Ф. -->
Строка 32: Строка 64:
 
# <tt>ucp.uc_stack</tt> освобождается через <tt>free()</tt>;
 
# <tt>ucp.uc_stack</tt> освобождается через <tt>free()</tt>;
 
# <tt>ucp.uc_stack</tt> переиспользуется, например, под другой контекст.
 
# <tt>ucp.uc_stack</tt> переиспользуется, например, под другой контекст.
 +
 +
<div id="cpuid"></div>
 +
== отсутствие cpuid.h ==
 +
 +
Обуславливаем соответствующий <tt>#include</tt> и обращения к функциям так:
 +
#if defined(__i386__) || defined(__x86_64__)
 +
...не забывая добавить подходящую по смыслу заглушку вместо результата функции.
 +
 +
При необходимости подробного различения процессоров "Эльбрус" обратите внимание на <tt>__builtin_cpu_is()</tt>; в [[lcc]] от 1.23.23 и 1.24.10 должны быть доступны более удобные <tt>__builtin_cpu_name()</tt> и <tt>__builtin_cpu_arch()</tt> (#4484).
 +
 +
<div id="sigsegv"></div>
 +
== SIGILL вместо ожидаемого сигнала ==
 +
Обратите внимание, что на e2k в некоторых случаях можно получить SIGILL (Illegal instruction) вместо ожидаемого SIGSEGV (Segmentation fault), SIGBUS (Bus error) или SIGFPE (Floating point exception).
 +
 +
Не тот сигнал приходит, как правило, либо в результате работы оптимизаций, либо при ручном написании кода на ассемблере или ассемблерных вставках. Если по каким-то причинам нужно поймать именно тот сигнал, который бы поймался на других архитектурах, то следует использовать режим с отключением оптимизаций, задействующих полуспекулятивный режим исполнения:
 +
* <tt>-O0</tt> -- режим компиляции без оптимизаций;
 +
* <tt>-O1</tt> -- минимальный набор оптимизаций;
 +
* <tt>-fcontrol-spec</tt> -- запрет полуспекулятивных обращений к памяти (для сохранения сингалов SIGSEGV и SIGBUS);
 +
* <tt>-fno-fp-spec</tt> -- запрет полуспекулятивных вещественных операций (для сохранения сигнала SIGFPE).
 +
 +
См. тж. [http://ftp.altlinux.org/pub/people/mike/elbrus/docs/elbrus_prog/html/chapter2.html#sigill Руководство] и {{path|posix_signals.html}}<ref>в составе {{pkg|lcc1.25-doc}} или аналогичного пакета на ОС Альт, по пути {{path|/opt/mcst/doc/posix_signals.html}} при установленной системе программирования в Эльбрус Линукс</ref>.
  
 
= Ссылки =
 
= Ссылки =
* [[эльбрус/lcc]]
+
* '''[[эльбрус/lcc]]'''
* [https://lvee.org/ru/abstracts/303 Free software porting on the Elbrus architecture]
+
* '''[http://ftp.altlinux.org/pub/people/mike/elbrus/docs/elbrus_prog/html/chapter3.html Руководство по эффективному программированию на платформе «Эльбрус». 3. Отличия в интерфейсах]'''
 +
* Доклады из серии [http://0x1.tv/Категория:ALTLinux_на_Эльбрусе ALT на e2k]:
 +
** [https://lvee.org/ru/abstracts/303 Free software porting on the Elbrus architecture]
 +
** [http://0x1.tv/20190827B Особенности портирования СПО на Эльбрус] (Андрей Савченко, OSSDEVCONF-2019)
 +
* Портирование Embox: [https://habr.com/ru/company/embox/blog/421441/], [https://habr.com/ru/company/embox/blog/447704/], [https://m.habr.com/ru/company/embox/blog/485694/]
 +
* [http://jug.ru/talks/jbreak-2016/java-on-elbrus/ Портирование Java на Эльбрус]
 +
* [https://habr.com/ru/company/jugru/blog/419155/ Портирование JS на Эльбрус]
 +
* [https://www.youtube.com/watch?v=f_hwK0zM9y8&t=29m17s Константин Трушкин: ответы на вопросы] (видео)
 +
* [https://www.youtube.com/watch?v=QC2OU5axEDI Yandex Day: 3. Компилятор для процессоров "Эльбрус". Алексей Маркин] (видео)
 +
* [https://www.youtube.com/watch?v=IeT091Ej1lU Yandex Day: 4. Прикладное программирование на Эльбрусе. Антон Аникин] (видео)
 +
* [http://habr.com/ru/company/gaijin/blog/533380/ Как мы переносили современные игры на процессор Эльбрус-8С] (Gaijin Entertainment)
 +
* [http://www.mcst.ru/files/52f220/590cd8/50136e/000004/ishin-loginov-vasilev-uskorenie_vychisleniy_s_ispolzovaniem_vysokoproizvoditelnyh_matematicheskih_i_multimediynyh_bibliotek_dlya_arhitektury_elbrus.pdf Ускорение вычислений с использованием высокопроизводительных математических и мультимедийных библиотек для архитектуры Эльбрус] ([[эльбрус/eml|EML]])
 +
 
 +
= Примечания =
 +
<references/>
  
 
{{Category navigation|title=E2K|category=E2K|sortkey=*}}
 
{{Category navigation|title=E2K|category=E2K|sortkey=*}}
 
[[Категория:devel]]
 
[[Категория:devel]]

Версия 18:55, 3 января 2021

Перенос ПО на платформу Эльбрус

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

В ALT RPM реализован макрос %e2k, рекомендуемый к применению в %ifarch.

configure: error: cannot guess build type; you must specify one

В архив исходников программы включены устаревшие копии этих файлов, поддержка e2k добавлена в gnu-config в 2015 году; достаточно обновить их вручную из свежей системной версии этого пакета или automake (который с большей вероятностью окажется под рукой) либо выполнить autoreconf -fisv:

cp -aLt . -- /usr/share/automake/config.{guess,sub}

В %changelog можно добавить, например[1]:

- fix build on newer arches

тесты на порядок байтов/битность

Нередко попадаются программы, которые интересует только длина указателей (размер integer) и, возможно, endianness; поскольку e2k -- 64-разрядная LE-архитектура, ищем подстроку вроде __amd64__, читаем контекст, добавляем аналогично __e2k__.

В альтовых пакетах на cmake исправления проверок битности порой выглядят примерно так[2]:

-%ifarch x86_64
+%if "%_lib" == "lib64"
 export LIB_SUFFIX=64
 %endif
- fixed build on 64-bit architectures

В проектах на boost порой попадается тот ax_boost_base.m4, где в тест на lib64 забит список архитектур; его придётся поправить перед запуском autoreconf[3] как-то так:

%ifarch %e2k ppc64le riscv64
sed -i 's,aarch64,&|riscv64|ppc64le|e2k,' m4/ax_boost_base.m4
%endif

Про невыровненный доступ к памяти на версиях архитектуры до пятой включительно ("Эльбрус-8СВ") известно, что он достаточно дорогой; поэтому про unaligned access интересующемуся коду можно сообщить, что таковой отсутствует.

SIMD

Алгоритм портирования таких программ простой:

  1. ищем в исходниках макрос __x86_64__[4] или на худой конец i386; если они покрывают фрагменты кода с SIMD-интринсиками (функции, имена которых начинаются на _mm_), то нам повезло;
  2. заменяем defined __x86_64__ на defined __x86_64__ || defined __e2k__;
  3. если попадается динамическая проверка наличия MMX/SSE, то указываем, что у нас всё есть до SSE4.1[5];
  4. к asm-вставкам нужно творчески подходить, но чаще проще готовый generic-вариант кода использовать.
Примечание: несмотря на некоторую аппаратную поддержку выполнения SIMD-инструкций, по сути они реализуются в компиляторе и осмысленность задействования может отличаться от проекта к проекту -- возможно замедление, особенно на AVX* и архитектурах ранее e2kv5.

компилятор/архитектура

Имейте в виду при выписывании #ifdef:

  • __e2k__ — это архитектура,
  • __LCC__ — компилятор.

Во-первых, lcc есть не только для e2k (привет sparc), поэтому если делается патч под особенности lcc (и, вероятнее всего, фроентенда edg), то правильнее использовать __LCC__ .

Во-вторых, со временем на e2k могут появится и другие компиляторы, например, clang через соответствующий бэкенд на основе lcc. И у них уже может не быть макроса __LCC__ , а вот __e2k__ будет.

Поэтому мне представляется правильным архитектурно-зависимые изменения в e2k заворачивать, а компиляторо-зависимые в LCC. Понятно, что в реальной жизни их отличить не всегда просто. - @bircoph

отсутствие makecontext()

На Эльбрусах makecontext_e2k() выделяет память под дополнительные стеки, поэтому если просто заменить s/makecontext/makecontext_e2k/, в программе может появиться утечка памяти. Нужно ещё поставить вызов freecontext_e2k() там, где выделенный для makecontext_e2k() ucp.uc_stack перестаёт использоваться под данный контекст, т.е. где:

  1. ucp.uc_stack освобождается через free();
  2. ucp.uc_stack переиспользуется, например, под другой контекст.

отсутствие cpuid.h

Обуславливаем соответствующий #include и обращения к функциям так:

#if defined(__i386__) || defined(__x86_64__)

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

При необходимости подробного различения процессоров "Эльбрус" обратите внимание на __builtin_cpu_is(); в lcc от 1.23.23 и 1.24.10 должны быть доступны более удобные __builtin_cpu_name() и __builtin_cpu_arch() (#4484).

SIGILL вместо ожидаемого сигнала

Обратите внимание, что на e2k в некоторых случаях можно получить SIGILL (Illegal instruction) вместо ожидаемого SIGSEGV (Segmentation fault), SIGBUS (Bus error) или SIGFPE (Floating point exception).

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

  • -O0 -- режим компиляции без оптимизаций;
  • -O1 -- минимальный набор оптимизаций;
  • -fcontrol-spec -- запрет полуспекулятивных обращений к памяти (для сохранения сингалов SIGSEGV и SIGBUS);
  • -fno-fp-spec -- запрет полуспекулятивных вещественных операций (для сохранения сигнала SIGFPE).

См. тж. Руководство и posix_signals.html[6].

Ссылки

Примечания

  1. поскольку затрагивает и riscv64, и обычно aarch64
  2. либо можно задействовать %_libsuff
  3. или найти этот фрагмент в уже сгенерированном configure, что несколько сложней
  4. или же __amd64__
  5. расширения системы команд SSE4.2 и AVX1 в каком-то виде также поддержаны в компиляторе, но, возможно, быстрее не будет
  6. в составе lcc1.25-doc или аналогичного пакета на ОС Альт, по пути /opt/mcst/doc/posix_signals.html при установленной системе программирования в Эльбрус Линукс