2016-06-16 32 views
23

Ich versuche, eine Umgebung zur Unterstützung der explorativen Datenanalyse in einem Cluster einzurichten. Basierend auf einer ersten Umfrage, was mein Ziel ist, verwende ich Scala/Spark mit Amazon EMR, um den Cluster bereitzustellen.So konfigurieren Sie Hochleistungs-BLAS/LAPACK für Breeze auf Amazon EMR, EC2

Momentan versuche ich nur ein paar grundlegende Beispiele zu bekommen, um zu bestätigen, dass ich alles richtig konfiguriert habe. Das Problem, das ich habe, ist, dass ich nicht die Leistung sehe, die ich von den Atlas BLAS-Bibliotheken auf der Amazon-Maschineninstanz erwarte.

Unten ist ein Codeausschnitt meines einfachen Benchmarks. Es ist nur eine quadratische Matrix multiply, gefolgt von einer kurzen fetten Multiplikation und einer hohen dünnen Multiplikation, um eine kleine Matrix zu erhalten, die gedruckt werden kann (ich wollte sicher sein, dass Scala keinen Teil der Berechnung wegen einer faulen Auswertung überspringen würde).

Ich verwende Breeze für die lineare Algebra Bibliothek und netlib-java in den lokalen nativen Bibliotheken für 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") 
    } 

Basierend auf einer Web-Umfrage von Benchmarks eine 3000x3000 zu ziehen Matrix Ich erwarte multiplizieren, um ca. 2-4s mit einer nativen, optimierten BLAS-Bibliothek. Wenn ich lokal auf meinem MacBook Air laufe, ist dieser Benchmark in 1,8 Sekunden abgeschlossen. Wenn ich dies auf EMR ausführe, ist es in ca. abgeschlossen. 11s (mit einer g2.2xlarge-Instanz, obwohl ähnliche Ergebnisse auf einer 3.x3-Instanz erhalten wurden). Als weiteren Vergleichstest habe ich einen vorgefertigten EC2 AMI von BIDMach project auf dem gleichen EC2-Instance-Typ, g2.2xlarge, ausgeführt und 2.2s erhalten (beachten Sie, dass der GPU-Benchmark für die gleiche Berechnung 0.047s ergab).

An dieser Stelle vermute ich, dass netlib-java nicht die richtige lib lädt, aber das ist, wo ich feststecke. Ich habe durch die netlib-java README viele gegangen times und es scheint, dass die ATLAS-Libs sind bereits nach Bedarf installiert (siehe unten)

