Spark on Yarn:性能调优

转载 2015年07月09日 15:52:38

我们团队一直在对Spark在大规模数据挖掘、机器学习上的应用进行实践和探索,本系列文章是我们在使用Spark on Yarn进行分布式开发的总结,有不足的地方,欢迎大家指正和交流,希望更多的人加入我们。

本文主要分享一下我们之前在开发Softmax Regression算法中的一些性能调优的经验(主要是基于0.6.1版本)。

1. 调优经验

应该说,Spark开发中,具体采用什么调优方法去优化性能,需要根据具体算法和实现而定,适合我们这个问题的方法不一定就适合其他问题,但希望我们的经验可以让其他人少踩点坑,更多的调优方法还可以参考官方文档中的  Configuration  和 Tuning  部分。

(1)配置项的使用

熟悉Hadoop开发的同学应该对配置项不陌生。根据不同问题,调整不同的配置项参数,是比较基本的调优方案。配置项可以在脚本文件中添加,也可以在代码中添加。如果是在代码中添加,则需要在 SparkContext 定义 之前 进行配置项的修改,例如:

1
2
System . setProperty ( "spark.akka.frameSize" , "100" )
val sc = new SparkContext ( args ( 0 ) , "SparkSR" )

其中每一个配置项的修改都通过setProerty来实现。下面介绍几个我们用到的比较重要的配置项:

  • spark.akka.frameSize: 控制Spark中通信消息的最大容量 (如 task 的输出结果),默认为10M。当处理大数据时,task 的输出可能会大于这个值,需要根据实际数据设置一个更高的值。如果是这个值不够大而产生的错误,可以从  worker的日志  中进行排查。通常 worker 上的任务失败后,master 的运行日志上出现”Lost TID: “的提示,可通过查看失败的 worker 的日志文件($SPARK_HOME/worker/下面的log文件) 中记录的任务的 Serialized size of result 是否超过10M来确定。
  • spark.storage.memoryFraction: 控制用于 Spark 缓存的 Java 堆空间,默认值是0.67,即 2/3 的 Java 堆空间用于 Spark 的缓存。如果任务的计算过程中需要用到较多的内存,而 RDD 所需内存较少,可以调低这个值,以减少计算过程中因为内存不足而产生的 GC 过程。在调优过程中我们发现,GC 过多是导致任务运行时间较长的一个常见原因。如果你的任务运行较慢,想确定是否是GC太多导致的,可以在 spark-env.sh 中设置 JAVA_OPTS 参数以打印 GC 的相关信息,设置如下: 

    1
    JAVA_OPTS = " -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps"

    这样如果有GC发生,就可以在master和work的日志上看到。
  • spark.default.parallelism: 控制Spark中的分布式shuffle过程默认使用的task数量,默认为8个。如果不做调整,数据量大时,就容易运行时间很长,甚至是出Exception,因为8个task无法handle那么多的数据。 注意这个值也不是说设置得越大越好。
  • spark.local.dir:Spark 运行时的临时目录,例如 map 的输出文件,保存在磁盘的 RDD 等都保存在这里。默认是 /tmp 这个目录,而一开始我们搭建的小集群上 /tmp 这个目录的空间只有2G,大数据量跑起来就出 Exception (”No space left on device”)了。

(2)Broadcast 变量

Spark 所支持的两种共享变量 (shared variables) 的一种,主要用于共享分布式计算过程中各个 task 都会用到的只读变量,broadcast 变量只会在每台计算机器上保存一份,而不会每个task都传递一份,节省空间,效率也高。Spark 的HadoopRDD 的  实现  中,就采用 broadcast 进行 Hadoop JobConf 的传输。 官方文档的说法  是当task的大小大于20k时,就可以考虑用 broadcast 进行优化。

在我们的实现中,权重矩阵是一个 100 * 1000000 的Float矩阵,Spark 默认进行压缩后大约是400M左右,由于梯度计算时每个样本都需要跟整个权重矩阵进行计算,因此权重矩阵的传输我们通过 broadcast 实现。而由于权重矩阵在每次迭代后都会更新,因此在每次迭代后都会重新 broadcast 一次。每次 worker 读取 broadcast 的时间短则几秒,长则二三十秒,相比序列化传参的方式,要快得多。但是这种实现也不完美,因为每次迭代所传输的 broadcast 变量都会保存在 worker 的内存中,直至内存不够用,spark 才会把旧的 broadcast 变量释放掉,不能提前release掉。

