9
votes

C ++ Solution efficace de la mémoire pour le système algébrique linéaire AX = B

J'utilise des liaisons de bibliothèque numérique pour Boost Ublas pour résoudre un système linéaire simple. L'option suivante fonctionne bien, sauf qu'il s'agit de la manipulation de matrices A (m x m) pour relativement Petit 'M'.

En pratique, j'ai une matrice beaucoup plus grande avec dimension m = 10 ^ 6 (jusqu'à 10 ^ 7).
Existe-t-il une approche C ++ existante pour la résolution de l'AX = B qui utilise efficacement la mémoire. P>

#include<boost/numeric/ublas/matrix.hpp>
#include<boost/numeric/ublas/io.hpp>
#include<boost/numeric/bindings/traits/ublas_matrix.hpp>
#include<boost/numeric/bindings/lapack/gesv.hpp>
#include <boost/numeric/bindings/traits/ublas_vector2.hpp>

// compileable with this command


//g++ -I/home/foolb/.boost/include/boost-1_38 -I/home/foolb/.boostnumbind/include/boost-numeric-bindings solve_Axb_byhand.cc -o solve_Axb_byhand -llapack


namespace ublas = boost::numeric::ublas;
namespace lapack= boost::numeric::bindings::lapack;


int main()
{
    ublas::matrix<float,ublas::column_major> A(3,3);
    ublas::vector<float> b(3);


    for(unsigned i=0;i < A.size1();i++)
        for(unsigned j =0;j < A.size2();j++)
        {
            std::cout << "enter element "<<i << j << std::endl;
            std::cin >> A(i,j);
        }

    std::cout << A << std::endl;

    b(0) = 21; b(1) = 1; b(2) = 17;

    lapack::gesv(A,b);

    std::cout << b << std::endl;


    return 0;
}


1 commentaires

Soulignez l'évidence, une matrice que la matrice de taille est de 4x10 ^ 12 à 4x10 ^ 14 octets, ou 4 à 400 téraoctets pour une seule matrice seule. (À moins que, comme indiqué ci-dessous, ses stars)


6 Réponses :



3
votes

Pas sûr des implémentations C ++, mais il y a plusieurs choses que vous pouvez faire si la mémoire est un problème en fonction du type de matrice que vous utilisez:

  1. Si votre matrice est rare ou bandée, vous pouvez utiliser un solveur de plaide ou de bande passante. Ceux-ci ne stockent pas zéro éléments en dehors de la bande.
  2. Vous pouvez utiliser un solveur de front d'onde, qui stocke la matrice sur disque et apporte uniquement le front d'onde matricielle pour la décomposition.
  3. Vous pouvez éviter de résoudre complètement la matrice et utilisez des méthodes itératives.
  4. Vous pouvez essayer les méthodes de solution de Monte Carlo.

2 commentaires

@duffymo: merci. J'ai examiné la mise en œuvre de l'approche itérative en C ++, mais ils ont toujours besoin de la stocker dans matrice. freenet-homepage.de/guwi17/ublas/examples Si je me trompe, faites Vous connaissez une implémentation mem efficace en C ++ pour itératif?


Correct, bulgaRatbra. J'aurais dû me souvenir de ça. J'éditionnerais des algorithmes parallèles, car le problème de la partition de l'œuvre sur les processeurs N et de la tricoter pour obtenir le résultat est germe au problème de la déplaçant temporairement sur le disque.



6
votes

Je suppose que votre matrice est dense. Si cela est rare, vous pouvez trouver de nombreux algorithmes spécialisés comme indiqué par Deusaduro et Duffyme .

Si vous n'avez pas de grappe (assez large) à votre disposition, vous souhaitez regarder des algorithmes hors de noyau. Scalapack a quelques solveurs extrêmes dans le cadre de son Paquet prototype , voir la documentation ICI et Google pour plus de détails. Recherche sur le Web pour les solvateurs / forfaits LU / (Matrix) «Out-of-Core) vous donnera des liens vers une richesse d'algorithmes et d'outils supplémentaires. Je ne suis pas un expert sur ceux.

Pour ce problème, la plupart des gens utiliseraient une cluster. Le colis que vous trouverez sur presque n'importe quel groupe est Scalapack, encore une fois. De plus, il existe généralement de nombreux autres emballages sur le cluster typique, de sorte que vous pouvez choisir et choisir ce qui convient à votre problème (exemples ICI et ici ).

Avant de commencer à coder, vous voulez probablement vérifier rapidement combien de temps il faudra pour résoudre votre problème. Un solveur typique prend environ O (3 * N ^ 3) (N est la dimension de la matrice). Si N = 100000, vous regardez donc 3000000 gflops. En supposant que votre solveur en mémoire soit 10 gflops / s par noyau, vous envisagez 3 1/2 jours sur un seul noyau. Au fur et à mesure que les algorithmes d'algorithmes, augmentent le nombre de cœurs devraient réduire le temps proche de linéairement. Au-dessus de cela vient les E / S.


1 commentaires

CAVEAT: Le dessus O (3 * N ^ 3) suppose que vous utilisez des nombres complexes. Pour les nombres réels, divisez tout par 6, c'est-à-dire quelque part autour de O (0,5 * N ^ 3).



3
votes

Jetez un coup d'œil au Liste des logiciels librement disponibles pour la solution de problèmes d'algèbre linéaire , compilés par Jack Dongarra et Hatem Ltaief.

Je pense que pour la taille du problème que vous regardez, vous avez probablement besoin d'un algorithme itératif. Si vous ne voulez pas stocker la matrice A dans un format clairsemé, vous pouvez utiliser une implémentation sans matrice. Les algorithmes itératifs n'ont généralement pas besoin d'accéder à des entrées individuelles de la matrice A, ils n'ont besoin que de calculer des produits de matrice-vectoriels AV (et parfois un ^ t v, le produit de la matrice transposée avec le vecteur). Donc, si la bibliothèque est bien conçue, elle devrait suffire si vous le transmettez une classe qui sait faire des produits de matrice-vectoriels.


0 commentaires

14
votes

Réponse courte: N'utilisez pas Boost's LAPACK Liaisons, celles-ci ont été conçues pour des matrices denses, Pas de matrices rares, utilisez UMFPACK à la place.

Réponse longue: UMFPACK est l'une des meilleures bibliothèques pour la résolution de l'AX = B lorsque A est grand et clairsemé.


0 commentaires