6
votes

Armadillo + Openblas plus lentement que Matlab?

Nouveau à ce sujet. Je suis en train de mettre à l'essai Armadillo + Openblas, et une simple logique de mouvement brownian géométrique de Monte-Carlo montre beaucoup plus longtemps que Matlab. Je crois que quelque chose doit être faux.

Environnement: Intel I-5 4 ​​Core, 8 Go de RAM, Vs 2012 Express, Armadillo 4.2, Openblas (binaire officiel x64) v0.2.9.rc2, p>

MATLAB prend 2 secondes pour la même logique, mais Armadillo + OB prend 12 secondes. J'ai également remarqué que le programme fonctionne sur un seul thread, mais je me suis tourné vers Openblas, car j'ai entendu parler de sa capacité multicœur. P>

Merci pour tout conseil. P>

#include <iostream>
#include <armadillo>
#include <ctime>

using namespace std;
using namespace arma;

int main()
{
clock_t start;
start = clock();
unsigned int R=100000;
vec Spre = 100*ones<vec> (R);
vec S = zeros<vec> (R);
double r = 0.03;
double Vol = 0.2;
double TTM = 5;
unsigned int T=260*TTM;
double dt = TTM/T;
for (unsigned int iT=0; iT<T; ++iT)
{
    S = Spre%exp((r-0.5*Vol*Vol)*dt + Vol*sqrt(dt)*randn(R));
    Spre = S;
}
cout << mean(S) << endl;
cout << (clock()-start) / (double) CLOCKS_PER_SEC << endl;
system("pause");
return 0;
}


4 commentaires

On dirait que la boucle ne finit pas d'appeler des fonctions de Blas, alors openblas n'est probablement pas le problème. Je soupçonne que l'optimisation et la vectorisation doivent être explicitement activées dans votre compilateur. Armadillo est une bibliothèque de modèles, et comme pour toutes les bibliothèques de modèle, l'optimisation pendant la compilation est un absolu doit . N'oubliez pas non plus que le compilateur MS VS n'est pas connu pour la robustesse ou la génération de code rapide. De loin meilleures performances peuvent être réalisées par le GCC ou compiler Intel C ++ . Vous pouvez obtenir GCC pour Windows via le MINGW Projet .


Autres mises à jour: Semble être le Randn (R) qui ralentit toute la logique. Commutée sur Zeros (R), puis terminée en moins de 2 secondes. Basculé sur Randn (R), puis encore 12 secondes ... c'est plus probablement le problème des armé-armadillo plutôt qu'un problème openblas. Très frustrant...


@MTall est passé à Eclipse + Mingw, fonctionne maintenant 52 secondes ... vraiment perdu ...


Quelles sont vos invocations de compilateur? Si vous exécutez une construction non optimisée, des choses sont tenues de rester lentes.


4 Réponses :


0
votes

Juste une suppose, mais on dirait que vous devez définir le nombre de fils à utiliser dans openblas via la variable openblas_num_threads code> d'environnement.

Essayez quelque chose comme: p>

set OPENBLAS_NUM_THREADS=4


7 commentaires

Merci pour la réponse rapide. J'ai essayé ceci: "C: \ version> Set openblas_num_threads = 4 c: \ version> Testopenblas 116.44 12.434 Appuyez sur n'importe quelle touche pour continuer..." Ai-je compris votre suggestion correctement? Il faut toujours plus de 12 secondes et fonctionne toujours comme un seul fil.


