2013-07-23 2 views
2

Je considère l'implémentation d'un tableau comme un conteneur, et je ne suis pas sûr d'utiliser un gsl :: gsl_vector ou un std :: vector. Le conteneur doit être efficace dans l'espace mais également très rapide lors de l'appel des valeurs. Le conteneur sera référencé en permanence dans le programme principal pour, par exemple, entrer des valeurs dans des fonctions tensorielles, entre autres choses. J'appelle du conteneur littéralement des milliards de fois. Le gsl_vector est pratique car il me permettra d'utiliser les bibliothèques gsl BLAS à l'occasion, et l'appel gsl_vector_get(...) est très efficace. D'autre part, je suis capable d'obtenir presque la même vitesse d'appels en utilisant des itérateurs stl, et le vecteur stl a une interface que je trouve tout à fait naturelle.gsl :: gsl_vector vs std :: surcharges vectorielles et efficacité

Y at-il des frais généraux de mémoire/problèmes d'efficacité que je devrais être au courant de ce que j'ai négligé dans le code ci-dessus?

En outre, j'utilise une implémentation std::vector<gsl_vector*> pour le moment, et un itérateur pour parcourir le vecteur std ::. Serait-il plus intelligent d'utiliser une gsl_matrix ici? L'idée serait d'utiliser gsl_vector_views pour obtenir le bon vecteur, plutôt que l'itérateur. Serait-ce plus efficace?

Répondre

2

D'une part, il est vrai qu'avec gsl_vector vous pouvez utiliser gsl BLAS ce qui est un gros avantage. D'un autre côté, il est également vrai que l'interface gsl est assez lourde pour un programmeur C++. Donc, aucune des solutions n'est vraiment satisfaisante. Cependant, je préfère fortement l'utilisation de gsl_matrix car

(i) avec un peu d'effort, vous pouvez écrire une petite classe wrapper qui améliore l'interface C encombrante de gsl_matrix (il est beaucoup plus difficile de gérer l'absence de bibliothèque BLAS dans std ::vecteur). (Ii) gsl_matrix est juste un wrapper à un tableau continu unidimensionnel où m(i,j) = array[i*N + j] pour la matrice carrée (même si la matrice n'est pas carrée, gsl_matrix l'implémente toujours comme un tableau unidimensionnel). Dans std::vector<gsl_vector*>, vous devrez "malloc" chaque gsl_vector individuellement, ce qui implique que la mémoire ne sera pas contiguë. Ceci frappe la performance parce que le manque de "localisation spatiale" dans l'allocation de mémoire augmente généralement considérablement les échecs de mémoire cache.

Si vous avez le choix d'utiliser une solution complètement différente, je mettrait en œuvre le calcul du tenseur en utilisant des classes StaticMatrix ou DynamicMatrix dans Blaze lib

Blaze

Pourquoi Blaze?

(i) L'interface StaticMatrix ou DynamicMatrix est bien meilleure que std::vector<gsl_vector*> ou gsl_matrix

(ii) est le plus rapide Blaze BLAS lib disponibles en C++. Il est plus rapide que gsl si vous avez Intel MKL disponible (rappelez-vous que Intel MKL est plus rapide que gsl BLAS). Pourquoi ça? Parce que Blaze utilise une nouvelle technique appelée "Smart Expression Template". Fondamentalement, les chercheurs en Allemagne ont montré dans une série d'articles paper 1paper 2 que la technique "Expression Template", qui est la technique standard dans de nombreuses bibliothèques BLAS C++, est terrible pour les opérations matricielles (opérations BLAS 3) parce que le compilateur ne peut pas être plus intelligent que code de bas niveau. Cependant, "Expression Template" peut être utilisé comme un wrapper plus intelligent pour les bibliothèques BLAS de bas niveau comme Intel MKL. Donc, ils créent une technique "Smart Expression Template" qui est juste une enveloppe à votre choix de blas lib bas niveau.Leurs points de référence sont étonnants

benchmark

+0

drôle comment les résultats de référence présentés par le projet X, il arrive que X sort le plus rapide. Les gens d'Eigen sont également catégoriques sur le fait que leur code est bon, et Armadillo a changé/amélioré depuis la version utilisée dans le benchmark. Votre kilométrage peut varier. –

+0

Il est beaucoup plus rapide que Armadillo (vous pouvez voir le lien de référence) parce que comme je l'ai dit blaze utiliser "Smart Expression Template". Signification: Blaze utilise des templates uniquement comme un wrapper pour les bibliothèques blas de code c de bas niveau (comme Intel mkl). Armadillo essaie de calculer l'opération matricielle en déroulant la boucle au moment de la compilation (la forme originale du "template d'expression") et les documents que j'ai liés montrent que c'est loin de la solution optimale. . Je pense que Eigen utilise une implémentation mixte, mais Blaze est aussi plus rapide qu'Eigen. –

+0

Oui. Le benchmark peut varier. Mais l'idée que "Expression Template" ne peut pas battre intel MKL (ou tout autre code bas niveau c) est très solide. Utiliser des templates comme un wrapper pour un code bas niveau optimisé est beaucoup mieux que de se fier au compilateur pour faire 100% du travail. Je pense que tous les BLAS C++ convergent sur cela, ce qui est l'idée derrière "Smart Expression Templates". –

Questions connexes