45 votes

blas multithread en python/numpy

J'essaie d'implémenter un grand nombre de multiplications matrice-matrice en Python. Au départ, j'ai supposé que NumPy utiliserait automatiquement mes bibliothèques BLAS threadées puisque je l'ai construit avec ces bibliothèques. Cependant, lorsque je regarde top ou autre chose, il semble que le code n'utilise pas du tout le threading.

Avez-vous une idée de ce qui ne va pas ou de ce que je peux faire pour utiliser facilement les performances de BLAS ?

107voto

Ümit Points 9802

J'ai déjà posté ce message dans un autre fil, mais je pense qu'il convient mieux à celui-ci :

MISE À JOUR (30.07.2014) :

J'ai ré-exécuté le benchmark sur notre nouveau HPC. Le matériel et le logiciel ont changé par rapport à la configuration de la réponse originale.

Je mets les résultats dans un feuille de calcul google (contient également les résultats de la réponse originale).

Matériel informatique

Notre HPC a deux nœuds différents, l'un avec des processeurs Intel Sandy Bridge et l'autre avec les nouveaux processeurs Ivy Bridge :

Sandy (MKL, OpenBLAS, ATLAS) :

  • CPU : 2 x 16 Intel(R) Xeon(R) E2560 Sandy Bridge @ 2.00GHz (16 cœurs)
  • RAM : 64 GB

Ivy (MKL, OpenBLAS, ATLAS) :

  • CPU : 2 x 20 Intel(R) Xeon(R) E2680 V2 Ivy Bridge @ 2.80GHz (20 cœurs, avec HT = 40 cœurs)
  • RAM 256 GB

Logiciel

La pile logicielle est pour les deux nœuds la même. Au lieu de GotoBLAS2 , OpenBLAS est utilisé et il existe également un ATLAS multithread BLAS qui est fixé à 8 threads (codé en dur).

  • OS : Suse
  • Compilateur Intel : ictce-5.3.0
  • Numpy : 1.8.0
  • OpenBLAS : 0.2.6
  • ATLAS : : 3.8.4

Point de repère du produit

Le code de benchmark est le même que ci-dessous. Cependant, pour les nouvelles machines, j'ai également exécuté le benchmark pour les tailles de matrice. 5000 y 8000 .
Le tableau ci-dessous comprend les résultats du benchmark de la réponse originale (renommée : MKL --> Nehalem MKL, Netlib Blas --> Nehalem Netlib BLAS, etc)

Matrix multiplication (sizes= 1000,2000,3000,5000,8000 )

Performances à un seul fil : single threaded performance

Performances multithreads (8 threads) : multi-threaded (8 threads) performance

Threads vs taille de la matrice (Ivy Bridge MKL) : Matrix-size vs threads

Benchmark Suite

benchmark suite

Performances à un seul fil : enter image description here

Performances multithreads (8 threads) : enter image description here

Conclusion

Les nouveaux résultats du benchmark sont similaires à ceux de la réponse originale. OpenBLAS y MKL réalisent des performances de même niveau, à l'exception de Valeur propre test. Le site Valeur propre ne donne que des résultats raisonnables sur OpenBLAS en mode monofilaire . En mode multithread, les performances sont moins bonnes.

El "Tableau des tailles de matrices par rapport aux fils" montrent également que même si MKL et OpenBLAS s'adaptent généralement bien au nombre de cœurs/threads, cela dépend de la taille de la matrice. Pour les petites matrices, ajouter plus de cœurs n'améliore pas beaucoup les performances.

Il y a également une augmentation d'environ 30 % des performances par rapport à Sandy Bridge a Ivy Bridge ce qui pourrait être dû à une fréquence d'horloge plus élevée (+ 0,8 Ghz) et/ou à une meilleure architecture.


Réponse originale (04.10.2011) :

Il y a quelque temps, j'ai dû optimiser certains calculs/algorithmes d'algèbre linéaire écrits en python à l'aide de numpy et de BLAS. J'ai donc évalué/testé différentes configurations de numpy/BLAS.

