He implementado CG en FORTRAN al vincularlo a Intel MKL.
Cuando hay declaraciones como: ( Consulte Wikipedia )
p=r;
x=x+alpha*p
r=r-alpha*Ap;
o similares en QMR (en una cantidad mucho mayor)
v_tld = r;
y = v_tld;
rho = norm( y );
w_tld = r;
z = w_tld;
xi = norm( z ); (and more)
¿Tiene sentido utilizar implementaciones BLAS Nivel 1 como DAXPY, DCOPY, DSCAL? La motivación para mi pregunta es:
Tengo 2 implementaciones de los algoritmos. Uno en el que solo he vinculado Norms y MatVecs a MKL; copiar, escalar y agregar se realiza mediante las funciones intrínsecas de Fortran y otra donde BLAS realiza todas las subrutinas posibles.
Tenía la idea de que nada puede ser más rápido que BLAS. Pero, resulta que mi código usando las funciones intrínsecas de Fortran corrió 100% más rápido que uno con las subrutinas BLAS Nivel 1 (FWIW, esto no fue un pequeño problema, fue resolver un sistema denso de tamaño 13k x 13k que llenó mis 4 GB de RAM). Estaba ejecutando ambos en 2 hilos (en una máquina de 2 núcleos)
ifort QMR.f90 -mkl
conMKL_DYNAMIC=TRUE
Había hecho una pregunta sobre SO con respecto a la extensión de BLAS, pero a medida que intentaba incluir BLAS Nivel 1 en mi código, mi código se volvía cada vez más lento.
¿Estoy haciendo algo mal o se espera esto?
Además, ¿tiene sentido intentar extender BLAS para hacer operaciones no obvias como y = 2.89*x
por DCOPY(n,2.89*x,1,y,1) or even DSCAL then DCOPY
?
Lo que también es interesante es DDOT
y DNRM2
mejora el rendimiento. Lo atribuí al hecho de que, dado que realizan multiplicaciones de doble precisión, podría ser útil ponerlas en paralelo.
Pregunta complementaria: ¿ Cuándo decide si una operación BLAS Nivel 1 realmente ayudará al rendimiento?
Agregando: Actualmente, estoy corriendo en una computadora portátil i3 2.13 GHz con 4 GB de RAM y información de proceso Debian de 64 bits aquí . Pero obtengo respuestas similares en una estación de trabajo Intel Xeon 12 core con 24 GB de RAM.
fuente
Respuestas:
Si su objetivo es realmente exprimir tanto rendimiento como sea posible, entonces es importante recordar:
Una biblioteca BLAS ajustada por el proveedor ciertamente debería ser su enfoque predeterminado, pero si se ha tomado el tiempo de kernels individuales y ha notado que alguna otra implementación es más rápida, entonces, por todos los medios, use la otra implementación. Perder el uso de intrínsecos de vectores posiblemente podría conducir a una gran diferencia de rendimiento.
Es posible que su mejor apuesta para rutinas simples como daxpy y dscal sea un bucle escrito a mano que explote la intrínseca del vector.
fuente
Dado el estado de la optimización de los compiladores de hoy en día, no creo que haya mucho vudú en las rutinas BLAS lineales, por ejemplo
DAXPY
,DCOPY
yDSCAL
, que su compilador no tiene ya, por ejemplo, SSE-vectorización y desenrollado del bucle.Si el código es el mismo, la única diferencia entre su rutina y una llamada al BLAS de MKL es la sobrecarga de la llamada de función y cualquier magia adicional que MKL podría estar tratando de hacer allí. Si este es el caso, la diferencia entre su código y el código de MKL debe ser constante, independiente del tamaño del problema / vector.
Esta pregunta tiene ecos interesantes de esta pregunta , que también se usa
DAXPY
como ejemplo.fuente
El estándar BLAS en realidad tiene varias comprobaciones de la corrección de los argumentos de la función que son innecesarios en muchas situaciones. Ver esta implementación de referencia de
daxpy.f
. Además, las constantes comoINCX
las conoce habitualmente en tiempo de compilación, pero la implementación no puede asumirlas. BLAS llama a unidades de compilación cruzada, y no conozco ningún compilador que pueda optimizarlas sin activar la optimización completa del programa.gemm
, con suficiente optimización habilitada.fuente
Las funciones BLAS1 representan un conjunto de núcleos que tienen un ancho de banda limitado porque su intensidad de cálculo es baja. En particular, estos núcleos hacen O (1) flops por acceso a memoria. Esto significa que en el hardware moderno, se ejecutan a una pequeña fracción del pico y esencialmente no hay nada que pueda hacer al respecto. La mejor implementación de BLAS1 verificará la alineación y el módulo de la longitud del vector FPU y funcionará en el pico de ancho de banda, que es probable que sea del 5-10% del pico de cálculo.
Cuando escribe estas operaciones explícitamente en la fuente, un buen compilador las reconoce de inmediato y presenta una implementación óptima que es equivalente a la BLAS1 mencionada anteriormente. Sin embargo, debido a que el compilador sabe más sobre el contexto, puede evitar ciertas ramas (no es que importen demasiado) y la sobrecarga de las llamadas de función, así como también realizar transformaciones de orden superior en el código que serían bloqueadas por una llamada de función a Una biblioteca opaca.
Hay una variedad de experimentos que puede realizar para determinar qué está afectando realmente el rendimiento de su código. Son bastante obvios, así que no los enumeraré aquí.
fuente