我目前正在尝试了解Spark计算的过程以及对内存消耗的影响。在
我在Zeppelin中使用Spark 2.3.2和Python2.7。在
基本上在下面的循环中,我要创建到集合。我用sci-kit-learn构建了一个机器学习模型,在sci-kit-learn计算之后,我对pyspark数据帧进行了大量的数据帧操作。对于每一个我都得到一个表rsmeMaeStep,它有8行10列,有小字符串或双精度值。rsmeMaeAll只是将单个分析加在一起,有8*26=208行,其中10列表示i=26。在
for i in range(26):
df_features_train, df_features_validation = randomizer(dataFiltered)
rsmeMaeStep, rsmeMaeAll = rsmeMaeAnalysis(rsmeMaeAll,df_features_train,df_features_test)
print(i)
我对代码做了一些时间分析。我花了10:42的时间。循环次数为26次或更长,每次循环次数为9.6次。 下一步我有问题。下面的代码应该只是对8到206行的简单聚合。对于i=1,它需要32秒,对于i=7 4:43(长8.8倍),但对于i=26,47分钟后我有0%的时间,或者它失败,并出现内存不足的消息。在
^{pr2}$根据逻辑,我认为每个循环中所有的表都应该被覆盖。只有小的rsmeMaeAll应该在每个循环中增加一点。但它还是一张很小的桌子。在
但Spark的行为可能有所不同。在
据我所知,第一步的sk学习代码是在第一步执行的。如果我正确理解了spark lazy求值,那么当我想打印结果时,代码中的pySpark操作就会开始执行。因此,Spark可能会将所有循环的所有表保存在内存中。对吗?在
如果我是对的,我需要代码在每个循环的末尾直接计算pySpark代码。在
我该怎么做?在
如果我这样做,会在下一个循环中触发覆盖表,还是每次循环都会增加内存消耗?我需要从内存中主动删除表吗?如何删除?在
编辑:我刚集成
rsmeMaeStep.collect()
rsmeMaeAll.collect()
以确保pyspark计算立即完成。 但是第一圈花了55秒。第七局花了10多分钟,在rsmeMaeAll.collect公司49分钟后的第8个环路。出现错误消息:
Py4JJavaError: An error occurred while calling o13488.collectToPython. :java.lang.OutOfMemoryError: Java heap space
我真的不明白每循环时间的指数增长。在我至少能跑10圈之前。那里发生了什么事?在
我认为这个问题与Spark中懒惰的评估有关。由于我收集了所有的信息,pyspark数据帧rsmeMaeAll可能所有产生rsmeMaeAll所需的信息都在我试图计算输出的同时加载到了缓存中。在
基于这个想法,我重新构建了代码,这样Spark就不必再把所有步骤都放在中间了。此外,我集成了一个时间度量,并用两个变量重新构建了旧代码,使一个变量更接近新逻辑,每个变量的计算必须在每个循环结束时完成。在
解决办法如下:
在rsmeMaeAnalysis中,我刚刚计算了一个分析的结果,返回了它们,将它们转换成Pandas数据框,并在Pandas中收集了所有的结果。结果是每次循环都花费了差不多相同的时间,即使在20次循环之后,我也没有内存问题。前十个循环的时间如下:
但后来我想确定的是,在pyspark数据帧中收集结果确实是个问题,因此我构建了一个尽可能接近pandas解决方案的代码,但要在pyspark数据帧中收集结果:
^{pr2}$前八个循环的时间如下:
在最初的版本中,仅使用时间测量,在第7次循环后出现内存不足错误之前,需要花费以下时间:
最后,似乎懒惰求值导致产生rsmeMaeAll所需的大量信息同时加载到缓存中,尽管大多数信息在每个循环结束时都不相关。在
相关问题 更多 >
编程相关推荐