пятница, 1 июня 2012 г.

Самостоятельная сборка Gmsh. Unix. Часть 2

Поскольку у поста "Самостоятельная сборка Gmsh. Unix" была первая часть, посвященная сборке Gmsh под Ubuntu с правами суперпользователя, еще одна часть обязательно должна быть. И она перед вами. При этом во второй части мы коснемся Unix'а с другой стороны, а именно будем рассматривать 64-битную SUSE Linux Enterprise Server 11 без графики и прав суперпользователя. Где такую можно встретить? Например, на вычислительных кластерах, или другими словами - суперкомпьютерах. Конечно, общие принципы сборки в обоих случаях не отличаются. Тем не менее, есть нюансы, вносящие некоторые изменения в этот процесс.

Конечно, самое большое отличие заключается в том, что теперь любой пакет, необходимый для сборки Gmsh'а, нужно компилировать из исходников. Никакого репозитория. Это можно считать минусом, т.к. установка из репозитория - проще не бывает, а можно - плюсом, т.к. при самостоятельной сборке вы сами выбираете версию (более свежую или, может, более стабильную на ваш взгляд).

Как и в первом случае, сборку Gmsh'а нужно начинать с CMake.

1. CMake

Обычно эта утилита уже стоит на кластерах. Обычно она не самая свежая. Однако для сборки Gmsh'а достаточно версии 2.4.1.

Итак, проверяем наличие CMake:

~$cmake --version

Моя система выдала

cmake version 2.6-patch 4

Что ж, вполне достаточно. Однако, если вы - передовик, и вам нужен свежий CMake (на момент написания поста это 2.8.8), его нужно собрать самому. Это, в общем то, совсем не сложно. Приступим.

  1. качаем исходники с cmake.org (выбираем Source distributions: Unix/Linux Source)
  2. перекидываем их на кластер
  3. распаковываем
    ~$tar -xf cmake-2.8.8.tar.gz
  4. заходим в исходники
    ~$cd cmake-2.8.8
  5. конфигурируем файлы
    ~$mdir ~/install
    Эта команда, конечно, ничего не конфигурирует, а только создает директорию install в домашней директории. Это делается затем, чтобы иметь централизованную директорию, в которую мы будем устанавливать все пакеты, собранные самостоятельно. Доступа к стандартным /usr или /usr/local все равно у нас нет, поэтому рекомендую придумать директорию (я назвал ее install - вы, как хотите) и указывать ее при конфигурировании следующим образом:
    ~$./configure --prefix=/home/user/install
  6. собираем исполняемый файл
    ~$make -j4
    Напомню, что '-j4' означает выполнение одновременно 4 инструкций, что ускоряет процесс для многоядерных архитектур.
  7. устанавливаем
    ~$make install
    На этом этапе все необходимые файлы копируются в директорию, которую мы указали на этапе конфигурирования под ключом --prefix, т.е. в данном случае в директорию ~/install. При этом сам исполняемый файл cmake лежит в директории ~/install/bin, которая создается автоматически.
Проверка версии CMake нам ничего нового не даст:

~$cmake --version
cmake version 2.6-patch 4

Для того, чтобы система увидела, где лежат собранные нами файлы, необходимо прописать путь до install/bin в переменную PATH. Это делается командой

~$export PATH=/home/user/install/bin:$PATH

Чтобы не вводить эту строку каждый раз при входе на кластер, поместите ее в файл ~/.bashrc

Ну теперь то уж все как надо:

~$cmake --version
cmake version 2.8.8

2. Gmsh

На установке Blas и Lapack я останавливаться не буду. Не представляю себе более-менее серьезный суперкомпьютер, на котором бы не было этих библиотек. Поэтому сразу переходим к сборке Gmsh. Процедура сборки, как уже было сказано, практически не отличается от случая с Ubuntu.

  1. качаем исходники с geuz.org
  2. перекидываем их на кластер
  3. распаковываем
    ~$tar -xf gmsh-x.x.x-source.tgz
  4. заходим в исходники
    ~$cd gmsh-x.x.x-source
  5. создаем директорию и залазим в нее
    ~$mkdir build; cd build
  6. конфигурируем файлы
    ~$cmake -DCMAKE_INSTALL_PREFIX=/home/user/install ..
    Как и в случае с конфигурацией CMake, мы указываем путь до директории install, в которую мы хотим установить Gmsh.
  7. собираем исполняемый файл
    ~$make -j4
  8. устанавливаем
    ~$make install
