Question

D'après mon expérience, .NET est 2 à 3 fois plus lent que le code natif.(J'ai implémenté L-BFGS pour l'optimisation multivariée).

J'ai retracé les publicités sur stackoverflow jusqu'àhttp://www.centerspace.net/products/

la vitesse est vraiment incroyable, la vitesse est proche du code natif.Comment peuvent-ils faire ça?Ils ont dit que:

Q.NMath est-il « pur » .NET ?

UN.La réponse dépend quelque peu de votre définition de « .NET pur ».NMath est écrit en C#, plus une petite couche Managed C++.Cependant, pour de meilleures performances des opérations de base d'algèbre linéaire, NMath s'appuie sur la bibliothèque native Intel Math Kernel (incluse avec NMath).Mais il n'y a pas de composants COM, pas de DLL, juste des assemblys .NET.De plus, toute la mémoire allouée dans la couche Managed C++ et utilisée par le code natif est allouée à partir du tas géré.

Quelqu'un peut-il m'expliquer davantage ?

Était-ce utile?

La solution

Le point sur le C ++ / CLI est correcte. Pour compléter le tableau, à seulement deux points intéressants supplémentaires:

  • .NET gestion de la mémoire (garbage collector) est évidemment pas le problème ici, comme NMath dépend encore de ce

  • L'avantage de la performance est effectivement fourni par Intel MKL, qui offre des implémentations extrêmement optimisés pour de nombreux processeurs. De mon point de vue, c'est le point crucial. L'utilisation straight-forward, naiv code C / C ++ vous donnera pas nécessairement des performances supérieures sur C # /. NET, il est parfois encore pire. Cependant C ++ / CLI vous permet d'exploiter toutes les options d'optimisation "sales".

Autres conseils

  

Comment peuvent-ils le faire?

Comme la plupart des bibliothèques numériques pour .NET, NMath est un peu plus d'une enveloppe sur un processeur Intel MKL intégré dans l'ensemble de .NET, probablement en lien avec C ++ / CLI pour créer un de montage mixte. Vous avez probablement benchmarkée ces bits qui ne sont pas réellement écrites dans .NET.

Les F # .NET Journal des articles Bibliothèques numériques: fonctions spéciales, numéros d'interpolation et aléatoire (16e Mars 2008) et bibliothèques numériques: algèbre linéaire et des méthodes spectrales (16e Avril 2008) ont testé un peu de fonctionnalité et NMath était en fait le plus lent de toutes les bibliothèques commerciales. Leur PRNG était plus lent que tous les autres et 50% plus lent que la bibliothèque Math.NET libre, certaines fonctionnalités de base était manquante (par exemple la capacité de calculer Gamma(-0.5)) et d'autres fonctionnalités de base (les fonctions liées à Gamma qu'ils ont fait de fournir) a été rompu. Les deux Extreme optimisation et Bluebit ont battu NMath à l'indice de référence eigensolver. NMath n'a même pas fourni une transformée de Fourier à l'époque.

Encore plus surprenant, les écarts de performance sont parfois énormes. La bibliothèque numérique commerciale la plus chère que nous avons testé (IMSL) a été plus de 500 × plus lent que la bibliothèque FFTW libre à l'indice de référence FFT et pas des bibliothèques fait usage de plusieurs cœurs à l'époque.

En fait, ce sont précisément la mauvaise qualité de ces bibliothèques qui nous a encouragés à commercialiser notre propre F # pour la bibliothèque (qui est 100% pur F # code) de Numerics.

Je suis l'un des principaux développeurs de ILNumerics . Donc, je suis partial, évidemment;) Mais nous sommes plus sur nos divulguais internes, donc je vais vous donner quelques indications sur nos vitesse « secrets ».