[[email protected] ~]$ 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 
[[email protected] ~]$ cat /etc/ld.so.conf 
include ld.so.conf.d/*.conf 
[[email protected] ~]$ 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 
[[email protected] ~]$ cat /etc/ld.so.conf.d/atlas-x86_64.conf 
/usr/lib64/atlas 

Unten habe ich zeigen zwei Beispiele, um die Benchmark auf Amazon EMR-Instanz läuft. Die erste zeigt, wenn das native System BLAS angeblich korrekt lädt. Die zweite zeigt, wenn das native BLAS nicht geladen wird und das Paket auf die Referenzimplementierung zurückfällt. Es scheint also, ein natives BLAS basierend auf den Nachrichten und dem Timing zu laden. Verglichen mit der lokalen Ausführung auf meinem Mac läuft der no BLAS-Fall ungefähr zur gleichen Zeit, aber der native BLAS-Fall läuft in 1.8s auf meinem Mac, verglichen mit 15s in dem Fall unten. Die Info-Nachrichten sind für meinen Mac im Vergleich zu EMR dieselben (abgesehen von bestimmten Verzeichnis-/Dateinamen usw.).

[[email protected] ~]$ 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 
[[email protected] ~]$ 
[[email protected] ~]$ 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 

An dieser Stelle meine beste Vermutung ist, dass es tatsächlich eine native lib wird geladen, aber es ist ein generisches ein Laden. Irgendwelche Vorschläge, wie ich überprüfen kann, welche gemeinsame Bibliothek zur Laufzeit abgerufen wird? Ich habe 'ldd' ausprobiert, aber das scheint nicht mit Funkensummen zu funktionieren. Oder vielleicht sind meine Erwartungen für Atlas falsch, aber es scheint schwer zu glauben, dass AWS die Bibliotheken vorinstallieren würde, wenn sie nicht mit einigermaßen wettbewerbsfähigen Geschwindigkeiten arbeiten würden.

Wenn Sie sehen, dass die Bibliotheken nicht korrekt mit EMR verbunden sind, geben Sie bitte an, was zu tun ist, damit die Atlas-Bibliotheken von netlib-java abgeholt werden können.

dank tim

+1

Könnten Sie konvertieren „follow-up“ in eine Antwort? Es liefert nützliche Einsichten und wenn es keine andere Antwort gibt, würde ich gerne das Kopfgeld vergeben. Danke im Voraus! –

+0

Ich kann nicht einmal die erste Instanz neu erstellen, wo Sie die standardmäßige EMR Atlas native lib abrufen. Haben Sie andere Dinge anders gemacht (nicht in Ihrem Beitrag aufgelistet), die dazu führten, dass die native lib anstelle von F2jBLAS verwendet wurde? Egal was ich versuche, ich scheine immer noch F2J zu bekommen. –

+0

Es ist lange her, dass ich mir das anschaue. Ich denke, die Art, wie Netlib in Breeze integriert ist, hat sich ein wenig verändert. Aber soweit ich mich erinnere, war der Schlüssel, um über Ihr Problem hinwegzukommen, die .jar-Datei, die die nativen Bibliotheks-Stubs enthält. Zu der Zeit, als ich das oben Gesagte zum ersten Mal veröffentlichte, musste das Jar HAD explizit mit einer zusätzlichen Pfadvariablen eingeschlossen werden. Es wurde NICHT in das Fettglas mit meiner Anwendung aufgenommen. Hier war ein guter Beitrag zum Einrichten von netlib, um BLAS zu verwenden https://datasciencemadesimpler.wordpress.com/tag/blas/ –

Antwort

10

Follow up:

Meine vorläufige Schlussfolgerung ist, dass die Atlas libs standardmäßig auf der Instanz Amazon EMR installiert einfach langsam. Entweder ist es ein generischer Build, der nicht für den bestimmten Maschinentyp optimiert wurde, oder er ist wesentlich langsamer als andere Bibliotheken.Mit dieser script als Leitfaden habe ich OpenBLAS für den spezifischen Maschinentyp gebaut und installiert, wo ich die Benchmarks ausgeführt habe (ich habe auch einige hilfreiche Informationen gefunden). Nach der Installation von OpenBLAS wurde mein 3000x3000-Matrix-Multiplikations-Benchmark in 3,9 Sekunden abgeschlossen (im Vergleich zu den oben aufgeführten 15,1-Sekunden bei Verwendung der Standard-Atlas-Bibliotheken). Dies ist immer noch langsamer als der gleiche Benchmark-Lauf auf meinem Mac (um den Faktor x2), aber dieser Unterschied fällt in einen Bereich, der glaubwürdig auf die zugrunde liegende h/w-Leistung zurückzuführen sein könnte.

ist die komplette Liste der Befehle, die ich verwendet, um OpenBLAS Libs auf Amazon EMR Spark Instanz zu installieren:

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 
+0

Die Schritte, die ich in AWS ausführe, behaupten immer noch, dass ich F2J benutze. Welche anderen Schritte hast du unternommen, um auf diese native lib zu verweisen? Hast du breeze-native dep eingebunden? Was ist die Bedeutung eines zusätzlichen classPath in deiner Frage? In Ihrem Beispiel scheint das die native lib und nicht F2J zu erfassen. –