(3)accumulator 变量

另外一种 Spark 所支持的共享变量。accumulator 支持在 worker 端进行对其累加操作 +=,但不能读取数据,类似 hadoop 中的counter,但其除了支持 Int 和 Double 类型外,用户还可以自定义类型,只要该类实现相应接口即可。此外,它还支持 type A += type B,即累加结果的类型和累加的值的类型无须一致。

在解决权重更新的问题时,accumulator 是我们尝试过的一种方式,即在 driver 程序中定义一个保存权重矩阵的 accumulator ,然后 worker 计算的梯度直接通过 += 操作,更新该 accumulator 。但尝试没有成功,在不停的 GC 之后,还没到 worker 执行代码的阶段,程序就挂了。

(4)reduce 和 reduceByKey

reduce 是 Action 操作,reduceByKey 是 Transformation 操作。

reduce 是一种聚合操作,可以把各个 task 的结果汇集到 master 节点,执行自定义的 function 操作。reduce的实现做了优化,可以把同一个task内的结果先在本地执行聚合function,再把结果传给master节点执行聚合操作。但由于始终还是要汇总到master节点,且reduce会把接收到的数据保存到内存直到所有task都完成为止,因此当task很多,task的结果数据又比较大时,master容易造成性能瓶颈。

reduceByKey 也是聚合操作,是根据key聚合对应的value。同样的,在每一个mapper把数据发送给reducer前,会在mapper本地先进行merge,类似mapreduce中的combiner。跟reduce不同的是,reduceByKey不是把数据汇集到master节点,是分布式进行的,因此不会存在reduce那样的性能瓶颈。

在我们的softmax regression算法的实现中,需要对worker上计算的梯度进行累加,由于每个 DataPoint 的特征向量是稀疏向量,其计算所得的梯度矩阵也是稀疏的。故我们把稀疏矩阵按照 (列id,列向量) 的形式进行分发,再通过 reduceByKey 对这些 pair 进行聚合累加,得到梯度矩阵。

2. 总结

当面对的数据规模较大时,调优是必经之路,尤其跟Spark打交道的主要是内存。开发过程中,尤其是性能调优时,Spark 的文档可能无法满足需求,特别是出现各种错误时,往往一头雾水,这时最好还是上  google group  上搜索或提问,他们的回复一般还是比较及时的,而且现在用Spark的人相比以前已经多了起来,你踩到的坑估计很多已经早被人踩过了。另外,本文提到的主要是Spark层面上的调优经验,至于机器学习算法的并行设计方面的经验,还请各位高手不吝指点。

该文章转自于http://www.tuicool.com/articles/FFVFnu

相关文章推荐

Spark on Yarn遇到的几个问题及解决思路

Spark on Yarn模式,其资源分配是交给Yarn的ResourceManager来进行管理的,但是目前的Spark版本,Application日志的查看,只能通过Yarn的yarn logs命...

spark on yarn作业运行的jar包缓存优化

这几天一直在追查spark on yarn的作业运行中的jar包分发,以及执行后的jar包删除的问题。从一开始的毫无头绪,到后来逐渐清晰,到后来通过hadoop的两个很简单的参数配置解决了问题。不得不...

Spark on Yarn集群搭建详细过程

由于最近学习大数据开发,spark作为分布式内存计算框架,当前十分火热,因此作为首选学习技术之一。Spark官方提供了三种集群部署方案: Standalone, Mesos, Yarn。其中 Stan...

Spark2.0.0集群环境部署(Spark On Yarn)

Spark 2.0.0发布已经有一段时间了,目前公司生产环境还是使用1.6系列版本。为了测试Spark 2.0.0各方面的稳定性和计算性能,我基于CDH集群环境,搭建了Spark On Yarn集群环...

Spark2.1.1<性能调优Spark运行时jar从yarn端访问>

1.为什么要让运行时Jar可以从yarn端访问spark2以后,原有lib目录下的大JAR包被分散成多个小JAR包,原来的spark-assembly-*.jar已经不存在每一次我们运行的时候,如果没...

Spark性能调优高级篇

前言 继Spark性能调优基础篇讲解了每个Spark开发人员都必须熟知的开发调优与资源调优之后,本文作为《Spark性能优化指南》的高级篇,将深入分析数据倾斜调优与shuffle调优,以解决更加...

SPARK_ON_YARN

  • 2014-09-18 23:23
  • 2.81MB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)