array - numpy python 3
blas multiproceso en python/numpy (4)
Estoy tratando de implementar una gran cantidad de multiplicaciones matriciales en Python. Inicialmente, asumí que NumPy usaría automáticamente mis bibliotecas BLAS enhebradas desde que las construí contra esas bibliotecas. Sin embargo, cuando miro top o algo más, parece que el código no usa enhebrar en absoluto.
¿Alguna idea de qué es lo que está mal o qué puedo hacer para usar fácilmente el rendimiento de BLAS?
¿Has oído hablar de MAGMA? Matrix Algebra en GPU y arquitectura multinúcleo http://icl.cs.utk.edu/magma/
El proyecto MAGMA tiene como objetivo desarrollar una biblioteca de álgebra lineal densa similar a LAPACK, pero para arquitecturas heterogéneas / híbridas, comenzando con los sistemas actuales "Multicore + GPU".
Es posible que debido a que la multiplicación de Matrix x Matrix está limitada por la memoria, agregar núcleos adicionales en la misma jerarquía de memoria no le da mucho. Por supuesto, si ves una aceleración considerable cuando cambias a tu implementación de Fortran, entonces podría ser incorrecta.
Según entiendo, el almacenamiento en caché adecuado es mucho más importante para este tipo de problemas que el poder de cálculo. Es de suponer que BLAS hace esto por ti.
Para una prueba simple, puede intentar instalar Enthought''s distribución python Enthought''s para comparar. Se vinculan con la biblioteca Math Kernel de Intel, que creo que aprovecha múltiples núcleos, si está disponible.
No todo NumPy usa BLAS, solo algunas funciones, específicamente dot()
, vdot()
, y innerproduct()
y varias funciones del módulo numpy.linalg
. También tenga en cuenta que muchas operaciones de NumPy están limitadas por el ancho de banda de la memoria para matrices de gran tamaño, por lo que es improbable que una implementación optimizada proporcione ninguna mejora. Si multi-threading puede dar un mejor rendimiento si está limitado por el ancho de banda de la memoria depende en gran medida de su hardware.
Ya publiqué esto en otro hilo, pero creo que encaja mejor en este:
ACTUALIZACIÓN (30.07.2014):
Vuelvo a ejecutar el punto de referencia en nuestro nuevo HPC. Tanto el hardware como la pila de software cambiaron de la configuración en la respuesta original.
Puse los resultados en una hoja de cálculo de google (también contiene los resultados de la respuesta original).
Hardware
Nuestro HPC tiene dos nodos diferentes, uno con CPU Intel Sandy Bridge y el otro con las nuevas CPU Ivy Bridge:
Sandy (MKL, OpenBLAS, ATLAS):
- CPU : 2 x 16 Intel (R) Xeon (R) E2560 Sandy Bridge a 2.00 GHz (16 núcleos)
- RAM : 64 GB
Ivy (MKL, OpenBLAS, ATLAS):
- CPU : 2 x 20 Intel (R) Xeon (R) E2680 V2 Ivy Bridge a 2.80 GHz (20 núcleos, con HT = 40 núcleos)
- RAM : 256 GB
Software
La pila de software es para ambos nodos, el sam. En lugar de GotoBLAS2 , se usa OpenBLAS y también hay un ATLAS BLAS de subprocesos múltiples configurado en 8 subprocesos (codificado).
- OS : Suse
- Compilador de Intel : ictce-5.3.0
- Numpy: 1.8.0
- OpenBLAS: 0.2.6
- ATLAS :: 3.8.4
Punto de referencia del producto
Benchmark-code es el mismo que a continuación. Sin embargo, para las nuevas máquinas también ejecuté el punto de referencia para tamaños de matriz 5000 y 8000 .
La siguiente tabla incluye los resultados del benchmark de la respuesta original (renombrado: MKL -> Nehalem MKL, Netlib Blas -> Nehalem Netlib BLAS, etc.)
Rendimiento de rosca simple:
Rendimiento multi-hilo (8 hilos):
Hilos frente a tamaño de matriz (Ivy Bridge MKL) :
Suite Benchmark
Rendimiento de rosca simple:
Rendimiento multi hilo (8 hilos):
Conclusión
Los nuevos resultados de referencia son similares a los de la respuesta original. OpenBLAS y MKL funcionan en el mismo nivel, con la excepción de la prueba de valor propio. La prueba Eigenvalue funciona solo razonablemente bien en OpenBLAS en modo de un solo hilo . En el modo de subprocesos múltiples, el rendimiento es peor.
El "Gráfico de tamaño de matriz frente a subprocesos" también muestra que, aunque MKL y OpenBLAS generalmente se adaptan bien al número de núcleos / subprocesos, depende del tamaño de la matriz. Para matrices pequeñas, agregar más núcleos no mejorará mucho el rendimiento.
También hay aproximadamente un 30% de aumento en el rendimiento de Sandy Bridge a Ivy Bridge, que podría deberse a una mayor frecuencia de reloj (+ 0,8 Ghz) y / o una mejor arquitectura.
Respuesta original (10.04.2011):
Hace algún tiempo tuve que optimizar algunos cálculos / algoritmos de álgebra lineal que se escribieron en python usando numpy y BLAS, por lo que evalué / probé diferentes configuraciones de numpy / BLAS.
Específicamente probé:
- Numpy con ATLAS
- Numpy con GotoBlas2 (1.13)
- Numpy con MKL (11.1 / 073)
- Numpy con Accelerate Framework (Mac OS X)
Ejecuté dos puntos de referencia diferentes:
- producto punto simple de matrices con diferentes tamaños
- Suite de referencia que se puede encontrar here .
Aquí están mis resultados:
Máquinas
Linux (MKL, ATLAS, No-MKL, GotoBlas2):
- Sistema operativo : Ubuntu Lucid 10.4 64 Bit.
- CPU : 2 x 4 Intel (R) Xeon (R) E5504 a 2.00 GHz (8 núcleos)
- RAM : 24 GB
- Compilador Intel : 11.1 / 073
- Scipy : 0.8
- Numpy : 1.5
Mac Book Pro (Accelerate Framework):
- Sistema operativo : Mac OS X Snow Leopard (10.6)
- CPU : 1 Intel Core 2 Duo 2,93 Ghz (2 núcleos)
- RAM : 4 GB
- Scipy : 0.7
- Numpy : 1.3
Servidor Mac (Accelerate Framework):
- Sistema operativo : Mac OS X Snow Leopard Server (10.6)
- CPU : 4 X Intel (R) Xeon (R) E5520 a 2.26 Ghz (8 núcleos)
- RAM : 4 GB
- Scipy : 0.8
- Numpy : 1.5.1
Punto de referencia del producto
Código :
import numpy as np
a = np.random.random_sample((size,size))
b = np.random.random_sample((size,size))
%timeit np.dot(a,b)
Resultados :
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 |
Suite Benchmark
Código :
Para obtener información adicional sobre el conjunto de referencia, consulte here .
Resultados :
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 |
Instalación
La instalación de MKL incluyó la instalación de la completa Intel Compiler Suite, que es bastante sencilla. Sin embargo, debido a algunos errores / problemas de configuración y compilación de numpy con soporte MKL fue un poco molesto.
GotoBlas2 es un pequeño paquete que se puede compilar fácilmente como una biblioteca compartida. Sin embargo, debido a un bug , debe volver a crear la biblioteca compartida después de compilarla para poder usarla con numpy.
Además de este edificio, por plataforma de objetivo múltiple no funcionó por alguna razón. Así que tuve que crear un archivo .so para cada plataforma para la que quiero tener un archivo optimizado libgoto2.so .
Si instala numpy desde el repositorio de Ubuntu, automáticamente instalará y configurará numpy para usar ATLAS . Instalar ATLAS desde la fuente puede llevar algo de tiempo y requiere algunos pasos adicionales (fortran, etc.).
Si instala Numpy en una máquina Mac OS X con Fink o Mac Ports , configurará numpy para usar ATLAS o Apple''s Accelerate Framework . Puede verificar ejecutando ldd en el archivo numpy.core._dotblas o llamando a numpy.show_config () .
Conclusiones
MKL funciona mejor seguido de cerca por GotoBlas2 .
En la prueba de autovalores , GotoBlas2 tiene un rendimiento sorprendentemente peor de lo esperado. No estoy seguro de por qué este es el caso.
Apple''s Accelerate Framework funciona muy bien especialmente en modo de un solo hilo (en comparación con las otras implementaciones de BLAS).
Tanto GotoBlas2 como MKL se adaptan muy bien con el número de subprocesos. Entonces, si tiene que lidiar con matrices grandes, ejecutarlo en múltiples hilos ayudará mucho.
En cualquier caso, no use la implementación predeterminada de netlib blas porque es demasiado lenta para cualquier trabajo computacional serio.
En nuestro clúster también instalé el ACML de AMD y el rendimiento fue similar al de MKL y GotoBlas2 . No tengo ningún número difícil.
Yo personalmente recomendaría usar GotoBlas2 porque es más fácil de instalar y es gratis.
Si desea codificar en C ++ / C también consulte Eigen3 que en algunos cases se supone que superará a MKL / GotoBlas2 y también es bastante fácil de usar.