Cómo configurar BLAS / LAPACK de alto rendimiento para Breeze en Amazon EMR, EC2


Estoy tratando de configurar un entorno que admita el análisis de datos exploratorios en un clúster. Basado en una encuesta inicial de lo que hay por ahí, mi objetivo es usar Scala / Spark con Amazon EMR para aprovisionar el clúster.

Actualmente solo estoy tratando de poner en marcha algunos ejemplos básicos para validar que tengo todo configurado correctamente. El problema que tengo es que no veo el rendimiento que espero de las bibliotecas Atlas BLAS en la máquina de Amazon instancia.

A continuación se muestra un fragmento de código de mi simple benchmark. Es solo una matriz cuadrada multiplicada seguida de una multiplicación de grasa corta y una multiplicación delgada alta para obtener una matriz pequeña que se pueda imprimir (quería asegurarme de que Scala no saltaría ninguna parte del cálculo debido a una evaluación perezosa).

Estoy usando Breeze para la biblioteca de álgebra lineal y netlib-java para extraer las bibliotecas nativas locales para BLAS/LAPACK

import breeze.linalg.{DenseMatrix, DenseVector}
import org.apache.spark.annotation.DeveloperApi
import org.apache.spark.rdd.RDD
import org.apache.spark.{Partition, SparkContext, TaskContext}
import org.apache.spark.SparkConf

import com.github.fommil.netlib.BLAS.{getInstance => blas}

import scala.reflect.ClassTag

object App {

