为什么Spark在内存用尽之前不将DataFrames写入磁盘?

时间:2019-05-20 12:02:50

标签: apache-spark pyspark

我只是一般地同时学习pyspark和Spark,并且开始编写了以下代码,该代码生成了一个随机有向图的片段列表(可能有重复的行)。如果您在装有edge_count=10**9的家用计算机上运行此代码,它将由于内存不足而崩溃(很久以后由于无法将df放入内存而导致崩溃) 。不管batch_size,崩溃发生在大约相同数量的边缘。

很明显,我没有完全理解persist应该做的事情。之所以列出数据帧,是因为我找不到任何干净的方法来创建足够大的单个数据帧,因为它们是不可变的。

我知道可以通过增加堆大小来减轻这种情况,但是我对这里的理论问题更感兴趣。我也知道您可以将persist(<stuff>)替换为checkpoint()来解决此问题;这会强制将每个子图写入磁盘。

import gc
import numpy as np
import pandas as pd
import pyspark


def generate_digraph(edge_count=10**9, batch_size=9*10**4,
                     steps_to_python_gc=2.5*10**7, domain_size=10**8):
    sc = pyspark.context.SparkContext.getOrCreate()
    sc.setCheckpointDir("~/.transitive_closure")
    spark = pyspark.sql.SparkSession(sc)
    spark.conf.set("spark.sql.execution.arrow.enabled", "true")
    batches_to_python_gc = steps_to_python_gc // batch_size
    batch_count = int(np.ceil(edge_count/batch_size))
    domain_size = 10**8
    digraph=[]
    for i in range(batch_count):
        if i%batches_to_python_gc == 0:
            print("Taking out the trash...")
            gc.collect()
        if i == batch_count-1 and edge_count % batch_size > 0:
            batch_size = edge_count % batch_size
        new_origins = np.random.randint(0,domain_size,dtype=np.int32,
                                        size=(batch_size,1))
        new_termini = np.random.randint(0,domain_size,dtype=np.int32,
                                        size=(batch_size,1))
        partial_digraph = pd.DataFrame(np.concatenate(
            [new_origins, new_termini], 1), columns=("origin", "terminus")
            )
        digraph.append(spark.createDataFrame(partial_digraph).
                       persist(pyspark.StorageLevel.DISK_ONLY))
    if i == batch_count-1:
        gc.collect()
        print("Concatenating...")
        df=pd.concat([partial_digraph.toPandas() for partial_digraph in digraph])
    sc.stop()
    return df

当然,有许多分布式计算任务,这些任务涉及将大量已处理的数据写入磁盘。 Spark如何处理这些任务?如何创建驻留在磁盘上的Spark可用大对象?能够在内存中保留一些东西,并在分配其他内存时将其与其他任务并行地写入磁盘,这是特别好的,这是我本来以为我可以持久化的方式(并且我希望我仍然可以,一旦我了解了它是如何工作的。

0 个答案:

没有答案