Библиотека кросс-компиляции линейной алгебры Armadillo
Мне нравится пользоваться библиотекой линейной алгебры Armadillo. Это становится чрезвычайно приятно при переносе октавных файлов.m на C++, особенно когда вам нужно использовать собственные методы.
Однако я столкнулся с проблемами, когда мне пришлось взять мою программу из родного ванильного G++ и сбросить ее на свой процессор ARM. Так как я потратил несколько часов, путаясь в своем пути, я хотел поделиться им, чтобы другие могли избежать разочарования.
Если бы кто-то еще мог добавить что-нибудь еще, мне бы это понравилось. Это был процесс, который я использовал для решения этой проблемы, и, конечно, это не единственный или лучший подход.
2 ответа
Прежде всего я использую Code Sourcery в качестве моего кросс-компилятора. Я знаю, что есть другие, но я еще не дошел до перекомпиляции для другого компилятора, несмотря на то, что это должно быть применимо к любому компилятору.
Информация:
Библиотека Armadillo требует LAPACK и BLAS, но Code Sourcery не имеет компилятора Fortran. Это привело меня к f2c-версии LAPACK и BLAS.
1. Получить источники:
Сначала пойди возьми источники.
2. Кросс-компиляция CLAPACK
Как только мы получим исходные коды, мы должны сделать кросс-компиляцию для нашего конечного оборудования. В моем случае ARM7 с использованием CodeSourcery. Это действительно хорошая идея прочитать README здесь, вы действительно можете сделать все это, просто потратив время и прочитав их.
Первое, что нужно сделать, это изменить файл make.inc, чтобы он смотрел на наш кросс-компилятор вместо обычного GCC. Обычно вы экспортируете $ $, но я обнаружил, что легче отслеживать, изменяя make-файлы.
Отредактируйте clapack-3.2.1-CMAKE/make.inc из:
CC = GCC LOADER = GCC
чтобы:
CC = [CROSS-COMPILER-GCC location] LOADER = [CROSS-COMPILER-GCC location]
Отредактируйте clapack-3.2.1-CMAKE/F2CLIBS/libf2c/Makefile из:
ld -r -x -o $*.xxx $*.o
чтобы:
[CROSS-COMPILER-LD location] -r -x -o $*.xxx $*.o
Скомпилируйте библиотеки f2c:
$make f2clib
Когда я делаю библиотеки f2c, я получаю ошибку в самом конце:
./a.out > arith.h /bin/sh: ./a.out: cannot execute binary file make[1]: *** [arith.h] Error 126 make[1]: Leaving directory `/home/matt/clapack-3.2.1-CMAKE/F2CLIBS/libf2c' make: *** [f2clib] Error 2
Здесь нет реальных проблем. Конечно, у него будут проблемы с выполнением, он был скомпилирован!
Скомпилируйте BLAS:
$make blaslib
Как только это будет сделано, вы заметите, что у вас есть новый "blas_XXXXX.a". Это ваша кросс-скомпилированная библиотека BLAS.
Компилировать LAPACK:
Make.inc укажет вам использовать
$make lapacklib
, но это приведет к попытке большего выполнения кросс-скомпилированных элементов. Вместо$cd
в каталог SRC и:$make
Это должно создать ваш новый "lapack_XXXXX.a". Теперь, когда у нас есть F2C, LAPACK и BLAS, я рекомендую разместить их где-нибудь, что имеет смысл, чтобы вы могли найти их позже. В моем случае я разместил их там, где храню свой компилятор Code Sourcery /CodeSourcery/arm-none-linux-gnueabi/usr/lib. Не забудьте переименовать эти файлы:
$cp libf2c.a [CROSS-COMPILE LIBRARY PATH]/libf2c.a $cp blas_XXXXX.a [CROSS-COMPILE LIBRARY PATH]/libblas.a $cp lapack_XXXXX.a [CROSS-COMPILE LIBRARY PATH]/liblapack.a
Помните, что они должны иметь "lib", чтобы быть распознанным позже. Снова идите вперед и сохраните их в своей кросс-скомпилированной библиотеке. Я настроил его с помощью цепочки инструментов, чтобы его было легче отделить от обычного gcc / g ++.
3. Кросс-компиляция ARMADILLO
Прежде всего, прочитайте README, всегда лучшее место для начала.
Продолжай и беги:
$cmake .
Это подготовит все и сгенерирует все, что понадобится cmake для создания нашей общей библиотеки броненосца. То, как я действовал здесь, совсем не так, как я думаю, что вы должны делать, но, поскольку я вообще не волшебник с make-файлами, я подумал, что было бы полезно показать, что я сделал, чтобы сделать кросс-компиляцию. Я изменил сгенерированные строки CMakeCache.txt следующим образом:
//CXX compiler.
CMAKE_CXX_COMPILER:FILEPATH=[CROSS-COMPILER-G++ location]
Я знаю, что где-то в этом файле CMakeCache.txt вы можете указать путь к расположению наших BLAS и LAPACK, но я изо всех сил пытался это выяснить. Вместо того, чтобы ломать голову над этой проблемой, я просто изменил "CMakeFiles/armadillo.dir/link.txt" и вручную добавил "-L [каталог кросс-компилированных BLAS/LAPACK]. Кто-то, кто более знаком с тем, как это сделать, может указать в комментарии? Затем, так как мы хотим вручную связать библиотеки BLAS и LAPACK, когда мы позже скомпилируем нашу программу (как говорит README), измените "include/armadillo_bits/config.hpp" и убедитесь, что строка, определяющая использование оболочки arma, закомментирован:
// #define ARMA_USE_WRAPPER
Осталось только сделать $cd
вернуться в корень каталога броненосца и
$make
Как только сборка завершится, вы сможете использовать Armadillo в своих программах.
4. Использование ARMADILLO в вашей программе
Чтобы использовать Armadillo в своей программе, добавьте #include <armadillo>
и пространство имен using namespace arma;
, Теперь вы должны быть в состоянии использовать все vec
а также mat
тебе хочется Обычно при использовании arma все, что вам нужно сделать во время компиляции, это связать библиотеку libarmadillo.so, но, как я уже говорил ранее, вместо этого нам нужно будет напрямую связать BLAS и LAPACK. Итак, вот мой синтаксис компилятора GCC C++:
[CROSS-COMPILER-G++] -I [CROSS-COMPILED ARMADILLO DIRECTORY]/include ...
и мой компоновщик:
[CROSS-COMPILER-G++] -L [CROSS-COMPILED LIBRARY] -o ... -llapack -lf2c -lblas
Также обратите внимание, что порядок, в котором вы связываете библиотеки, имеет значение! Сначала должен появиться lapack, затем f2c, затем blas.
На самом деле все, что вам нужно, это убедиться, что кросс-скомпилированный каталог armadillo включен, когда вы компилируете, и ваши ссылки настроены правильно, как указано выше.
Опять больше информации, тем лучше, пожалуйста, не стесняйтесь добавлять больше комментариев. То, что работало для вас, отличалось от того, что я делал, что делал неправильно, что можно сделать, чтобы улучшить.
Благодарю.
Моя конкретная настройка - кросс-версия OSX (IDE Eclipse), скомпилированная для Beaglebone Black. Однако эти инструкции должны работать для аналогичных установок.
Необязательный:
Для компиляции я использовал Mac OS X ARM GNU Linux G++ Lite 2013.11-33 Toolchain. В частности, ARM GNU / Linux G++ Lite 2013.11-33 Advanced Binary.
1. Скачать:
Как писал Мэтт, кросс-компилятор GCC не поддерживает Fortran, поэтому, если вы хотите скомпилировать LAPACK и BLAS, используйте измененную версию, найденную здесь. Я использую это clapack-3.2.1-CMAKE.tgz
2. Создайте файл кросс-компиляции cmake:
Вы можете использовать инструментальный конструктор или просто написать его. Я написал один.
Пример:
# http://www.cmake.org/Wiki/CMake_Cross_Compiling#The_toolchain_file
# REQUIRED
SET(CMAKE_SYSTEM_NAME Linux)
SET(CMAKE_SYSTEM_VERSION 1)
SET(CMAKE_SYSTEM_PROCESSOR arm)
# Added for the beaglebone
SET(FLOAT_ABI_SUFFIX "")
# specify the cross compiler
SET(CMAKE_C_COMPILER /usr/local/arm-2013.11/bin/arm-none-linux-gnueabi-gcc)
SET(CMAKE_CXX_COMPILER /usr/local/arm-2013.11/bin/arm-none-linux-gnueabi-c++)
# where is the target environment
SET(CMAKE_FIND_ROOT_PATH /usr/local/arm-2013.11)
# search for programs in the build host directories
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# for libraries and headers in the target directories
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
Примечание: я впервые делаю файл cmake. Это не гарантируется, чтобы быть правильным.
Вам нужно заменить /usr/local/arm-2013.11/bin/arm-none-linux-gnueabi-gcc на путь к выбранному вами компилятору, а также /usr/local/arm-2013.11/bin/arm- none-linux-gnueabi-C++ и /usr/local/arm-2013.11
Я решил сохранить этот файл cmake как beaglebone.cmake
3. Скомпилируйте:
Извлеките clapack-3.2.1-CMAKE.tgz и cd
компилировать: cmake -DCMAKE_TOOLCHAIN_FILE=~/Dropbox/ рабочие пространства / beaglebone / beaglebone.cmake
где ~/Dropbox/workspaces/beaglebone/beaglebone.cmake - это путь к вашему файлу cmake.
делать
По какой-то причине я получаю:
ds-mac-pro:clapack-3.2.1-CMAKE bunny$ make
Scanning dependencies of target arithchk
[ 0%] Building C object F2CLIBS/libf2c/CMakeFiles/arithchk.dir/arithchk.c.o
Linking C executable arithchk
[ 0%] Built target arithchk
[ 0%] Generating arith.h
/bin/sh: arithchk: command not found
make[2]: *** [F2CLIBS/libf2c/arith.h] Error 127
make[1]: *** [F2CLIBS/libf2c/CMakeFiles/f2c.dir/all] Error 2
make: *** [all] Error 2
Как ни странно, запуск make снова компилируется нормально:
ds-mac-pro:clapack-3.2.1-CMAKE bunny$ make
[ 0%] Built target arithchk
Scanning dependencies of target f2c
[ 0%] Building C object F2CLIBS/libf2c/CMakeFiles/f2c.dir/f77vers.c.o
[ 0%] Building C object F2CLIBS/libf2c/CMakeFiles/f2c.dir/i77vers.c.o
[ 0%] Building C object F2CLIBS/libf2c/CMakeFiles/f2c.dir/main.c.o
[ 0%] Building C object F2CLIBS/libf2c/CMakeFiles/f2c.dir/s_rnge.c.o
...
[100%] Building C object TESTING/EIG/CMakeFiles/xeigtstz.dir/xerbla.c.o
[100%] Building C object TESTING/EIG/CMakeFiles/xeigtstz.dir/xlaenv.c.o
[100%] Building C object TESTING/EIG/CMakeFiles/xeigtstz.dir/chkxer.c.o
[100%] Building C object TESTING/EIG/CMakeFiles/xeigtstz.dir/__/__/INSTALL/dsecnd.c.o
Linking C executable xeigtstz
[100%] Built target xeigtstz
4. Скопируйте (установите):
find . | grep \.a$
возвращается
./BLAS/SRC/libblas.a
./F2CLIBS/libf2c/libf2c.a
./SRC/liblapack.a
./TESTING/MATGEN/libtmglib.a
cp libblas.a libf2c.a и liblapack.a в вашу любимую папку библиотеки. Я сделал /usr/local/armadillo-4.300.3/lib
Необходимые:
1. Копия включает в себя:
Armadillo не нужно компилировать. Я не проводил никаких тестов для проверки, но похоже, что использование LAPACK и BLAS прекрасно работает с некомпилированной копией Armadillo с использованием #define в коде. Примеры кода позже.
экстракт броненосца-4.300.3.tar.gz
(необязательно) cp armadillo-4.300.3/include/ /usr/local/armadillo-4.300.3/include
и, конечно, замените /usr/local/armadillo-4.300.3/include на ваш путь выбора
2. Настройте GCC для использования Armadillo:
Я использую Eclipse с надстройкой поддержки кросс-компилятора C/C++ (меню "Справка" -> "Установить новое программное обеспечение..."), но инструкции легко преобразовать в cli или другие интегрированные среды разработки.
В окне свойств проекта: C/C++ Build -> Settings
Кросс-компилятор G++ -> Включает -> Включает пути (-I)
Нажмите +, чтобы добавить включение. Мой включаемый путь: /usr/local/armadillo-4.300.3/include
3. НЕОБЯЗАТЕЛЬНО - Настройте GCC для использования скомпилированных библиотек:
Cross G++ Linker -> Библиотеки ->
Библиотеки (-l)
LAPACK
f2c
Блас
Путь поиска в библиотеке (-L)
Нажмите +, чтобы добавить путь. Мой путь: /usr/local/armadillo-4.300.3/lib
3. Пример кода:
В файле cpp попробуйте:
#include <armadillo>
using namespace arma;
mat A = randu<mat>(4,5);
mat B = randu<mat>(4,5);
std::cout << A*B.t() << std::endl;
Успех!:D
Некоторые функции Armadillo не поддерживают напрямую и будут работать только с скомпилированными библиотеками. Вы можете проверить, что библиотеки скомпилированы и работают правильно, запустив простой тест, такой как:
#define ARMA_DONT_USE_WRAPPER
#define ARMA_USE_LAPACK
#define ARMA_USE_BLAS
#include <armadillo>
using namespace arma;
mat A = randu<mat>(5,5);
double x = det(A);
std::cout << x << std::endl;