Présentation et exemples de mise en oeuvre de la bibliothèque Armadillo en C++

 

 

ARTICLE IDLABS

 

Mise en œuvre de la bibliothèque Armadillo en C++

 

PÉRIODE 3
(2017-2018)

 

Sommaire


 

Introduction


L’algèbre linéaire est très souvent utilisée pour le calcul scientifique. Armadillo est une bibliothèque logicielle d'algèbre linéaire pour le langage de programmation C ++.

Elle vise à fournir des calculs de base efficaces et simplifiés, tout en ayant une interface simple et facile à utiliser. Ses utilisateurs cibles sont des scientifiques et des ingénieurs.

 Armadillo est particulièrement intéressant pour les utilisateurs de Matlab* (langage de programmation utilisé à des fins de calcul numérique) qui veulent porter leur code en C++ pour optimiser la vitesse d’exécution.

En revanche, il est important de noter que Armadillo ne peut pas remplacer toutes les fonctionnalités de Matlab. Si votre code utilise une boîte à outils Matlab spécialisée, vous devrez trouver une autre bibliothèque pour compléter Armadillo ou implémenter la fonctionnalité manquante.

Présentation de Armadillo


Armadillo est une bibliothèque d'algèbre linéaire de haute qualité (matrices mathématiques) pour le langage C ++, visant un bon équilibre entre vitesse et facilité d'utilisation. Elle possède plusieurs caractéristiques :

  • fournit une syntaxe de haut niveau (API) délibérément similaire à Matlab ;

  • utile pour le développement d'algorithmes directement en C ++, ou la conversion rapide de code de recherche en environnements de production (par exemple, produits logiciels et matériels) ;

  • peut être utilisé pour l'apprentissage automatique, la reconnaissance de formes, la vision par ordinateur, le traitement du signal, la bioinformatique, les statistiques, la finance, etc ;

  • fournit des classes efficaces pour les vecteurs, les matrices et les cubes (tenseurs de 1er, 2e et 3e ordre), ainsi que 200+ fonctions associées; nombres entiers, à virgule flottante et complexes sont pris en charge ;

  • diverses décompositions matricielles sont fournies grâce à l'intégration avec LAPACK, ou l'un de ses remplacements à haute performance (par exemple multi-thread Intel MKL, ou OpenBLAS) ;

  • un évaluateur d'expression sophistiqué (basé sur la méta-programmation de modèle) combine automatiquement plusieurs opérations pour augmenter la vitesse et l'efficacité ;

  • peut utiliser automatiquement OpenMP multi-threading (parallélisation) pour accélérer les opérations coûteuses en calcul.

Installation


Armadillo utilise BLAS* (Basic Linear Algebra Subprograms) et LAPACK* (Linear Algebra Package) pour les opérations matricielles. Il est recommandé d'installer une version optimisée des bibliothèques ci-dessus sur votre système et non les implémentations de référence de Netlib*. Dans les différentes sections d’installation de cet article, je vais vous guider sur la façon d’installer BLAS et LAPACK en fonction de votre système d’exploitation.

Pour vérifier que notre installation fonctionne, nous prendrons pour exemple ce programme :

 1 #include <iostream>
 2 #include <armadillo>
 3 
 4 int main(int argc, const char **argv) {
 5     // Initialize the random generator
 6     arma::arma_rng::set_seed_random();
 7     
 8     // Create a 4x4 random matrix and print it on the screen
 9     arma::Mat<double> A = arma::randu(4,4);
10     std::cout << "A:\n" << A << "\n";
11     
12     // Multiply A with his transpose:
13     std::cout << "A * A.t() =\n";
14     std::cout << A * A.t() << "\n";
15     
16     // Access/Modify rows and columns from the array:
17     A.row(0) = A.row(1) + A.row(3);
18     A.col(3).zeros();
19     std::cout << "add rows 1 and 3, store result in row 0, also fill 4th column with zeros:\n";
20     std::cout << "A:\n" << A << "\n";
21     
22     // Create a new diagonal matrix using the main diagonal of A:
23     arma::Mat<double>B = arma::diagmat(A);
24     std::cout << "B:\n" << B << "\n";
25     
26     // Save matrices A and B:
27     A.save("A_mat.txt", arma::arma_ascii);
28     B.save("B_mat.txt", arma::arma_ascii);
29     
30     return 0;
31 }

Ce qui nous donnera comme résultat :