  def NaiveMultiplication(n: Int) : Unit = {

    val vl = java.text.NumberFormat.getIntegerInstance.format(n)
    println(f"Naive Multipication with vector length " + vl)

    println(blas.getClass().getName())

    val sm: DenseMatrix[Double] = DenseMatrix.rand(n, n)
    val a: DenseMatrix[Double] = DenseMatrix.rand(2,n)
    val b: DenseMatrix[Double] = DenseMatrix.rand(n,3)

    val c: DenseMatrix[Double] = sm * sm
    val cNormal: DenseMatrix[Double] = (a *  c)  * b

    println(s"Dot product of a and b is \n$cNormal")
  }

Basado en una encuesta web de puntos de referencia Estoy esperando un 3000x3000 matriz multiplicar para tomar aprox. 2-4s usando una biblioteca BLAS nativa y optimizada. Cuando corro localmente en mi MacBook Air, este benchmark se completa en 1.8 s. Cuando corro esto en EMR, se completa en aprox. 11s (usando una instancia g2. 2xlarge, aunque se obtuvieron resultados similares en un m3.instancia xlarge). Como otra comprobación cruzada, ejecuté una AMI EC2 precompilada desde el proyecto BIDMach en el mismo tipo de instancia EC2, g2. 2xlarge, y obtuve 2.2 s (nota, el benchmark de GPU para el mismo cálculo cedió 0,047 s).

En este punto sospecho que netlib-java no está cargando la lib correcta, pero aquí es donde estoy atascado. He pasado por el README netlib-java muchas veces y parece que las libs de ATLAS ya están instaladas como se requiere (ver más abajo)

[hadoop@ip-172-31-3-69 ~]$ ls /usr/lib64/atlas/
libatlas.a       libcblas.a       libclapack.so      libf77blas.so      liblapack.so      libptcblas.so      libptf77blas.so
libatlas.so      libcblas.so      libclapack.so.3    libf77blas.so.3    liblapack.so.3    libptcblas.so.3    libptf77blas.so.3
libatlas.so.3    libcblas.so.3    libclapack.so.3.0  libf77blas.so.3.0  liblapack.so.3.0  libptcblas.so.3.0  libptf77blas.so.3.0
libatlas.so.3.0  libcblas.so.3.0  libf77blas.a       liblapack.a        libptcblas.a      libptf77blas.a
[hadoop@ip-172-31-3-69 ~]$ cat /etc/ld.so.conf
include ld.so.conf.d/*.conf
[hadoop@ip-172-31-3-69 ~]$ ls /etc/ld.so.conf.d
atlas-x86_64.conf  kernel-4.4.11-23.53.amzn1.x86_64.conf  kernel-4.4.8-20.46.amzn1.x86_64.conf  mysql55-x86_64.conf  R-x86_64.conf
[hadoop@ip-172-31-3-69 ~]$ cat /etc/ld.so.conf.d/atlas-x86_64.conf 
/usr/lib64/atlas

A continuación, he mostrado 2 ejemplos que ejecutan el benchmark en la instancia de Amazon EMR. La primera muestra cuando el sistema nativo BLAS supuestamente carga correctamente. El segundo muestra cuando el BLAS nativo no se carga y el paquete vuelve a la aplicación de referencia. Así que parece estar cargando un BLAS nativo basado en los mensajes y el tiempo. En comparación con la ejecución local en mi Mac, el caso sin BLAS se ejecuta aproximadamente al mismo tiempo, pero el caso BLAS nativo se ejecuta en 1.8 s en mi Mac en comparación con 15s en el caso siguiente. Los mensajes de información son los mismos para mi Mac en comparación con EMR (aparte de dir/nombres de archivo específicos, etc.).

[hadoop@ip-172-31-3-69 ~]$ spark-submit --class "com.cyberatomics.simplespark.App" --conf "spark.driver.extraClassPath=/home/hadoop/simplespark-0.0.1-SNAPSHOT-jar-with-dependencies.jar"   --master local[4] simplespark-0.0.1-SNAPSHOT-jar-with-dependencies.jar  3000 naive
Naive Multipication with vector length 3,000
Jun 16, 2016 12:30:39 AM com.github.fommil.jni.JniLoader liberalLoad
INFO: successfully loaded /tmp/jniloader2856061049061057802netlib-native_system-linux-x86_64.so
com.github.fommil.netlib.NativeSystemBLAS
Dot product of a and b is 
1.677332076284315E9   1.6768329748988206E9  1.692150656424957E9   
1.6999000993276503E9  1.6993872020220244E9  1.7149145239563465E9  
Elapsed run time:  15.1s
[hadoop@ip-172-31-3-69 ~]$ 
[hadoop@ip-172-31-3-69 ~]$ spark-submit --class "com.cyberatomics.simplespark.App"  --master local[4] simplespark-0.0.1-SNAPSHOT-jar-with-dependencies.jar  3000 naive
Naive Multipication with vector length 3,000
Jun 16, 2016 12:31:32 AM com.github.fommil.netlib.BLAS <clinit>
WARNING: Failed to load implementation from: com.github.fommil.netlib.NativeSystemBLAS
Jun 16, 2016 12:31:32 AM com.github.fommil.netlib.BLAS <clinit>
WARNING: Failed to load implementation from: com.github.fommil.netlib.NativeRefBLAS
com.github.fommil.netlib.F2jBLAS
Dot product of a and b is 
1.6640545115052865E9  1.6814609592261212E9  1.7062846398842275E9  
1.64471099826913E9    1.6619129531594608E9  1.6864479674870768E9  
Elapsed run time:  28.7s

En este punto mi mejor conjetura es que en realidad está cargando un lib nativa, pero está cargando una genérica. ¿Alguna sugerencia sobre cómo puedo verificar qué biblioteca compartida está recogiendo en tiempo de ejecución? Probé ' ldd ' pero parece que no funciona con spark-submit. O tal vez mis expectativas para Atlas son incorrectas, pero parece difícil creer que AWS preinstalaría las bibliotecas si no estuvieran ejecutando velocidades razonablemente competitivas.

Si ve que las libs no están enlazadas correctamente en EMR, por favor proporcione orientación sobre lo que necesito hacer para el Atlas libs para ser recogido por netlib-java.

Gracias tim

Author: Tim Ryan, 2016-06-16

1 answers

Seguimiento:

Mi conclusión provisional es que las libs de Atlas instaladas de forma predeterminada en la instancia de Amazon EMR son simplemente lentas. O bien es una compilación genérica que no ha sido optimizada para el tipo de máquina específico, o es fundamentalmente más lenta que otras bibliotecas. Usando este script como guía construí e instalé OpenBLAS para el tipo de máquina específico donde estaba ejecutando los puntos de referencia(también encontré información útil aquí). Una vez que OpenBLAS fue instalado mi 3000x3000 matrix multiply benchmark completado en 3.9 s (en comparación con los 15.1 s mencionados anteriormente cuando se utiliza el Atlas libs predeterminado). Esto sigue siendo más lento que la misma ejecución de referencia en mi Mac (por un factor de x2), pero esta diferencia cae en un rango que podría deberse creíblemente al rendimiento h/n subyacente.

Aquí hay una lista completa de los comandos que utilicé para instalar OpenBLAS libs en la instancia EMR, Spark de Amazon:

sudo yum install git
git clone https://github.com/xianyi/OpenBlas.git
cd OpenBlas/
make clean
make -j4
sudo mkdir /usr/lib64/OpenBLAS
sudo chmod o+w,g+w /usr/lib64/OpenBLAS/
make PREFIX=/usr/lib64/OpenBLAS install
sudo rm /etc/ld.so.conf.d/atlas-x86_64.conf 
sudo ldconfig
sudo ln -sf /usr/lib64/OpenBLAS/lib/libopenblas.so /usr/lib64/libblas.so
sudo ln -sf /usr/lib64/OpenBLAS/lib/libopenblas.so /usr/lib64/libblas.so.3
sudo ln -sf /usr/lib64/OpenBLAS/lib/libopenblas.so /usr/lib64/libblas.so.3.5
sudo ln -sf /usr/lib64/OpenBLAS/lib/libopenblas.so /usr/lib64/liblapack.so
sudo ln -sf /usr/lib64/OpenBLAS/lib/libopenblas.so /usr/lib64/liblapack.so.3
sudo ln -sf /usr/lib64/OpenBLAS/lib/libopenblas.so /usr/lib64/liblapack.so.3.5
 11
Author: Tim Ryan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-24 17:54:18