我正在尝试设置一个环境来支持集群上的探索性数据分析。根据对现有情况的初步调查,我的目标是使用 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 矩阵乘法大约需要。 2-4s 使用原生的、优化的 BLAS 库。当我在 MacBook Air 上本地运行时,此基准测试在 1.8 秒内完成。当我在 EMR 上运行它时,它大约会完成。 11 秒(使用 g2.2xlarge 实例,尽管在 m3.xlarge 实例上获得了类似的结果)。作为另一个交叉检查,我从 BIDMach project 运行了一个预构建的 EC2 AMI在相同的 EC2 实例类型 g2.2xlarge 上,得到了 2.2s(注意,相同计算的 GPU 基准产生了 0.047s)。
在这一点上,我怀疑 netlib-java 没有加载正确的库,但这就是我被卡住的地方。我已经阅读了很多 netlib-java README times并且似乎已经根据需要安装了 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 实例上运行基准测试的示例。第一个显示 native 系统 BLAS 应该何时正确加载。第二个显示 native BLAS 未加载并且包回退到引用实现的时间。因此,它似乎确实在根据消息和时间加载 native BLAS。与在我的 Mac 上本地运行相比,无 BLAS 案例的运行时间大致相同,但 native 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 库。
谢谢
蒂姆
请您参考如下方法:
跟进:
我的初步结论是 Amazon EMR 实例上默认安装的 Atlas 库很慢。它要么是尚未针对特定机器类型进行优化的通用构建,要么从根本上比其他库慢。使用此 script作为指南,我为运行基准测试的特定机器类型构建并安装了 OpenBLAS(我还找到了一些有用的信息 here)。安装 OpenBLAS 后,我的 3000x3000 矩阵乘法基准测试在 3.9 秒内完成(与使用默认 Atlas 库时上面列出的 15.1 秒相比)。这仍然比在我的 Mac 上运行的相同基准测试慢(x2 倍),但这种差异落在一个范围内,这可能是由于潜在的硬件性能。
这是我用于在 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