我有一个非常简单的pyspark程序,应该从S3读取CSV文件:
r = sc.textFile('s3a://some-bucket/some-file.csv')
.map(etc... you know the drill...)
运行本地Spark节点时失败(它在EMR中工作)。我收到了OOM错误和GC崩溃。经过进一步检查,我意识到分区数量非常高。在此特定情况下,r.getNumPartitions()
将返回2358041
。
我意识到这完全是我文件的大小(以字节为单位)。当然,这会让Spark崩溃。
我尝试过不同的配置,例如chaning mapred.min.split.size
:
conf = SparkConf()
conf.setAppName('iRank {}'.format(datetime.now()))
conf.set("mapred.min.split.size", "536870912")
conf.set("mapred.max.split.size", "536870912")
conf.set("mapreduce.input.fileinputformat.split.minsize", "536870912")
我还尝试使用repartition
或将分区参数更改为textFile
,但无济于事。
我很想知道是什么让Spark认为从文件大小中获取分区数量是一个好主意。
答案 0 :(得分:2)
一般来说,它没有。正如This is the resulting image eliasah中的his answer很好地解释了minPartitions
使用hadoopConfiguration
JavaSparkContext
(如果没有提供,则为2)和Hadoop输入格式计算的拆分。
后者只会在配置指示的情况下过高。这表明某些配置文件会干扰您的程序。
您的代码可能存在的问题是您使用了错误的配置。应使用sc = ... # type: SparkContext
sc._jsc.hadoopConfiguration().setInt("mapred.min.split.size", min_value)
sc._jsc.hadoopConfiguration().setInt("mapred.max.split.size", max_value)
而不是Spark配置来设置Hadoop选项。看起来您使用Python,因此您必须使用私有{{1}}实例:
{{1}}
答案 1 :(得分:1)
Hadoop 2.6实际上有一个错误可以做到这一点;最初的S3A版本没有为Spark分割提供块大小,默认值“0”表示每个作业一个字节。
以后的版本都应该使用fs.s3a.block.size作为指定块大小的配置选项...类似33554432(= 32 MB)的东西将是一个开始。
如果您使用的是Hadoop 2.6.x.不要使用S3A。这是我的建议。