1 A:
 2    0.8014   0.0455   0.6745   0.0752
 3    0.8795   0.0962   0.8912   0.4586
 4    0.2497   0.6405   0.1736   0.7043
 5    0.9363   0.4145   0.9103   0.1549
 6 
 7 A * A.t() =
 8    1.1050   1.3449   0.3993   1.3949
 9    1.3449   1.7875   0.7589   1.7458
10    0.3993   0.7589   0.9987   0.7663
11    1.3949   1.7458   0.7663   1.9012
12 
13 add rows 1 and 3, store result in row 0, also fill 4th col with zeros:
14 A:
15    1.8159   0.5107   1.8016        0
16    0.8795   0.0962   0.8912        0
17    0.2497   0.6405   0.1736        0
18    0.9363   0.4145   0.9103        0
19 
20 B:
21    1.8159        0        0        0
22         0   0.0962        0        0
23         0        0   0.1736        0
24         0        0        0        0

Windows

Je considère que vous possédez la version la plus récente de Visual Studio, qui est actuellement 2017, et que vous pouvez créer, compiler et exécuter un simple code C++ depuis Visual Studio. Si le langage C++ n’est pas encore installé dans Visual Studio, vous devez installer Développement Desktop en C++ via Visual Studio Installer. Vous pouvez suivre ce tutoriel.

Concernant les bibliothèques BLAS et LAPACK, il est recommande d'utiliser Intel MKL si vous avez un processeur Intel ou OpenBlas qui fonctionne sur les processeurs Intel et AMD. Les deux alternatives fournissent des « binary packages » Windows et l'utilisation est similaire, vous devez lier les bibliothèques à votre code compilé. Nous utiliserons Intel MKL pour notre exemple.

Intel MKL peut être obtenu gratuitement à partir du lien ci-dessous, en créant un compte Intel. Après enregistrement, vous pourrez télécharger un programme d'installation qui copiera les bibliothèques, généralement dans C:\Program Files(x86)\IntelSWTools. Ouvrez IntelSWTools et cherchez le dossier mkl.

Par la suite, créer un nouveau projet Application console Visual C ++ → Win32. Veillez à sélectionner Projet vide.

Faites un clique-droit sur le dossier Source et ajouter un fichier C++. Nommez ce fichier comme vous le souhaitez.

Maintenant, ouvrez votre dossier projet. Par défaut, Visual Studio enregistre les nouveaux projets dans Documents → Visual Studio 2xxx → ProjectSur l’image ci-dessus, mon projet se nome Armadillo_demo, donc j’ouvrirai ce projet. Copier le dossier mkl dans votre projet.

Téléchargez la version stable de Armadillo depuis http://arma.sourceforge.net/download.html, au moment où j’écris cet article, c’est armadillo-8.400.0.tar.xz.

Extraire l’archive. Une fois l’archive extraite, ouvrez le dossier armadillo-xxxx et copiez le dossier include dans votre projet, comme vous l’avez fait avec mkl.

Dans votre projet, vous pouvez créer un nouveau dossier armadillo dans lequel vous viendrez copier le dossier include. Si vous avez bien suivi les instructions, votre projet devrait ressembler à ceci :

La raison pour laquelle nous avons copier tous ces dossiers dans notre projet, est d’avoir un projet générique et autonome. Pour le futur, vous serez en mesure de déplacer le projet sur un ordinateur différent qui possède Visual Studio et utiliser le projet tel qu’il est.

Si vous avez besoin de mettre à jour Armadillo, remplacez simplement les fichiers du dossier include.

Une fois ces pré-requis terminés, ouvrez le projet dans Visual Studio. Clique droit sur votre projet et sélectionnez Propriétés. Dépliez la liste C/C++ et sélectionnez Général Ajout de répertoires supplémentaires, double clique et sélectionnez Modifier. Utilisez le bouton jaune pour insérer une nouvelle ligne et recherchez mkl\include dans votre dossier de projet et appuyer sur Choisir dossier. Cliquez sur la ligne de chemin absolu et remplacez tout jusqu’à \mkl\include avec 2 points. Vous devriez avoir quelque chose semblable à ..\mkl\include.

Répétez les étapes ci-dessus pour armadillo\include. Vous devriez vous retrouver avec quelques chose comme :

Appuyez sur Ok. Ensuite, aller dans Éditeur de liens → Général → Bibliothèque d'importation supplémentaire et sélectionnez mkl\lib\intel64_win. Dans le cas où votre ordinateur est en 32 bits, utilisez mkl\lib\ia32_win. Comme précédemment, effacez la première partie du chemin et remplacez-la par deux points. Vous devriez vous retrouver avec quelque chose comme :

