我想在相对较大的图上运行Pagerank 35亿个节点900亿个边缘。我一直在尝试使用不同的群集大小以使其运行。但首先是代码:
MAX(city) | MAX(COUNT(city))
-------------------- -------------------
udhna | 4
我从一开始就经历了高垃圾收集问题。因此,我为群集尝试了不同的设置和大小。我主要关注两篇文章:
https://databricks.com/blog/2015/05/28/tuning-java-garbage-collection-for-spark-applications.html
我在亚马逊EMR上运行集群。这些是我当前使用的相关设置:
from pyspark.sql import SparkSession
import graphframes
spark = SparkSession.builder.getOrCreate()
edges_DF = spark.read.parquet('s3://path/to/edges') # 1.4TB total size
verts_DF = spark.read.parquet('s3://path/to/verts') # 25GB total size
graph_GDF = graphframes.GraphFrame(verts_DF, edges_DF)
graph_GDF = graph_GDF.dropIsolatedVertices()
result_df = graph_GDF.pageRank(resetProbability=0.15, tol=0.1)
pagerank_df = result_df.vertices
pagerank_df.write.parquet('s3://path/to/output', mode='overwrite')
我尝试了集群大小,但第一个似乎可行的实验是
具有以下参数的集群:"spark.jars.packages": "org.apache.hadoop:hadoop-aws:2.7.6,graphframes:graphframes:0.7.0-spark2.4-s_2.11",
"spark.dynamicAllocation.enabled": "false",
"spark.network.timeout":"1600s",
"spark.executor.heartbeatInterval":"120s",
"spark.executor.extraJavaOptions": "-XX:+UseG1GC -XX:+UnlockDiagnosticVMOptions -XX:+G1SummarizeConcMark -XX:InitiatingHeapOccupancyPercent=35 -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:OnOutOfMemoryError='kill -9 %p'",
"spark.driver.extraJavaOptions": "-XX:+UseG1GC -XX:+UnlockDiagnosticVMOptions -XX:+G1SummarizeConcMark -XX:InitiatingHeapOccupancyPercent=35 -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:OnOutOfMemoryError='kill -9 %p'",
"spark.storage.level": "MEMORY_AND_DISK_SER",
"spark.rdd.compress": "true",
"spark.shuffle.compress": "true",
"spark.shuffle.spill.compress": "true",
"spark.memory.fraction": "0.80",
"spark.memory.storageFraction": "0.30",
"spark.serializer":"org.apache.spark.serializer.KryoSerializer",
"spark.sql.shuffle.partitions":"1216"
"yarn.nodemanager.vmem-check-enabled": "false",
"yarn.nodemanager.pmem-check-enabled": "false"
"maximizeResourceAllocation": "true"
"fs.s3.maxConnections": "5000",
"fs.s3.consistent": "true",
"fs.s3.consistent.throwExceptionOnInconsistency":"false",
"fs.s3.consistent.retryPolicyType":"fixed",
"fs.s3.consistent.retryPeriodSeconds":"10"
使用--deploy-mode cluster --num-executors 75 --executor-cores 5 --executor-memory 36g --driver-memory 36g --driver-cores 5
进行此配置,时间已经很短了,但是一切正常,但是由于它是对集群的测试,所以总的GC
的存储量很小,甚至在我得到{{ 1}}之所以发生这种情况是因为我将2.7 TB
留给了很少的RAM。因此,我重新运行了整个过程,但是这次用ExecutorLostFailure (executor 54 exited caused by one of the running tasks) Reason: Container from a bad node Exit status: 137.
重新运行了我的node
问题,回来了,我的集群表现得很奇怪。因此,我以为我理解了这样一个问题:--executor-cores 5 --executor-memory 35g
时间较长的原因并不是每个执行者的内存不足。
我启动的下一个群集具有以下参数:GC
因此,像以前一样,更大的群集和每个执行器更大的内存。一切运行顺利,我通过GC
注意到第一步大约花了--deploy-mode cluster --num-executors 179 --executor-cores 5 --executor-memory 45g --driver-memory 45g --driver-cores 5
ram。
我虽然了解一些问题,即我的集群使用更少的内核并扩大每个执行程序的内存可以使程序运行更快,但我猜想它与ganglia
的大小约为25gb无关,它将适合每个执行器的内存并留出计算空间(25GB * 179将近5.5TB)。
因此,我启动的下一个集群具有相同数量的节点,但是我将执行程序的大小调整为:5.5 TB
立即将所有问题归还!通过verts_DF
,集群挂起的次数高达--num-executors 119 --executor-cores 5 --executor-memory 75g
,我可以看到RAM最多填满了9个可用TB中的8个。我感到困惑。
我回过头来再次旋转了GC
集群,幸运的是,使用ganglia
可以轻松完成该集群,因为我可以克隆它。但是现在这种配置也无法正常工作。 --num-executors 179 --executor-cores 5 --executor-memory 45g
倍高的群集立即达到EMR
的已用内存。
这是怎么回事?感觉就像我玩轮盘赌,有时相同的配置有效,而其他时候却没有?
答案 0 :(得分:1)
如果经过一段时间后仍然有人迷失了方向,那就意识到问题出在graphx
或graphframes
如何加载图形上。两者都试图生成它们正在加载的图的所有三元组,它们具有非常大的图分辨率OOM
,这是因为具有35亿个节点和700亿条边的图已经毁了其中的许多。
我通过在pyspark
中实现pagerank编写了一个解决方案。可以肯定它的速度不及scala
,但它可以扩展并且不会遇到所描述的三元组问题。
我在github上发布了它
https://github.com/thagorx/spark_pagerank
答案 1 :(得分:0)
如果您运行的是带有pyspark和graphframes的独立版本,则可以通过执行以下命令来启动pyspark REPL
:
pyspark --driver-memory 2g --executor-memory 6g --packages graphframes:graphframes:0.7.0-spark2.4-s_2.11
对于最新发布的Spark版本,请确保适当地更改SPARK_VERSION
环境变量