我有一个大约 190GB 的数据集,被划分为 1000 个分区。
我的 EMR 集群最多允许 10 个
r5a.2xlarge
TASK 节点和 2 个 CORE 节点。每个节点有 64GB mem 和 128GB EBS 存储。
在我的 Spark 作业执行中,我将其设置为使用
executor-cores 5
、driver cores 5
、executor-memory 40g
、driver-memory 50g
、spark.yarn.executor.memoryOverhead=10g
、spark.sql.shuffle.partitions=500
、spark.dynamicAllocation.enabled=true
但是我的工作总是失败,并出现类似的错误
spark.shuffle.MetadataFetchFailedException
spark.shuffle.FetchFailedException
java.io.IOException: No space left on device
Container Lost
etc...
我在网上找到的很多这类问题的答案都说要增加内存开销。我就是这么做的,从2G到10G。我的
executor memory
和 memoryOverhead
总共是 50G。 40G 分配给执行器,10G 分配给开销。但我认为我已经达到极限了,因为我无法超过 56。
我认为我已尽一切可能来优化我的 Spark 工作:
但我的工作仍然失败。还有什么我可以尝试的吗?我是否应该进一步增加开销,以便我的执行程序内存/开销内存为 50/50? 我的工作的神经节的内存概况看起来像这样:
(急剧下降是当集群因所有执行器节点死亡而刷新它们时)
任何见解将不胜感激
谢谢你
编辑:[解决方案]
我在我的帖子中附加了解决我问题的确切解决方案,这要归功于
Debuggerrr
基于他在答案中的建议。
persist()
方法
(由 Debuggerrr 建议),我能够将其保存到内存和光盘中
并简单地回调它,而不需要清理它的一部分
GC.spark.dynamicAllocation.enabled
。该博客指出,如果我们手动计算资源,最好将该属性设置为 false,因为如果您的计算与其不一致,spark 往往会错误分配资源。一旦我将其设置为 false,并设置正确的执行器和火花属性,它就像一个魅力![编辑2]: 特别适合我的工作的参数是:
--executor-cores 5 --driver-cores 5 --executor-memory 44g --driver-memory 44g --num-executors 9 --conf spark.default.parallelism=100 --conf spark.sql.shuffle.partitions=300 --conf spark.yarn.executor.memoryOverhead=11g --conf spark.shuffle.io.retryWait=180s --conf spark.network.timeout=800s --conf spark.serializer=org.apache.spark.serializer.KryoSerializer --conf spark.dynamicAllocation.enabled=false
Memory overhead
应该是执行器内存的
10%
或
328 MB
。不要将其增加到任何值。
number of executors
。您必须以这样的方式计算它,为 YARN 和后台进程留出一些空间。另外,您可以尝试增加 1 或 2 个核心。
cluster
模式下运行它,无论您分配给执行程序的数量如何,请为其添加 +1,因为 1 个执行程序将在集群模式下被视为驱动程序执行程序。
spark-shell on EMR
上手动执行这些步骤,你就会知道哪部分代码需要花费很多时间来运行。
官方博客了解一些技巧。