Plus précisément, j'ai testé :

  • Numpy avec ATLAS
  • Numpy avec GotoBlas2 (1.13)
  • Numpy avec MKL (11.1/073)
  • Numpy avec le framework Accelerate (Mac OS X)

J'ai effectué deux benchmarks différents :

  1. produit scalaire simple de matrices de tailles différentes
  2. Suite de tests de référence que l'on peut trouver aquí .

Voici mes résultats :

Machines

Linux (MKL, ATLAS, No-MKL, GotoBlas2) :

  • OS : Ubuntu Lucid 10.4 64 Bit.
  • CPU : 2 x 4 Intel(R) Xeon(R) E5504 @ 2.00GHz (8 Cores)
  • RAM : 24 GB
  • Compilateur Intel : 11.1/073
  • Scipy : 0.8
  • Numpy : 1.5

Mac Book Pro (Cadre d'Accélération) :

  • OS : Mac OS X Snow Leopard (10.6)
  • CPU : 1 Intel Core 2 Duo 2.93 Ghz (2 Cœurs)
  • RAM : 4 GB
  • Scipy : 0.7
  • Numpy : 1.3

Serveur Mac (Cadre d'Accélération) :

  • OS : Mac OS X Snow Leopard Server (10.6)
  • CPU : 4 X Intel(R) Xeon(R) E5520 @ 2.26 Ghz (8 Cores)
  • RAM : 4 GB
  • Scipy : 0.8
  • Numpy : 1.5.1

Point de référence du produit

Code :

import numpy as np
a = np.random.random_sample((size,size))
b = np.random.random_sample((size,size))
%timeit np.dot(a,b)

Résultats :

    System        |  size = 1000  | size = 2000 | size = 3000 |
netlib BLAS       |  1350 ms      |   10900 ms  |  39200 ms   |    
ATLAS (1 CPU)     |   314 ms      |    2560 ms  |   8700 ms   |     
MKL (1 CPUs)      |   268 ms      |    2110 ms  |   7120 ms   |
MKL (2 CPUs)      |    -          |       -     |   3660 ms   |
MKL (8 CPUs)      |    39 ms      |     319 ms  |   1000 ms   |
GotoBlas2 (1 CPU) |   266 ms      |    2100 ms  |   7280 ms   |
GotoBlas2 (2 CPUs)|   139 ms      |    1009 ms  |   3690 ms   |
GotoBlas2 (8 CPUs)|    54 ms      |     389 ms  |   1250 ms   |
Mac OS X (1 CPU)  |   143 ms      |    1060 ms  |   3605 ms   |
Mac Server (1 CPU)|    92 ms      |     714 ms  |   2130 ms   |

Dot product benchmark - chart

Benchmark Suite

Code :
Pour de plus amples informations sur la suite de repères, voir aquí .

Résultats :

    System        | eigenvalues   |    svd   |   det  |   inv   |   dot   |
netlib BLAS       |  1688 ms      | 13102 ms | 438 ms | 2155 ms | 3522 ms |
ATLAS (1 CPU)     |   1210 ms     |  5897 ms | 170 ms |  560 ms |  893 ms |
MKL (1 CPUs)      |   691 ms      |  4475 ms | 141 ms |  450 ms |  736 ms |
MKL (2 CPUs)      |   552 ms      |  2718 ms |  96 ms |  267 ms |  423 ms |
MKL (8 CPUs)      |   525 ms      |  1679 ms |  60 ms |  137 ms |  197 ms |  
GotoBlas2 (1 CPU) |  2124 ms      |  4636 ms | 147 ms |  456 ms |  743 ms |
GotoBlas2 (2 CPUs)|  1560 ms      |  3278 ms | 116 ms |  295 ms |  460 ms |
GotoBlas2 (8 CPUs)|   741 ms      |  2914 ms |  82 ms |  262 ms |  192 ms |
Mac OS X (1 CPU)  |   948 ms      |  4339 ms | 151 ms |  318 ms |  566 ms |
Mac Server (1 CPU)|  1033 ms      |  3645 ms |  99 ms |  232 ms |  342 ms |

Benchmark suite - chart

Installation

Installation de MKL comprenait l'installation de la suite complète du compilateur Intel, ce qui est assez simple. Cependant, à cause de certains bugs/problèmes, la configuration et la compilation de numpy avec le support MKL ont été un peu compliquées.

GotoBlas2 est un petit paquetage qui peut être facilement compilé comme une bibliothèque partagée. Cependant, en raison d'un bogue vous devez recréer la bibliothèque partagée après l'avoir construite afin de l'utiliser avec numpy.
En plus de cela, le construire pour une plateforme à cibles multiples ne fonctionne pas pour une raison quelconque. J'ai donc dû créer un .donc pour chaque plateforme pour laquelle je veux avoir un fichier optimisé libgoto2.so fichier.

Si vous installez numpy à partir du dépôt d'Ubuntu, il installera et configurera automatiquement numpy pour utiliser ATLAS . Installation de ATLAS à partir des sources peut prendre un certain temps et nécessite quelques étapes supplémentaires (fortran, etc).

Si vous installez numpy sur une machine Mac OS X avec Fink ou Ports Mac il va soit configurer numpy pour utiliser ATLAS ou Le cadre de travail Accelerate d'Apple . Vous pouvez le vérifier en exécutant ldd sur le répertoire numpy.core._dotblas ou en appelant numpy.show_config() .

Conclusions

MKL est le plus performant, suivi de près par GotoBlas2 .
Dans le valeur propre Le test GotoBlas2 donne des résultats étonnamment plus mauvais que prévu. Je ne sais pas trop pourquoi c'est le cas.
Le cadre de travail Accelerate d'Apple est très performant, surtout en mode monofilaire (par rapport aux autres implémentations de BLAS).

Les deux sites GotoBlas2 y MKL s'adapte très bien au nombre de fils. Donc, si vous devez traiter de grandes matrices, l'exécuter sur plusieurs threads vous aidera beaucoup.

Dans tous les cas, n'utilisez pas l'option par défaut netlib blas car elle est bien trop lente pour tout travail de calcul sérieux.

Sur notre cluster, j'ai également installé ACML d'AMD et les performances étaient similaires à celles de MKL y GotoBlas2 . Je n'ai pas de chiffres précis.

Je recommande personnellement d'utiliser GotoBlas2 parce que c'est plus facile à installer et que c'est gratuit.

Si vous souhaitez coder en C++/C, consultez également les pages suivantes Eigen3 qui est censé être plus performant MKL/GotoBlas2 dans certains cas et est également assez facile à utiliser.

17voto

Sven Marnach Points 133943

Tout NumPy n'utilise pas BLAS, seules certaines fonctions -- spécifiquement dot() , vdot() y innerproduct() et plusieurs fonctions de la numpy.linalg module. Notez également que de nombreuses opérations de NumPy sont limitées par la bande passante de la mémoire pour les grands tableaux, de sorte qu'une mise en œuvre optimisée a peu de chances d'apporter une amélioration. Le fait que le multithreading puisse offrir de meilleures performances si vous êtes limité par la bande passante mémoire dépend fortement de votre matériel.

2voto

MRocklin Points 2855

Il est possible que, la multiplication matricielle étant soumise à des contraintes de mémoire, l'ajout de cœurs supplémentaires sur la même hiérarchie de mémoire ne vous apporte pas grand-chose. Bien sûr, si vous constatez une accélération substantielle lorsque vous passez à votre implémentation Fortran, alors je peux me tromper.

Je crois savoir qu'une mise en cache appropriée est bien plus importante pour ce type de problèmes que la puissance de calcul. Vraisemblablement, BLAS fait cela pour vous.

Pour un test simple, vous pouvez essayer d'installer Enthought's distribution python pour comparaison. Ils sont liés à la distribution Intel Bibliothèque du noyau mathématique qui, je crois, exploite plusieurs cœurs s'ils sont disponibles.

1voto

Lindon Points 127

Avez-vous entendu parler de MAGMA ? Algèbre matricielle sur architecture GPU et multicore http://icl.cs.utk.edu/magma/

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X