Un buen punto de partida es el gran libro La ciencia de la programación de cálculos matriciales de Robert A. van de Geijn y Enrique S. Quintana-Ortí. Proporcionan una versión de descarga gratuita.
BLAS se divide en tres niveles:
El nivel 1 define un conjunto de funciones de álgebra lineal que operan solo en vectores. Estas funciones se benefician de la vectorización (por ejemplo, del uso de SSE).
Las funciones de nivel 2 son operaciones matriz-vector, por ejemplo, algún producto matriz-vector. Estas funciones podrían implementarse en términos de funciones de Nivel1. Sin embargo, puede aumentar el rendimiento de estas funciones si puede proporcionar una implementación dedicada que haga uso de alguna arquitectura de multiprocesador con memoria compartida.
Las funciones de nivel 3 son operaciones como el producto matriz-matriz. Nuevamente, podría implementarlos en términos de funciones de Nivel2. Pero las funciones de Level3 realizan operaciones O (N ^ 3) en datos O (N ^ 2). Entonces, si su plataforma tiene una jerarquía de caché, puede aumentar el rendimiento si proporciona una implementación dedicada que sea optimizada para caché / compatible con caché . Esto está muy bien descrito en el libro. El principal impulso de las funciones de Level3 proviene de la optimización de la caché. Este impulso supera significativamente el segundo impulso del paralelismo y otras optimizaciones de hardware.
Por cierto, la mayoría (o incluso todas) de las implementaciones BLAS de alto rendimiento NO se implementan en Fortran. ATLAS se implementa en C. GotoBLAS / OpenBLAS se implementa en C y sus partes críticas de rendimiento en Assembler. Solo la implementación de referencia de BLAS se implementa en Fortran. Sin embargo, todas estas implementaciones de BLAS proporcionan una interfaz Fortran de modo que se puede vincular contra LAPACK (LAPACK obtiene todo su rendimiento de BLAS).
Los compiladores optimizados juegan un papel menor a este respecto (y para GotoBLAS / OpenBLAS el compilador no importa en absoluto).
En mi humilde opinión, la implementación de BLAS no utiliza algoritmos como el algoritmo Coppersmith-Winograd o el algoritmo Strassen. No estoy exactamente seguro de la razón, pero esta es mi suposición:
- Tal vez no sea posible proporcionar una implementación optimizada de caché de estos algoritmos (es decir, perdería más de lo que ganaría)
- Estos algoritmos son numéricamente no estables. Como BLAS es el núcleo computacional de LAPACK, esto no es posible.
Editar / Actualizar:
El documento nuevo e innovador para este tema son los documentos BLIS . Están excepcionalmente bien escritos. Para mi conferencia "Conceptos básicos de software para computación de alto rendimiento", implementé el producto matriz-matriz después de su artículo. De hecho, implementé varias variantes del producto matriz-matriz. Las variantes más simples están escritas completamente en C simple y tienen menos de 450 líneas de código. Todas las demás variantes simplemente optimizan los bucles
for (l=0; l<MR*NR; ++l) {
AB[l] = 0;
}
for (l=0; l<kc; ++l) {
for (j=0; j<NR; ++j) {
for (i=0; i<MR; ++i) {
AB[i+j*MR] += A[i]*B[j];
}
}
A += MR;
B += NR;
}
El rendimiento general del producto matriz-matriz solo depende de estos bucles. Aproximadamente el 99,9% del tiempo se pasa aquí. En las otras variantes usé intrínsecos y código ensamblador para mejorar el rendimiento. Puedes ver el tutorial pasando por todas las variantes aquí:
ulmBLAS: Tutorial sobre GEMM (Producto Matrix-Matrix)
Junto con los documentos de BLIS, resulta bastante fácil comprender cómo las bibliotecas como Intel MKL pueden obtener ese rendimiento. ¡Y por qué no importa si usa almacenamiento principal en filas o columnas!
Los puntos de referencia finales están aquí (llamamos a nuestro proyecto ulmBLAS):
Puntos de referencia para ulmBLAS, BLIS, MKL, openBLAS y Eigen
Otra edición / actualización:
También escribí un tutorial sobre cómo se usa BLAS para problemas de álgebra lineal numérica, como resolver un sistema de ecuaciones lineales:
Factorización LU de alto rendimiento
(Esta factorización LU la utiliza, por ejemplo, Matlab para resolver un sistema de ecuaciones lineales).
Espero encontrar tiempo para extender el tutorial para describir y demostrar cómo realizar una implementación paralela altamente escalable de la factorización LU como en PLASMA .
Ok, aquí tienes: Codificación de una factorización de LU paralela optimizada de caché
PD: También hice algunos experimentos para mejorar el rendimiento de uBLAS. En realidad, es bastante simple impulsar (sí, jugar con las palabras :)) el rendimiento de uBLAS:
Experimentos sobre uBLAS .
Aquí un proyecto similar con BLAZE :
Experimentos en BLAZE .