Appuyez sur Ok. Cliquez une nouvelle fois sur Éditeur de liens → Entrée → Dépendances supplémentaires, cliquez sur la ligne existante et selectionnez Modifier. Ajouter trois nouvelles dépendances : mkl_core.lib, mkl_sequential.lib, mkl_intel_lp64.lib:

Appuyez sur Ok de la fenêtre actuelle. Appuyez sur Appliquer et Ok de la fenêtre Propriétés.

Maintenant, copiez le code présenté précédemment (au début de l’article), dans le fichier main.cpp. Changez le compilateur à x64.

Exécutez le code en appuyant sur Déboguer → Exécuter sans débogage. Vous devriez voir quelque chose comme ceci :

Mac

Sur Mac, vérifiez d'abord que vous disposez des dernières versions de Xcode* et des outils de ligne de commande. Vous pouvez installer Xcode depuis l'application AppStore. Si vous n'avez pas installé les outils de ligne de commande, ouvrez un terminal et tapez: xcode-select –install qui vous guidera à travers le processus d’installation.

Une fois Xcode installé, ouvrez l'application et acceptez la licence (sans cela, il se peut que des erreurs étranges surviennent).

Ensuite, installez Homebrew*, qui est un gestionnaire de paquets agréable qui vous permettra d'installer divers logiciels à partir de votre Terminal. Suivez simplement les instructions d'installation de leur page Web et acceptez les valeurs par défaut.

Allez sur la page Web Armadillo et vérifiez le numéro de version de la version stable. Habituellement, Homebrew a la dernière version de Armadillo disponible. Si ce n'est pas le cas, vous pouvez installer à partir des sources.

Ouvrez un terminal et tapez : brew tap homebrew/science, puis brew info armadillo.

Si le numéro de version d'Armadillo rapporté par Homebrew, correspond à la version stable de la page web de la bibliothèque, tout va bien. Vous pouvez installer la bibliothèque avec: brew install cmake pkg-config et brew install armadillo.

Si la version Hombrew est antérieure à la dernière version stable d'Armadillo, téléchargez la bibliothèque et extrayez l'archive dans votre dossier Téléchargements. Pour compiler Armadillo à partir des sources, ouvrez un Terminal et écrivez:

  • brew install cmake pkg-config
  • cd Downloads/
    
  • cd armadillo-*
  • cmake .
  • make
  • sudo make install

À ce stade, vous devriez avoir installé Armadillo sur votre machine. Sur Mac, il n'est pas nécessaire d'installer BLAS et LAPACK, le système fournit déjà des versions accélérées de ces bibliothèques et Armadillo les utilisera.

Tout d'abord, je vais vous montrer comment compiler l'exemple du début de cet article, en utilisant le Terminal. Copiez le code dans un fichier nommé test.cpp et écrivez: clang++ test.cpp -o test -DARMA_DONT_USE_WRAPPER -framework Accelerate.

Exécutez avec : ./test , ce qui nous donne le résultat suivant :

Ensuite, ouvrez Xcode et créez un nouveau projet macOS. Donnez un nom au projet, quelque chose comme Armadillo_demo. Assurez-vous que vous sélectionnez C++ pour le langage :

Appuyez sur Suivant et acceptez les valeurs pas défauts pour les options restantes.

Dans le panneau de gauche, cliquez sur le nom du projet et sélectionnez l'onglet Paramètres de construction. Ensuite, utilisez la zone de recherche pour rechercher les chemins de recherche du compilateur pour les en-têtes et les bibliothèques. Cliquez sur les chemins de recherche d'en-tête et ajoutez /usr/local/include. Répétez l'opération pour les chemins de recherche de bibliothèque et ajoutez /usr/local/lib :

Par la suite, sélectionnez l’onglet Build Phases → Link Binary With Libraries, appuyer sur + et sélectionner Add Other. Maintenant, appuyez sur les touches Commande + Maj + G qui ouvrira une zone de texte de recherche, écrivez /user/local et appuyez sur Go. Sélectionnez le dossier lib et libarmadillo.dylib. Appuyez sur Open pour terminer :

Maintenant, copiez l'exemple du début de l’article, dans votre fichier main.cpp et appuyez sur le bouton Run :

Linux

Utilisant personnellement Ubuntu* 16.04, j’utiliserai cette version pour l’exemple.

Ouvrez un terminal et assurez vous que votre système est bien à jour : sudo apt update et sudo apt upgrade.

