Apache spark For循环在EMR中保持重新启动(pyspark)

Apache spark For循环在EMR中保持重新启动(pyspark),apache-spark,pyspark,memory-leaks,nested-loops,amazon-emr,Apache Spark,Pyspark,Memory Leaks,Nested Loops,Amazon Emr,我有一个嵌套的for循环,它在内部循环中对一个数据帧执行10次操作,并在完成内部循环后将生成的10个数据帧合并到一个数据帧中 更新:我使用字典创建数据帧列表来存储每个操作,然后在内部循环结束时合并它们 然后,它将其写入带有outloop迭代编号的拼花地板文件。 outerloop有6次迭代,因此应生成6个拼花文件 事情是这样的: train=0 for i in range(0,6): train=train+30 #For loop to aggregate input and

我有一个嵌套的for循环,它在内部循环中对一个数据帧执行10次操作,并在完成内部循环后将生成的10个数据帧合并到一个数据帧中

更新:我使用字典创建数据帧列表来存储每个操作,然后在内部循环结束时合并它们

然后,它将其写入带有outloop迭代编号的拼花地板文件。 outerloop有6次迭代,因此应生成6个拼花文件

事情是这样的:

train=0
for i in range(0,6):
    train=train+30
    #For loop to aggregate input and create 10 output dataframes
    dfnames={}
    for j in range(0,10):
        ident="_"+str(j)  
        #Load dataframe of around 1M rows
        df=spark.read.parquet("s3://path")
        dfnames['df'+ident]= #Perform aggregations and operations
    #Combine the 10 datframes into a single df
    df_out=df_1.uniionByName(d_2).unionByName(df_3)...unionByName(df_10)
    #Write to output parquet file
    df_out.write.mode('overwrite').parquet("s3://path/" + str(train) +".parquet"
在完成外循环的第三次迭代之前,它似乎工作得很好。然后出于某种原因,它使用另一个尝试id重新启动循环。 因此,我得到了前3个文件,但它没有进入第4次迭代,而是重新启动以重新生成第一个文件。我没有得到任何失败的阶段或工作

我已经尝试过单独使用伪变量和打印语句运行for循环(不加载大型数据帧等),它们可以很好地完成。 我认为这与循环后刷新内存的方式有关

以下是我的EMR Spark运行条件: 我在一个EMR集群上运行它,该集群有5个执行器、5个驱动程序节点和10个实例,总共有50个核心。spark executor和driver内存分别为45G,总共约583G。 典型的随机读取为250G,随机写入为331G

一些相关的Spark环境变量如下所示:

在循环或内存管理方面,我有没有做错什么?
如有任何见解,将不胜感激

您是如何获得df1、df2。。。在这条线之前

#将10个数据帧组合成一个单独的df df_out=df1.uniionByName(d2).unionByName(df3)…unionByName(df10)

我的猜测是,您的数据帧计划正在变得越来越大,这可能会引起问题

我建议在内部循环中创建一个数据帧列表,并使用
reduce
方法合并它们

像下面这样

from functools import reduce
from pyspark.sql import DataFrame
df_list = []
for j in range(0,10):  
        #Load dataframe of around 1M rows
        df = spark.read.parquet("s3://path")
        transformed_df = #do your transforms
        df_list.append(transformed_df)

final_df = reduce(DataFrame.unionByName, df_list)


你是如何得到你的df1,df2。。。在这条线之前

#将10个数据帧组合成一个单独的df df_out=df1.uniionByName(d2).unionByName(df3)…unionByName(df10)

我的猜测是,您的数据帧计划正在变得越来越大,这可能会引起问题

我建议在内部循环中创建一个数据帧列表,并使用
reduce
方法合并它们

像下面这样

from functools import reduce
from pyspark.sql import DataFrame
df_list = []
for j in range(0,10):  
        #Load dataframe of around 1M rows
        df = spark.read.parquet("s3://path")
        transformed_df = #do your transforms
        df_list.append(transformed_df)

final_df = reduce(DataFrame.unionByName, df_list)


尽量不要将Python数据结构与Spark数据结构相结合

您希望将for循环转换为设计形式的map reduce,foreach

除此之外,您还可以在每次迭代中创建一个缓存/火花检查点,以避免从头开始重新运行整个DAG

要缓存数据,请执行以下操作:

df.cache()
检查点

spark.sparkContext.setCheckpointDir('<some path>')
df.checkpoint()
spark.sparkContext.setCheckpointDir(“”)
df.checkpoint()

一旦您使用spark结构而不是python结构,这些将显示性能和规模的改进。例如,用foreach替换For循环,用map reduce替换列表的并集。

尽量不要将Python数据结构与Spark数据结构结合起来

您希望将for循环转换为设计形式的map reduce,foreach

除此之外,您还可以在每次迭代中创建一个缓存/火花检查点,以避免从头开始重新运行整个DAG

要缓存数据,请执行以下操作:

df.cache()
检查点

spark.sparkContext.setCheckpointDir('<some path>')
df.checkpoint()
spark.sparkContext.setCheckpointDir(“”)
df.checkpoint()

一旦您使用spark结构而不是python结构,这些将显示性能和规模的改进。例如,用foreach替换For循环,用map reduce替换列表的并集。

我更新了帖子以显示该部分。我使用字典
dfnames
将生成的10个数据帧存储为
df_1
df_2
、df_3`等。。然后是名字。这10个数据帧中的每一个都是唯一的,我想在内部循环之后简单地合并它们。“reduce”方法会以任何方式修改内容吗?另外,
append
函数是否会将追加的dfs的内容保留在单个节点中而不是分布式节点中?
reduce
方法不会修改内容。它只是将在其参数中传递的特定函数应用于所有列表元素
append
只是将数据帧追加到列表中,而数据帧只是计划,它们不包含任何数据。基本上,您的列表将有对每个迭代的每个转换的引用。类似这样的
[DataFrame[comment:bigint,inp\u col:string,inp\u val:string],DataFrame[comment:bigint,inp\u col:string,inp\u val:string],DataFrame[comment:bigint,inp\u col:string,inp\u val:string]
我尝试了
append
方法。但我有一个内存堆错误:(我更新了我的帖子来展示这一部分。我使用字典
dfnames
将生成的10个数据帧存储为
dfu 1
dfu 2
,df_3`等,然后是unionByName。这10个数据帧中的每一个都是唯一的,我只想在内部循环后合并它们。“reduce”方法会以任何方式修改内容吗lso
append
函数是否将附加dfs的内容保留在单个节点中,而不是分布式的?
reduce
方法不会修改内容。它只是将参数中传递的特定函数应用于所有列表元素。
append
只是将数据帧附加到列表中,而数据帧是我们只是计划,它们不包含任何数据。基本上,您的列表将对每次迭代的每个转换都有引用。类似这样的
[DataFrame[comment:bigint,inp\u col:string,inp\u val:string],DataFrame[comment:bigint,inp\u col:string,inp\u col:string],DataFrame[comment:bigint,inp\u col:st]