【发布时间】:2021-04-28 04:26:36
【问题描述】:
我有一个大约 190GB 的数据集,被划分为 1000 个分区。
我的 EMR 集群最多允许 10 个r5a.2xlarge TASK 节点和 2 个 CORE 节点。每个节点有 64GB 内存和 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...
我在网上找到的很多这类问题的答案都说要增加 memoryOverhead。我做到了,从 2G 到 10G。我的总executor memory 和memoryOverhead 是50G。 40G 分配给执行者,10G 分配给开销。但我认为我已经达到了极限,因为我无法超过 56。
我认为我已尽一切可能优化我的 Spark 工作:
- 增加分区
- 增加 spark.sql.shuffle.partitions
- 增加执行器和开销内存
但我的工作仍然失败。还有什么我可以尝试的吗?我应该更多地增加我的开销,以便我的执行程序内存/开销内存为 50/50? 我在 ganglia 工作的内存配置文件如下所示:
(急剧下降是当集群由于它们死亡而刷新所有执行器节点时)
任何见解将不胜感激
谢谢
编辑:[解决方案]
感谢Debuggerrr 根据他在回答中的建议,我在帖子中附上了解决我问题的确切解决方案。
- 我有一个大型数据框,我在执行了很多操作后正在重新使用它
其他数据帧的计算。通过使用
persist()方法 (由 Debuggerrr 建议),我能够将其保存到 MEMORY 和 DISC 并简单地调用它而不用清理它的一部分 GC。 - 我还按照他的回答中提到的最佳实践博客 Debuggerrr 计算了正确的执行程序内存、执行程序数量等。但我没有做的是禁用
spark.dynamicAllocation.enabled。该博客指出,如果我们手动计算资源,最好将该属性设置为 false,因为如果您的计算与它不一致,spark 往往会错误分配资源。一旦我将它设置为 false,并设置了正确的 executor 和 spark 属性,它就像一个魅力!
[编辑 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
【问题讨论】:
标签: apache-spark pyspark amazon-emr