Ensuite, nous allons installer les pré-requis Armadillo : sudo apt install cmake libopenblas-dev liblapack-dev

En théorie, vous pouvez installer Armadillo en utilisant le gestionnaire de paquets apt, mais ce n'est pas recommandé car la version fournie par apt est vraiment ancienne. Je suggère de télécharger et d'extraire la dernière version stable de Armadillo.

Une fois que vous avez extrait Armadillo dans votre dossier Téléchargements, vous pouvez créer et installer la bibliothèque avec :

  • cd Téléchargements/

  • cd arma*

  • cmake .

  • make

  • sudo make install

 Copiez l’exemple du début dans un fichier nomé test.cpp. Vous pouvez compiler le code en utilisant : g++ test.cpp -o test -DARMA_DONT_USE_WRAPPER -lopenblas -llapack et ./test

 

Exemple d’utilisation des matrices


Configuration de base

Pour cette exemple, j’utiliserai Code::Blocks (16.01) sous Ubuntu 16.04.

Créez un nouveau projet Console sur Code::Blocks. Dans le fichier main.cpp, ajoutez la librairie armadillo : #include <armadillo>. Pour rendre l’utilisation des fonctions de Armadillo plus facile, ajoutez le namespace arma comme ceci : using namespace arma

.

On crée une matrice que l’on appelle A (mat A). endr indique à notre programme la fin d’une ligne. B est une matrice également, mais possédant des nombres a virgules, plus exactement des nombres du type float (fmat B). Et enfin, la fonction randu(x,y) permet d’initialiser une matrice aléatoire de x ligne pour y colonne.

Manipulation

 Nous avons vu comment initialiser une matrice. Maintenant, nous allons voir comment manipuler la taille d’une matrice ainsi que ces lignes et ces colonnes.

On commence par initialiser une matrice de nombres à virgules aléatoires A, possédante 4 lignes et 3 colonnes. La fonction reshape(x,y) permet de redimensionner la matrice en x lignes et y colonnes tout en conservant les données précédentes.

On veut ajouter une nouvelle ligne dans notre matrice A. On commence par créer notre ligne X aléatoire. Enfin, on appelle la fonction insert_rows(x,V) sur notre matrice A, qui permet d’ajouter un vecteur V à l’index x de la matrice.

Notez que l’index d’une matrice est semblable à l’index des tableaux. Tout ceci nous donne donc :

Sauvegarde/Chargement

Armadillo permet également de sauvegarder une matrice, ou de charger une matrice.

On peut vérifier si une matrice est vide ou non avec la fonction is_empty(). Si elle est vide, la fonction retourne 1, sinon elle retourne la matrice. On peut donner un nom à notre matrice avec la fonction print().

Également, on peut enregistrer une matrice dans un fichier, par défault, le fichier s’enregistre dans le projet actuel. Pour ce faire, il faut utiliser la fonction save(file_name, file_type)file_name prendra le nom du fichier à enregistrer, et file_type le type du fichier à enregistrer.

À l’inverse, on peut charger une matrice avec la fonction load(file_name, file_type)file_name est le nom du fichier à charger, et file_type le type du fichier à charger. Ce qui nous donne comme résultat :


Glossaire


Matlab : langage de programmation de quatrième génération, émulé par un environnement de développement du même nom, utilisé à des fins de calcul numérique.

BLAS : Basic Linear Algebra Subprograms sont un ensemble de fonctions standardisées (interface de programmation) réalisant des opérations de base de l'algèbre linéaire comme des additions de vecteurs, des produits scalaires ou des multiplications de matrices.

LAPACK : Linear Algebra Package est une bibliothèque logicielle écrite en Fortran, dédiée comme son nom l'indique à l'algèbre linéaire numérique.

Netlib : Site qui offre une collection de bibliothèques de fonctions pour le calcul numérique. La plupart des bibliothèques sont écrites en Fortran ou en C.

Fortran : Inventé en 1954, FORmula TRANslator est un langage de programmation utilisé principalement pour le calcul scientifique.

Xcode: Environnement de développement pour macOS, ainsi que pour iOS, watchOS et tvOS.

Homebrew : Logiciel de gestionnaire de paquets pour les ordinateurs d’Apple gratuit et open-source écrit en ruby. Son but est de simplifier l’installation de programme.

Ubuntu : Distribution Linux, dédiée aux ordinateurs personnels.

Références


Auteur


   Article écrit par Marciniak Marius, élève de 3ème année, dans le cadre de l’année scolaire à CampusID.



               

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *