在实现RDD时,PySpark的工作似乎陷入困境

时间:2016-06-29 19:16:58

标签: apache-spark pyspark

我有一个SparkJob,它通过在N个项目之间创建成对分数矩阵开始。尽管这种情况非常快,但是它的速度相当快,达到了大约20K的元素,之后它们似乎很长时间陷入困境。我在多次尝试中看到的最后一个日志行是“清理累加器”我已经附加了下面的代码块,用随机创建的50K元素数据集来重现问题。笛卡尔积非常快,并且在几分钟内(25亿行)返回生成的RDD,但第二次计数卡住了两个多小时,日志或Spark Jobs UI中没有进度更新。我有一个15 EC2 M3.2xLarge节点的集群。我怎样才能理解这里发生了什么,以及如何加快速度呢?

import random
from pyspark.context import SparkContext
from pyspark.sql import HiveContext, SQLContext
import math
from pyspark.sql.types import *
from pyspark.sql.types import Row
sc=SparkContext(appName='kmedoids_test')
sqlContext=HiveContext(sc)
n=50000
A = [random.normalvariate(0, 1) for i in range(n)]
B = [random.normalvariate(1, 1) for i in range(n)]
C = [random.normalvariate(-1, 0.5) for i in range(n)]
df = sqlContext.createDataFrame(zip(A,B,C), ["A","B","C"])
f = lambda x, y : math.pow((x.A - y.A), 2) + math.pow((x.B - y.B), 2) +    math.pow((x.C - y.C), 2)
schema  = StructType([StructField("row_id", LongType(), False)] +       df.schema.fields[:])
no_of_cols=len(df.columns)
rdd_zipped_with_index=df.rdd.zipWithIndex()
reconstructed_rdd = rdd_zipped_with_index.map(lambda x: [x[1]]+list(x[0][0:no_of_cols]))
indexed_df=reconstructed_rdd.toDF(schema)
indexed_rdd = indexed_df.rdd
sc._conf.set("spark.sql.autoBroadcastJoinThreshold","-1") #turning off broadcast join
rdd_cartesian_prod = indexed_rdd.cartesian(indexed_rdd)
print "----------Count in self-join--------------- {0}".format(rdd_cartesian_prod.count()) #this returns quickly in about 160s
ScoreVec = Row("head_id","tail_id","score")
output_rdd = rdd_cartesian_prod.map(lambda x :   ScoreVec(float(x[0].row_id), float(x[1].row_id), float(f(x[0], x[1]))))
print "-----------Count after scoring---------------  {0}".format(output_rdd.count()) #gets stuck here for a LONG time
output_df = output_rdd.toDF() #does not get here

1 个答案:

答案 0 :(得分:1)

这可能是由lazy evaluation

引起的
  

Spark是一样的。它一直等到你完成给它的操作员,并且只有当你要求它给你最终的答案时它才会评估,并且它总是看起来限制它要做多少工作。

笛卡尔积之后的行数indexed_rdd.count()^2。 Spark实际上并不需要生成所有这些行来知道将有多少行。尽管output_rdd.count()中的行数相同,但Spark实际上是在处理所有数据并在计数之前映射它。这就是为什么这项任务需要更长时间的原因。要证明这是正在发生的事情,您可以尝试indexed_rdd.cache().count()。在计数之前进行缓存将强制进行数据处理(并将结果保存在内存中)并且需要很长时间。

相关问题