Как настроить высокопроизводительный BLAS/LAPACK для Breeze на Amazon EMR, EC2

Я пытаюсь настроить среду для поддержки аналитики аналитических данных в кластере. Исходя из первоначального опроса, моя цель - использовать Scala/Spark с Amazon EMR для обеспечения кластера.

В настоящее время я просто пытаюсь получить некоторые базовые примеры и проверить, что у меня все настроено правильно. У меня проблема в том, что я не вижу производительности, ожидаемой от библиотек Atlas BLAS на экземпляре компьютера Amazon.

Ниже приведен фрагмент кода моего простого теста. Это просто умножение квадратной матрицы с последующим умножением на короткое жирное и умноженное на высокое, чтобы получить небольшую матрицу, которую можно напечатать (я хотел быть уверен, что Scala не пропустит какую-либо часть вычислений из-за ленивых вычислений).

Я использую Breeze для библиотеки линейной алгебры и netlib-java, чтобы использовать локальные библиотеки для 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")
  }

Основываясь на веб-обзоре тестов, я ожидаю, что умножение матрицы 3000x3000 займет ок. 2-4 с использованием собственной оптимизированной библиотеки BLAS. Когда я запускаю локально на своем MacBook Air, этот тест завершается через 1.8 с. Когда я запускаю это на EMR, это завершается в течение ок. 11s (с использованием экземпляра g2.2xlarge, хотя аналогичные результаты были получены на экземпляре m3.xlarge). В качестве еще одной перекрестной проверки я запустил предварительно скомпилированный AMI EC2 из проекта BIDMach для того же типа экземпляра EC2, g2.2xlarge, и получил 2,2 с (обратите внимание, что тест GPU для того же вычисления дал 0,047 с).

На данный момент я подозреваю, что netlib-java не загружает правильную библиотеку, но я застрял здесь. Я много раз читал README по netlib-java, и кажется, что библиотеки ATLAS уже установлены в соответствии с требованиями (см. Ниже)

[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

Ниже я покажу 2 примера выполнения теста на экземпляре Amazon EMR. Первый показывает, когда родная система BLAS предположительно загружается правильно. Второй показывает, когда собственный BLAS не загружается, и пакет возвращается к эталонной реализации. Так что, похоже, он загружает собственный BLAS на основе сообщений и времени. По сравнению с локальным запуском на моем Mac, случай no BLAS запускается примерно в одно и то же время, но собственный случай BLAS выполняется на 1.8 с на моем Mac по сравнению с 15 с в приведенном ниже случае. Информационные сообщения для моего Mac одинаковы по сравнению с EMR (кроме определенных имен каталогов / файлов и т. Д.).

[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

На данный момент мое лучшее предположение заключается в том, что он на самом деле загружает нативную библиотеку, но загружает общую. Любые предложения о том, как я могу проверить, какую разделяемую библиотеку она собирает во время выполнения? Я пробовал 'ldd', но, похоже, не работает с spark-submit. Или, может быть, мои ожидания от Atlas неверны, но, похоже, трудно поверить, что AWS предварительно установит libs, если они не будут работать на достаточно конкурентоспособных скоростях.

Если вы видите, что библиотеки EMR неправильно связаны, пожалуйста, предоставьте рекомендации о том, что мне нужно сделать, чтобы библиотеки Atlas были подобраны с помощью netlib-java.

спасибо тим

2 ответа

Решение

Следовать за:

Мой предварительный вывод заключается в том, что библиотеки Atlas, установленные по умолчанию на экземпляре Amazon EMR, просто медленны. Либо это общая сборка, которая не была оптимизирована для конкретного типа компьютера, либо она существенно медленнее, чем другие библиотеки. Используя этот сценарий в качестве руководства, я создал и установил OpenBLAS для конкретного типа компьютера, на котором я выполнял тесты (здесь я также нашел некоторую полезную информацию). После установки OpenBLAS мой тест матричного умножения 3000x3000 завершился за 3,9 с (по сравнению с 15,1 с, перечисленными выше при использовании библиотек Atlas по умолчанию). Это все еще медленнее, чем тот же тест на моем Mac (в 2 раза), но эта разница находится в диапазоне, который может быть достоверно обусловлен базовой производительностью.

Вот полный список команд, которые я использовал для установки библиотек OpenBLAS на Amazon EMR, экземпляр Spark:

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

Следуя приведенному ниже руководству, я смог заставить работать собственные библиотеки BLAS.

https://spark.apache.org/docs/latest/ml-linalg-guide.html

https://github.com/luhenry/netlib

СБТ зависимость:

"dev.ludovic.netlib" % "blas" % "3.0.3"

Затем в вашем Scala-коде проверьте следующие утверждения:

      // import statement
import dev.ludovic.netlib.blas.NativeBLAS

// print this in your function
println(s"BLAS dev.ludovic.netlib.blas.NativeBLAS: ${NativeBLAS.getInstance()}")

Должно быть напечатано что-то вроде этого:

      BLAS dev.ludovic.netlib.blas.NativeBLAS: dev.ludovic.netlib.blas.JNIBLAS@68a4dcc6

РЕДАКТИРОВАТЬ: На самом деле простое выполнение описанных выше шагов у меня не сработало.

Пришлось отдельно собирать баночки и добывать спарку, чтобы их использовать. Я подробно описал шаги по компиляции jar в этой сути.

https://gist.github.com/dineshdharme/8bd39cdbc35a09033b9ba2cfd1bdf146

Если вы не хотите проходить трудоемкий процесс, я бы посоветовал пойти напрямую.STEP 3и следуйте инструкциям.

Другие вопросы по тегам