如何在 Amazon EMR、EC2 上为 Breeze 配置高性能 BLAS/LAPACK

问题描述 投票:0回答:2

我正在尝试建立一个环境来支持集群上的探索性数据分析。根据对现有内容的初步调查,我的目标是使用 Scala/Spark 与 Amazon EMR 来配置集群。

目前我只是尝试启动并运行一些基本示例,以验证我是否已正确配置所有内容。我遇到的问题是,我没有看到 Amazon 机器实例上的 Atlas BLAS 库所期望的性能。

下面是我的简单基准测试的代码片段。它只是一个方阵乘法,然后是短胖乘法和高瘦乘法,以生成一个可以打印的小矩阵(我想确保 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 矩阵乘法大约需要使用本机优化的 BLAS 库需要 2-4 秒。当我在 MacBook Air 上本地运行时,该基准测试在 1.8 秒内完成。当我在 EMR 上运行此程序时,它会在大约 5 分钟内完成。 11 秒(使用 g2.2xlarge 实例,但在 m3.xlarge 实例上获得了类似的结果)。作为另一项交叉检查,我在相同的 EC2 实例类型 g2.2xlarge 上运行了来自BIDMach 项目的预构建 EC2 AMI,并得到了 2.2 秒(注意,相同计算的 GPU 基准测试结果为 0.047 秒)。

此时我怀疑 netlib-java 没有加载正确的库,但这就是我陷入困境的地方。我已经多次阅读了 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

下面我展示了在 Amazon EMR 实例上运行基准测试的 2 个示例。第一个显示本机系统 BLAS 何时正确加载。第二个显示本机 BLAS 未加载并且包回退到参考实现的时间。因此,它似乎确实是根据消息和时间加载本机 BLAS。与在我的 Mac 上本地运行相比,无 BLAS 情况的运行时间大约相同,但本机 BLAS 情况在我的 Mac 上的运行时间为 1.8 秒,而下面的情况为 15 秒。与 EMR 相比,我的 Mac 的信息消息相同(除了特定的目录/文件名等)。 

[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 会预安装这些库,如果它们没有运行相当有竞争力的速度。

如果您发现 EMR 上的库未正确链接,请提供有关我需要做什么的指导,以便 netlib-java 获取 Atlas 库。

谢谢 蒂姆

apache-spark amazon-ec2 amazon-emr scala-breeze jblas
2个回答
12
投票

我的初步结论是,Amazon EMR 实例上默认安装的 Atlas 库速度很慢。它要么是尚未针对特定机器类型进行优化的通用构建,要么从根本上比其他库慢。使用这个

脚本

作为指导,我为运行基准测试的特定机器类型构建并安装了OpenBLAS(我还发现了一些有用的信息here)。安装 OpenBLAS 后,我的 3000x3000 矩阵乘法基准测试在 3.9 秒内完成(与上面列出的使用默认 Atlas 库时的 15.1 秒相比)。这仍然比我的 Mac 上运行的相同基准测试慢(2 倍),但这种差异在一定范围内,可能是由于底层硬件性能造成的。 以下是我用于在 Amazon EMR、Spark 实例上安装 OpenBLAS 库的命令的完整列表:

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
投票

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

https://github.com/luhenry/netlib

sbt 依赖:

"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()}")

© www.soinside.com 2019 - 2024. All rights reserved.