我正在尝试搭建一个支持集群上探索性数据分析的环境。根据对现有资源的初步调查,我的目标是使用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")
}
基于网络调查的基准测试,我预计使用本地优化的BLAS库进行3000x3000矩阵乘法大约需要2-4秒。在我的MacBook Air上本地运行该基准测试仅需1.8秒。但在EMR上运行该基准测试需要约11秒(使用g2.2xlarge实例,在m3.xlarge实例上也获得了类似的结果)。为了进一步验证,我在相同的EC2实例类型g2.2xlarge上运行来自BIDMach项目的预构建EC2 AMI,获得了2.2秒的结果(请注意,同样计算的GPU基准测试仅需0.047秒)。
目前我怀疑是netlib-java没有正确加载库,但我卡在这里了。我已经多次阅读了netlib-java的README文件,看起来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 实例上运行基准测试的两个示例。第一个示例显示当原生系统BLAS正确加载时的情况。第二个示例显示当本机 BLAS 未加载并且软件包退回到参考实现时的情况。因此,根据消息和时间,似乎确实正在加载本地 BLAS。与在我的 Mac 上本地运行相比,无 BLAS 情况大约在相同时间内运行,但本地 BLAS 情况在我的 Mac 上运行1.8秒,而在下面的情况下需要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会预安装这些库。
如果您发现EMR上的库未正确链接,请指导我应该怎么做才能使netlib-java选择Atlas库。
谢谢 tim