Spark性能 - 如何并行化大循环?

时间:2015-12-08 07:11:27

标签: performance scala parallel-processing apache-spark

我有一个完全包含8000个循环的Spark应用程序,它运行在5个节点的集群上。每个节点有125GB内存和32个内核。关注的代码如下所示:

for (m <- 0 until deviceArray.size) { // there are 1000 device 
  var id = deviceArray(m)

  for (t <- 1 to timePatterns) { // there are 8 time patterns
     var hrpvData = get24HoursPVF(dataDF, id, t).cache()

  var hrpvDataZI = hrpvData.zipWithIndex

  var clustersLSD = runKMeans(hrpvData, numClusters, numIterations)

  var clusterPVPred = hrpvData.map(x => clustersLSD.predict(x))
  var clusterPVMap = hrpvDataZI.zip(clusterPVPred)

  var pvhgmRDD = clusterPVMap.map{r => (r._2, r._1._2)}.groupByKey

  var arrHGinfo = pvhgmRDD.collect 

  // Post process data 
  // .....

  hrpvData.unpersist()
  }
}

函数调用get24HoursPVF()为k-means准备特征向量,大约需要40秒。每个循环大约需要50秒才能完成使用群集。我的数据大小为2到3 GB(从表中读取)。给定8000个循环,运行此Spark应用程序的总时间是不可接受的(8000x50s)。

由于每个设备都是独立的,有没有办法并行化8000次迭代?或者如何利用集群来解决总运行时间长的问题?斯卡拉未来不会工作,因为它只是同时提交工作,但Spark不会同时运行这些工作。

1 个答案:

答案 0 :(得分:3)

除了for循环之外,您在代码中的Spark中有2个最慢的API调用 - groupByKeycollect

几乎不会使用groupByKey,而是查看reduceByKey,有关详细信息,请参阅此Databricks blog

collect将该RDD中的所有数据传输到驱动程序节点上的数组,除非这些数据少,否则会对性能产生相当大的影响。

在for循环中,我并不是特别熟悉您尝试做的事情,但在

var hrpvData = get24HoursPVF(dataDF, id, t).cache()

您正在为每个id和t值构建和缓存新数据框。我不确定为什么你不能在开始时只构建包含id和t的每个变体的单个数据帧,然后在整个数据帧上运行你的zipWithIndex,map等?