Библиотека кросс-компиляции линейной алгебры Armadillo

Мне нравится пользоваться библиотекой линейной алгебры Armadillo. Это становится чрезвычайно приятно при переносе октавных файлов.m на C++, особенно когда вам нужно использовать собственные методы.

Однако я столкнулся с проблемами, когда мне пришлось взять мою программу из родного ванильного G++ и сбросить ее на свой процессор ARM. Так как я потратил несколько часов, путаясь в своем пути, я хотел поделиться им, чтобы другие могли избежать разочарования.

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

2 ответа

Решение

Прежде всего я использую Code Sourcery в качестве моего кросс-компилятора. Я знаю, что есть другие, но я еще не дошел до перекомпиляции для другого компилятора, несмотря на то, что это должно быть применимо к любому компилятору.

Информация:

Библиотека Armadillo требует LAPACK и BLAS, но Code Sourcery не имеет компилятора Fortran. Это привело меня к f2c-версии LAPACK и BLAS.

1. Получить источники:

Сначала пойди возьми источники.

2. Кросс-компиляция CLAPACK

Как только мы получим исходные коды, мы должны сделать кросс-компиляцию для нашего конечного оборудования. В моем случае ARM7 с использованием CodeSourcery. Это действительно хорошая идея прочитать README здесь, вы действительно можете сделать все это, просто потратив время и прочитав их.

  1. Первое, что нужно сделать, это изменить файл 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
    
  2. Скомпилируйте библиотеки 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
    

    Здесь нет реальных проблем. Конечно, у него будут проблемы с выполнением, он был скомпилирован!

  3. Скомпилируйте BLAS:

    $make blaslib
    

    Как только это будет сделано, вы заметите, что у вас есть новый "blas_XXXXX.a". Это ваша кросс-скомпилированная библиотека BLAS.

  4. Компилировать 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;
Другие вопросы по тегам