Tout dépend de la façon dont les ressources du système sont utilisées! Si vous êtes sur la vitesse pure et la nécessité de gérer de grands réseaux, vous assurez-vous de (par ordre d'importance, le plus important en premier)

  1. Gérer votre mémoire appropriée! gestion de la mémoire « Naive » conduira à une mauvaise performance, car il met l'accent sur le GC mal, provoque la fragmentation de la mémoire et dégrade la localisation de mémoire (d'où la performance du cache). Dans un environnement collecté des déchets comme .NET, cela revient à empêcher des allocations de mémoire fréquentes. En ILNumerics, nous avons mis en place un pool de mémoire haute performance pour archieve cet objectif (et l'élimination déterministe des réseaux temporaires pour obtenir une belle syntaxe confortable sans sémantique de fonction maladroits).

  2. Utiliser le parallélisme! Cette cible à la fois: le parallélisme et le parallélisme niveau de données de niveau fil. noyaux multiples sont utilisés en vissant les pièces à forte intensité de calcul du calcul. Sur X86 / X64 processeurs extensions SIMD / multimédias comme SSE.XX et AVX permettent une vectorisation petite mais efficace. Ils ne sont pas directement adressables par les langages .NET en cours. Et c'est la seule raison, pourquoi MKL peut est encore plus rapide que le code .NET « pur ». (Mais des solutions sont déjà en hausse.)

  3. Pour archieve vitesse des langues hautement optimisées comme Fortran et C ++, les mêmes optimisations doivent s'appliquer à votre code comme fait pour eux. C # offre l'option ne le faire.

Remarque, ces précautions doivent être suivies dans cet ordre! Il n'a pas de sens de se soucier des extensions SSE ou même la suppression de contrôle lié, si le goulot d'étranglement est la bande passante de la mémoire et le processeur (s) passent plus le temps d'attente pour les nouvelles données. En outre, pour de nombreuses opérations simples, il ne paie même pas d'investir d'énormes efforts pour Archieve l'échelle minuscule dernier à des performances de pointe! Prenons l'exemple commun de la fonction LAPACK DAXPY. Il ajoute les éléments d'un vecteur X à l'élément correspondant d'un autre vecteur Y. Si cela est fait pour la première fois, toute la mémoire pour X et Y devra obtenir extraite de la mémoire principale. Il y a peu à rien que vous pouvez faire à ce sujet. Et la mémoire est le goulot d'étranglement! Ainsi, peu importe si l'ajout à la fin se fait de la manière naïve en C #

for (int i = 0; i < C.Length; i++) {
    C[i] = X[i] + Y[i]; 
}

ou fait en utilisant des stratégies de vectorisation - il faudra attendre la mémoire!

Je sais, cette réponse ne en quelque sorte «sur les réponses de la question, puisque la plupart de ces stratégies ne sont actuellement pas utilisées du produit mentionné (encore?). En suivant thoses des points, vous éventuellement finir avec beaucoup de meilleures performances que chaque implémentation naïve dans une langue « maternelle ».

Si vous êtes intéressé, vous pourriez divulguer votre implémentation de L-BFGS? Je serai heureux de le convertir en ILNumerics et afficher les résultats de la comparaison et je suis sûr, d'autres bibliothèques énumérées ici aimeraient suivre. (?)

J'ai posté un blog article répondre à cette question .

La clé est C ++ / CLI . Il vous permet de compiler du code C ++ dans un ensemble .NET managé.

Aujourd'hui, il est courant dans l'industrie de créer des bibliothèques mixtes .Net/natives afin de tirer parti des avantages des deux plates-formes pour l'optimisation des performances.Non seulement NMath, mais de nombreuses bibliothèques commerciales et gratuites avec une interface .net fonctionnent ainsi.Par exemple:Math.NET Numériques, dnAnalytics, Optimisation Extrême, FinMaths et plein d'autres.L'intégration avec MKL est extrêmement populaire pour les bibliothèques numériques .net, et la plupart d'entre elles utilisent simplement l'assemblage Managed C++ comme niveau intermédiaire.Mais cette solution présente un certain nombre d'inconvénients :

  1. Intel MKL est un logiciel propriétaire et il est un peu cher.Mais certaines bibliothèques comme dnAnalytics proposent un remplacement gratuit de la fonctionnalité MKL par du code .net pur.Bien sûr, c'est beaucoup plus lent, mais c'est gratuit et entièrement fonctionnel.

  2. Cela réduit votre compatibilité, vous devez disposer de DLL de noyau C++ gérées lourdement pour les modes 32 bits et 64 bits.

  3. Les appels gérés en natif nécessitent un marshaling qui ralentit les performances des opérations rapides et fréquemment appelées telles que Gamma ou NormalCDF.

Deux derniers problèmes résolus dans la bibliothèque RTMath FinMath.Je ne sais pas vraiment comment ils l'ont fait, mais ils fournissent une seule DLL .net pure qui a été compilée pour n'importe quelle plate-forme CPU et prend en charge 32 bits et 64 bits.De plus, je n'ai constaté aucune dégradation des performances par rapport à MKL lorsque je dois appeler NormalCDF des milliards de fois.

Depuis le (natif) Intel MKL fait le calcul, vous êtes en train de ne pas faire le calcul en code managé. Vous êtes simplement en utilisant le gestionnaire de mémoire de .Net, de sorte que les résultats sont facilement utilisés par le code .Net.

J'ai appris le commentaire de forme plus @Darin Dimitrov à sa réponse et le commentaire de @Trevor Misfeldt à @ commentaire des Darin. Par conséquent l'affichage comme une réponse, pour les futurs lecteurs.

NMath utilise P / Invoke ou C ++ / CLI pour appeler Intel Math Kernel Library fonctions natives qui est l'endroit où les calculs les plus intenses sont faits et qui est pourquoi il est si rapide.

temps est passé méthodes de décomposition à l'intérieur de MKL d'Intel . Aucune copie des données est nécessaire , que ce soit. Alors, ce n'est pas une question de savoir si la CLI est rapide ou non. Il est sur l'endroit où l'exécution se passe .

Aussi @ blog de Paul est aussi une bonne lecture. Voici le résumé.

C # est rapide, allocation de mémoire n'est pas. Réutiliser les variables telles que ref ou sur les paramètres , au lieu de retourner de nouvelles variables de méthodes. Une nouvelle variable allouer consomme de la mémoire et ralentit l'exécution. @Haymo Kutschbach a bien expliqué cela.

Si la précision n'est pas nécessaire, le gain de performance en passant de deux à simple précision est considérable (sans parler de la mémoire d'économie pour le stockage de données).

Pour de nombreux calculs courts, pour appeler une routine C ++ / cli de C #, épinglant tous les pointeurs de données allouées dans l'espace géré, puis appeler la bibliothèque Intel est généralement mieux que d'utiliser P / Invoke pour appeler la bibliothèque directement à partir de C # , en raison du coût de marshaling les données. Comme l'a mentionné @Haymo Kutschbach dans les commentaires, pour les types blittables cependant pas de différence entre C ++ / CLI et C #. Les tableaux de types et les classes blittables qui ne contiennent que des membres blittables sont épinglés au lieu de copier pendant marshaling. Reportez-vous https://msdn.microsoft.com/en -us / bibliothèque / 75dwhxf7 (v = vs.110) .aspx pour une liste de types blittables et non blittables.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top