Если у вас все пройдет гладко с первого раза, то вы - счастливчик. У меня ни разу так не получилось. Поэтому ниже - некоторые проблемы, с которыми я столкнулся, и как их побороть.

Первым делом проверяем с какими опциями будет собираться Gmsh. Вернее, сначала нас интересуют только две опции - Blas и Lapack. На том кластере, которым пользовался я, были установлены Blas и Lapack в составе IntelMKL. Проблема была в том, что CMake их в упор не видел. Все попытки подсунуть ему путь до них через опции -DCMAKE_PREFIX_PATH ни к чему не привели. Осталось только одно - ковыряться с CMakeLists.txt, который лежит в gmsh-x.x.x-source, и которым руководствуется CMake во всем, в том числе и в поиске библиотек Blas/Lapack. Находим следующий отрывок:

elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
# on Linux try to find the Intel MKL without a Fortran compiler
<...>
set(MKL_LIBS_REQUIRED mkl_gf_lp64 iomp5 mkl_gnu_thread mkl_core guide pthread)
find_all_libraries(LAPACK_LIBRARIES MKL_LIBS_REQUIRED "" ${MKL_PATH})

И заменяем его на следующий:

elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
# on Linux try to find the Intel MKL without a Fortran compiler
<...>
set(MKL_LIBS_REQUIRED mkl_gf_lp64 mkl_gnu_thread mkl_core pthread)
set(EXTRA_PATH /common/intel/mkl/lib/intel64)
find_all_libraries(LAPACK_LIBRARIES_1 MKL_LIBS_REQUIRED ${EXTRA_PATH} "")
set(MKL_LIBS_REQUIRED iomp5 guide)
set(EXTRA_PATH /common/intel/Compiler/11.1/072/lib/intel64)
find_all_libraries(LAPACK_LIBRARIES_2 MKL_LIBS_REQUIRED ${EXTRA_PATH} "")
set(LAPACK_LIBRARIES)
list(APPEND LAPACK_LIBRARIES ${LAPACK_LIBRARIES_1})
list(APPEND LAPACK_LIBRARIES ${LAPACK_LIBRARIES_2})
message("LAPACK_LIBRARIES = " ${LAPACK_LIBRARIES})

Итак, что мы сделали. Мы просто-напросто разбили одну процедуру поиска библиотек на две. В исходном варианте библиотеки mkl* ищутся вместе с библиотеками iomp5, guide и pthread, которые к mkl большого отношения не имеют. И если на вашем кластере, как и у меня, эти библиотеки лежат в разных местах, велика вероятность, что все сразу они не будут найдены. Нахождение их "всех сразу" очень важно, ведь макрос find_all_libraries, написанный авторами Gmsh'а, возвращает в переменную LAPACK_LIBRARIES пути до библиотек только в том случае, если все они были найдены. Если хотя бы одна библиотека не нашлась, возвращается пустое значение. Поэтому в моем случае поиск библиотек было решено делать "порциями". При этом указывается путь, по которому CMake точно может найти библиотеки. Если бы в списке имелось 10 библиотек, и все они лежали по разным углам, пришлось бы один вызов find_all_libraries бить на 10 кусков. Затем все найденные пути засовываются в ту же LAPACK_LIBRARIES и, на всякий случай, выводится ее значение. При рассмотренном варианте поиска библиотек все они были найдены, и Gmsh благополучно сконфигурировался с поддержкой Blas и Lapack из IntelMKL.

Если вы не знаете, где лежат библиотеки Blas и Lapack, найти их можно такой командой:

~$find / -name "*blas*" > ~/findblas

При таком поиске полезные строки, показывающие, где лежит что-нибудь, связанное с Blas, будут затерты кучей сообщений о том, что вы ищете там, где не имеете прав (ведь вы ищете везде, начиная с корня). Поэтому полезно перевести вывод этих строк в какой-нибудь файл. После завершения поиска в файле findblas вы найдете, где лежит blas, ну или хотя-бы какие-то зацепки по этому поводу.

После успешной компиляции появилась новая проблема - на этапе сборки:

