我刚创建了range(1,100000)
的python列表。
使用SparkContext完成以下步骤:
a = sc.parallelize([i for i in range(1, 100000)])
b = sc.parallelize([i for i in range(1, 100000)])
c = a.zip(b)
>>> [(1, 1), (2, 2), -----]
sum = sc.accumulator(0)
c.foreach(lambda (x, y): life.add((y-x)))
其中发出如下警告:
ARN TaskSetManager:阶段3包含一个非常大的任务(4644 KB)。建议的最大任务大小为100 KB。
如何解决此警告?有没有办法处理大小?而且,它会影响大数据的时间复杂度吗?
答案 0 :(得分:9)
答案 1 :(得分:6)
一般的想法是,PySpark会创建与执行程序一样多的java进程,然后将数据传送到每个进程。如果进程太少,则在Java堆空间上会发生内存瓶颈。
在您的情况下,特定错误是您使用sc.parallelize([...])
创建的RDD未指定分区数(参数numSlices
,请参阅docs)。并且RDD默认为一些太小的分区(可能由单个分区构成)。
要解决此问题,只需指定所需的分区数:
a = sc.parallelize([...], numSlices=1000) # and likewise for b
当您指定越来越多的切片时,您会看到警告消息中指定的大小减小。增加切片数量,直到您不再收到警告消息。例如,获取
Stage 0 contains a task of very large size (696 KB). The maximum recommended task size is 100 KB
表示您需要指定更多切片。
在处理内存问题时可能有用的另一个提示(但这与警告消息无关):默认情况下,每个执行程序可用的内存为1 GB左右。您可以通过命令行指定更大的金额,例如使用--executor-memory 64G
。
答案 2 :(得分:4)
扩展@ leo9r评论:考虑不使用python range
,而sc.range
https://spark.apache.org/docs/1.6.0/api/python/pyspark.html#pyspark.SparkContext.range。
因此,您可以避免将大量列表从驱动程序传输到执行程序。
当然,此类RDD通常仅用于测试目的,因此您不希望它们被广播。