@Andreasbvb: Tout d'abord, êtes-vous en cours d'exécution de l'IDE ou de la ligne de commande? Il est probablement préférable de simplement définir la variable d'environnement une fois et pour tous pour votre système (via Propriétés du système -> Advanced-> Variables d'environnement sur la plupart des versions Windows). Assurez-vous ensuite de redémarrer votre IDE pour obtenir un environnement frais. Pendant que vous y êtes, assurez-vous de construire une construction de "version" et de ne pas courir via le débogueur. Ensuite, nous verrons quel type d'écart de performance reste.


Merci @trew hall. J'ai défini le système EV, redémarré et redémarré VS2012. Compilé à nouveau sous la libération de x64 et obtenez toujours la même chose. Maintenant, je doute que c'est ainsi que les binaires sont faits. Permettez-moi de tester Intel MKL un jour, alors j'aurai une meilleure idée.


@Andreashbvb: courez-vous via le débogueur ou propre? Vous devez appuyer sur le bouton "Exécuter sans débogage (Shift-F5)" si vous le faites à partir de la VS IDE ou du débogueur tuera vos performances.


J'ai effectivement essayé de deux manières: 1) Exécutez W / O Débogu 2) Exécuter à partir de la ligne de commande système. Aucun d'entre eux n'a contribué. J'ai testé la même logique avec la bibliothèque GPU Arrayfire et c'était très impressionnant, alors j'ai tendance à soupçonner que des fichiers binaires sont compilés sous forme de fil unique ... Cependant, 12 secondes est encore trop longue, même pour un seul fil. Merci.


@Andreashbvb - Vérifiez que l'optimisation et la vectorisation sont explicitement activées dans votre compilateur. Des bibliothèques de modèles tels que Armadillo nécessitent une optimisation.


@mTall merci pour l'entrée. Je suis un peu limitée à VS2012, alors existe-t-il un cadre que je pourrais essayer d'abord? par exemple. Les paramètres d'optimisation et de vectorisation que vous avez mentionnés. Où sont-ils à vs2012? Merci. J'ai trouvé C ++ -> Optimisation-> Optimisation complète (\ OX) mais rien d'autre plus proche ...



0
votes

Assurez-vous que vous disposez de diffuser des extensions SIMD activées lorsque vous compilez votre code. Dans Visual Studio, vérifiez votre projet Options de génération de code C / C ++ Compiler.


0 commentaires

2
votes

L'observation de la clé est que la fonction ARMADILLO EXP () est bien plus lente que MATLAB. Des frais généraux similaires sont observés dans le journal (), la POW () et SQRT ().


3 commentaires

Armadillo finit par appeler std :: exp (exp (), std :: journal (), etc., ce qui signifie que le problème de la vitesse est avec les fonctions STD :: (c.-à-d. Dans la bibliothèque C ++ standard). La manière dont ces fonctions sont implémentées dépendent de chaque système d'exploitation et / ou de compilateur. Sous Windows + vs, cela peut ne pas être aussi génial.


Merci @mTall. Je passe à Mingw64 et j'ai fini par la même performance décevante. Devrais-je essayer Linux + GCC?


Essayez d'utiliser l'option -ffast-math avec GCC, qui détend certaines des garanties de sécurité strictes. Cela accélère souvent des programmes. Sinon, vous voudrez peut-être regarder à l'aide du VDEXP () fonction de Intel MKL , qui peut être facilement interfacé avec des vecteurs et des matrices de Armadillo. Matlab utilise en interne MKL, vous obtiendrez donc la même performance que MATLAB.



3
votes

Premier, le goulot d'étranglement n'est pas exp (), bien que STD :: exp est lente. Le problème est Randn ().

sur ma machine, Randn () prend la majeure partie du temps. Et lorsque j'utilise la mise en œuvre de Randn de MKL_VSL, le coût temporel est tombé de 12 à 4s, comparable à 3s de Matlab. P>

#include <iostream>
#include <armadillo>
#include <ctime>
#include "mkl_vml.h"
#include "mkl_vsl.h"
using namespace std;
using namespace arma;

#define SEED 0
#define BRNG VSL_BRNG_MCG31
#define METHOD 0
int main()
{
clock_t start;
VSLStreamStatePtr stream;
start = clock();
vslNewStream(&stream, BRNG, SEED);
unsigned int R=100000;
vec Spre = 100*ones<vec> (R);
vec S = zeros<vec> (R);
double r = 0.03;
double Vol = 0.2;
double TTM = 5;
unsigned int T=260*TTM;
double dt = TTM/T;
double tmp = sqrt(dt);
vec tmp2=100*zeros<vec>(R);
vec tmp3=100*zeros<vec>(R);
for (unsigned int iT=0; iT<T; ++iT)
{
    vdRngGaussian(METHOD,stream, R, tmp3.memptr(), 0, 1);
    tmp2 =(r - 0.5 * Vol * Vol) * dt + Vol * tmp * tmp3;
    vdExp(R, tmp2.memptr(), tmp3.memptr());
    S = Spre%tmp3;
    Spre = S;
}
cout << mean(S) << endl;
cout << (clock()-start) / (double) CLOCKS_PER_SEC << endl;
vslDeleteStream(&stream);
//system("pause");
return 0;
}


0 commentaires