Linking CXX executable gmsh
/common/intel/Compiler/11.1/072/lib/intel64/libiomp5.so: undefined reference to `pthread_atfork'
collect2: выполнение ld завершилось с кодом возврата 1
make[2]: *** [gmsh] Ошибка 1
make[1]: *** [CMakeFiles/gmsh.dir/all] Ошибка 2
make: *** [all] Ошибка 2

Как известно, в Unix при линковке библиотека libsomething.a (.so) указывается в виде -lsomething.
Однако, погуглив, выяснилось, что в случае с библиотекой pthread это не всегда так. Уж не знаю, в чем тут дело, но в каком-то форуме посоветовали в командной строке вместо -lpthread написать просто -pthread, т.е. убрать букву 'l'. И это помогло. Произведя данную замену в файлах gmsh-x.x.x-source/build/CMakeFiles/gmsh.dir/link.txt и (там же) relink.txt, все собралось на ура.

Этап установки прошел без приключений и, казалось бы, Gmsh готов к использованию, однако потребовалась финальная полировка в виде прописывания путей до библиотек mkl*, iomp5, guide (которые мы указывали в исправленном варианте CMakeLists.txt) в переменную LD_LIBRARY_PATH. Делается это так же, как и для переменной PATH:

~$export LD_LIBRARY_PATH=/common/intel/mkl/lib/intel64:/common/intel/Compiler/11.1/072/lib/intel64:$LD_LIBRARY_PATH

И, конечно же, лучше всего эту строку записать в ~/.bashrc

Проверив Gmsh командой

~$gmsh --info

можно смело начинать его эксплуатировать.

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

В случае с Ubuntu кроме FLTK мы также рассматривали поддержку OpenCascade для Gmsh'a. И вот это - действительно полезная опция.

3. OpenCascade

При желании установить OCC из исходников, мы имеем два источника файлов. Первый и самый очевидный источник - сайт opencascade.org. Однако есть альтернатива. Группа особо активных пользователей OCCT организовала свое сообщество, под эгидой которого выпускает патчи, обновления и другие вкусности к стандартному ОСС. Вместе с исходниками OCCT весь этот пакет называется OCE (Opencascade Community Edition). И это действительно классная штука. Первое и одно из самых ощутимых отличий OCE от OCCT это то, что сообщество переставило процесс конфигурации Makefile'ов со стандартного GNU Autoconf на рельсы мощного и гибкого CMake. А другое отличие в том, что OCE намного быстрее реагируют на найденные баги в библиотеке, и буквально в тот же день выпускают новый патч. Так что я двумя руками за OCE. Скачать его можно отсюда. Вопросы по OCE можно задавать здесь. Библиотека весьма обширна, поэтому я дополню свой пост подробностями установки OCE на кластере как только появится такая необходимость. А пока что остановимся на этом, тем более что процесс установки довольно прост и аналогичен уже рассмотренному ранее для Gmsh'а.

Интересный момент

Уже после опубликования поста я вспомнил об одном интересном, на мой взгляд, моменте, который я случайно заметил, долго ковыряясь в файле CMakeLists.txt, чтобы добиться нормальной конфигурации Gmsh'а. Я просматривал разные версии, начиная от 2.4.2 и до последних девелоперских. И вот что я обнаружил. В CMakeLists.txt для Gmsh 2.4.2 есть такие строки:

if(MSVC)
  # remove really annoying (and stupid, and wrong) warning about
  # bool/int cast performance in Visual C++
  set(GMSH_CONFIG_PRAGMAS "#pragma warning(disable:4800)")
endif(MSVC)

Здесь всего лишь задается отключение предупреждения о bool/int преобразовании в Visual C++. Но обратите внимание на комментарий перед этим: "really annoying (and stupid, and wrong) warning" (рельно раздражающее (и глупое, и неверное) предупреждение).

Теперь перенесемся в CMakeLists.txt для более поздней версии Gmsh 2.5.1. Там похожие строки тоже есть:

if(MSVC)
  # remove annoying warning about bool/int cast performance
  set(GMSH_CONFIG_PRAGMAS "#pragma warning(disable:4800)")
  # <...>
  # плюс добавились другие команды
  # <...>
endif(MSVC)

Однако теперь в комментарии мы видим лишь "annoying warning" (раздражающее предупреждение). Что ж, повышение терпимости авторов Gmsh'а к продукту от Microsoft налицо. Такие дела.

Комментариев нет:

Отправить комментарий