我有一个完全包含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不会同时运行这些工作。
答案 0 :(得分:3)
除了for循环之外,您在代码中的Spark中有2个最慢的API调用 - groupByKey
和collect
。
几乎不会使用groupByKey,而是查看reduceByKey
,有关详细信息,请参阅此Databricks blog。
collect
将该RDD中的所有数据传输到驱动程序节点上的数组,除非这些数据少,否则会对性能产生相当大的影响。
在for循环中,我并不是特别熟悉您尝试做的事情,但在
中var hrpvData = get24HoursPVF(dataDF, id, t).cache()
您正在为每个id和t值构建和缓存新数据框。我不确定为什么你不能在开始时只构建包含id和t的每个变体的单个数据帧,然后在整个数据帧上运行你的zipWithIndex,map等?