我在火花工作中遇到一个让我感到惊讶的错误:
Total size of serialized results of 102 tasks (1029.6 MB) is
bigger than spark.driver.maxResultSize (1024.0 MB)
我的工作是这样的:
def add(a,b): return a+b
sums = rdd.mapPartitions(func).reduce(add)
rdd有~500个分区,func获取该分区中的行并返回一个大数组(一个1.3M双精度或~10Mb的numpy数组)。 我想总结所有这些结果并归还他们的总和。
Spark似乎在内存中保存了mapPartitions(func)的总结果(大约5gb),而不是以递增方式处理它,这需要大约30Mb。
不是增加spark.driver.maxResultSize,有没有办法逐步执行reduce?
更新:实际上,我有点惊讶的是,这两个结果在记忆中有更多的结果。
答案 0 :(得分:5)
这里没有什么特别令人惊讶的。使用reduce
时Spark会对驱动程序进行最终减少。如果func
返回单个对象,则实际上相当于:
reduce(add, rdd.collect())
您可以使用treeReduce
:
import math
# Keep maximum possible depth
rdd.treeReduce(add, depth=math.log2(rdd.getNumPartitions()))
sum(rdd.toLocalIterator())
前一个将以增加的网络交换为代价递归地合并工作者的分区。您可以使用depth
参数调整性能。
后者只会在当时收集一个分区,但可能需要重新评估rdd
,并且该作业的重要部分将由驱动程序执行。
根据func
中使用的确切逻辑,您还可以通过将矩阵拆分为块并逐块执行添加来改善工作分布,例如使用BlockMatrices