Solución:
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 (contiene también los resultados de la respuesta original).
Hardware
Nuestro HPC tiene dos nodos diferentes, uno con CPU Intel Sandy Bridge y otro con las CPU Ivy Bridge más nuevas:
Arenoso (MKL, OpenBLAS, ATLAS):
- UPC: 2 x 16 Intel (R) Xeon (R) E2560 Sandy Bridge a 2,00 GHz (16 núcleos)
- RAM: 64 GB
Hiedra (MKL, OpenBLAS, ATLAS):
- UPC: 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, sam. En lugar de GotoBLAS2, OpenBLAS se utiliza y también hay un ATLAS multiproceso BLAS que se establece en 8 subprocesos (codificado).
- SO: Suse
- Compilador Intel: ictce-5.3.0
- Numpy: 1.8.0
- OpenBLAS: 0.2.6
- ATLAS:: 3.8.4
Benchmark de producto escalar
El código de referencia es el mismo que se muestra 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 de referencia de la respuesta original (renombrado: MKL -> Nehalem MKL, Netlib Blas -> Nehalem Netlib BLAS, etc.)
Rendimiento de un solo hilo:
Rendimiento de subprocesos múltiples (8 subprocesos):
Hilos frente al tamaño de la matriz (Ivy Bridge MKL):
Suite Benchmark
Rendimiento de un solo hilo:
Rendimiento de subprocesos múltiples (8 subprocesos):
Conclusión
Los nuevos resultados de referencia son similares a los de la respuesta original. OpenBLAS y MKL desempeñarse en el mismo nivel, con la excepción de Valor propio prueba. los Valor propio La prueba funciona solo razonablemente bien en OpenBLAS en modo de un solo hilo. En el modo de subprocesos múltiples, el rendimiento es peor.
los “Gráfico de tamaño de matriz frente a subprocesos” También muestran que aunque MKL y OpenBLAS generalmente escalan bien con el 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 para Ivy Bridge lo que puede deberse a una mayor frecuencia de reloj (+ 0,8 Ghz) y / o una mejor arquitectura.
Respuesta original (04.10.2011):
Hace algún tiempo tuve que optimizar algunos cálculos / algoritmos de álgebra lineal que se escribieron en Python usando numpy y BLAS, así que comparé / 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 escalar simple de matrices con diferentes tamaños
- Paquete de referencia que se puede encontrar aquí.
Aquí están mis resultados:
Máquinas
Linux (MKL, ATLAS, No-MKL, GotoBlas2):
- SO: Ubuntu Lucid 10.4 de 64 bits.
- UPC: 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
Macbook Pro (Acelerar marco):
- SO: Mac OS X Snow Leopard (10.6)
- UPC: 1 Intel Core 2 Duo 2,93 Ghz (2 núcleos)
- RAM: 4 GB
- Scipy: 0,7
- Numpy: 1.3
Servidor Mac (Acelerar marco):
- SO: Servidor Mac OS X Snow Leopard (10.6)
- UPC: 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 de producto escalar
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 la suite de referencia, consulte aquí.
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
Instalación de MKL incluyó la instalación de Intel Compiler Suite completa, que es bastante sencillo. Sin embargo, debido a algunos errores / problemas, configurar y compilar numpy con soporte MKL fue un poco complicado.
GotoBlas2 es un pequeño paquete que se puede compilar fácilmente como una biblioteca compartida. Sin embargo, debido a un error, debe volver a crear la biblioteca compartida después de construirla para poder usarla con numpy.
Además de esta construcción, para múltiples plataformas de destino no funcionó por alguna razón. Entonces tuve que crear un .asi que archivo para cada plataforma para la que quiero tener un optimizado libgoto2.so expediente.
Si instala numpy desde el repositorio de Ubuntu, se instalará y configurará automáticamente numpy para usar ATLAS. Instalando ATLAS desde la fuente puede llevar algún tiempo y requiere algunos pasos adicionales (fortran, etc.).
Si instala numpy en una máquina Mac OS X con Soplón o Puertos Mac configurará numpy para usar ATLAS o Marco de aceleración de Apple. Puede comprobar ejecutando ldd en el numpy.core._dotblas archivo o llamada numpy.show_config ().
Conclusiones
MKL se desempeña mejor seguido de cerca por GotoBlas2.
En el valor propio prueba GotoBlas2 funciona sorprendentemente peor de lo esperado. No estoy seguro de por qué es así.
Marco de aceleración de Apple funciona realmente bien, especialmente en modo de un solo subproceso (en comparación con las otras implementaciones de BLAS).
Ambos GotoBlas2 y MKL escala muy bien con el número de hilos. Entonces, si tiene que lidiar con matrices grandes, ejecutarlo en varios subprocesos será de gran ayuda.
En cualquier caso, no use el predeterminado netlib blas implementación porque es demasiado lenta para cualquier trabajo computacional serio.
En nuestro clúster también instalé ACML de AMD y el rendimiento fue similar a MKL y GotoBlas2. No tengo números difíciles.
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 se supone que tiene un rendimiento superior MKL / GotoBlas2 en algunos casos y también es bastante fácil de usar.
He ejecutado su punto de referencia. No hay diferencia entre C ++ y numpy en mi máquina:
¿Crees que mi enfoque es justo o hay algunos gastos generales innecesarios que puedo evitar?
Parece justo porque no hay diferencia en los resultados.
¿Esperaría que el resultado mostrara una discrepancia tan grande entre el enfoque de c ++ y python? Ambos utilizan objetos compartidos para sus cálculos.
No.
Como prefiero usar Python para mi programa, ¿qué puedo hacer para aumentar el rendimiento al llamar a las rutinas BLAS o LAPACK?
Asegúrese de que numpy utilice una versión optimizada de las bibliotecas BLAS / LAPACK en su sistema.
Aquí hay otro punto de referencia (en Linux, simplemente escriba make
): http://dl.dropbox.com/u/5453551/blas_call_benchmark.zip
http://dl.dropbox.com/u/5453551/blas_call_benchmark.png
No veo esencialmente ninguna diferencia entre los diferentes métodos para matrices grandes, entre Numpy, Ctypes y Fortran. (Fortran en lugar de C ++ — y si esto importa, su punto de referencia probablemente esté roto).
Tu CalcTime
La función en C ++ parece tener un error de signo. ... + ((double)start.tv_usec))
debería ser en su lugar ... - ((double)start.tv_usec))
. ¿Quizás su punto de referencia también tiene otros errores, por ejemplo, comparar entre diferentes bibliotecas BLAS o diferentes configuraciones BLAS como el número de subprocesos, o entre el tiempo real y el tiempo de la CPU?
EDITAR: no pudo contar las llaves en el CalcTime
función – está bien.
Como pauta: si realiza una evaluación comparativa, publique siempre todos el código en alguna parte. Comentar los puntos de referencia, especialmente cuando es sorprendente, sin tener el código completo no suele ser productivo.
Para averiguar contra qué BLAS Numpy está vinculado, haga lo siguiente:
$ python Python 2.7.2+ (default, Aug 16 2011, 07:24:41) [GCC 4.6.1] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import numpy.core._dotblas >>> numpy.core._dotblas.__file__ '/usr/lib/pymodules/python2.7/numpy/core/_dotblas.so' >>> $ ldd /usr/lib/pymodules/python2.7/numpy/core/_dotblas.so linux-vdso.so.1 => (0x00007fff5ebff000) libblas.so.3gf => /usr/lib/libblas.so.3gf (0x00007fbe618b3000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fbe61514000)
ACTUALIZAR: Si tu hipocresía import numpy.core._dotblas, su Numpy está usando su copia de respaldo interna de BLAS, que es más lenta y no está diseñada para usarse en computación de rendimiento. La respuesta de @Woltan a continuación indica que esta es la explicación de la diferencia que ve en Numpy vs.Ctypes + BLAS.
Para solucionar la situación, necesita ATLAS o MKL — consulte estas instrucciones: http://scipy.org/Installing_SciPy/Linux La mayoría de las distribuciones de Linux se envían con ATLAS, por lo que la mejor opción es instalar su libatlas-dev
paquete (el nombre puede variar).