我正在尝试对一个7节点集群上Cloudera的Spark(2.1.0)中的数据帧进行groupBy操作,总共有大约512GB的RAM。我的代码如下。
ndf = ndf.repartition(20000)
by_user_df = ndf.groupBy(ndf.name) \
.agg(collect_list("file_name")) \
.withColumnRenamed('collect_list(file_name)', 'file_names')
by_user_df = by_user_df.repartition(20000)
by_user_df.count()
ndf是一个包含2列的数据帧,用户ID和文件名。我试图通过userid创建一个文件名列表,以传递给CountVectorizer和集群。
我收到以下错误
java.lang.OutOfMemoryError: Requested array size exceeds VM limit
at org.apache.spark.sql.catalyst.expressions.codegen.BufferHolder.grow(BufferHolder.java:73)
at org.apache.spark.sql.catalyst.expressions.GeneratedClass$GeneratedIterator.processNext(Unknown Source)
at org.apache.spark.sql.execution.BufferedRowIterator.hasNext(BufferedRowIterator.java:43)
at org.apache.spark.sql.execution.WholeStageCodegenExec$$anonfun$8$$anon$1.hasNext(WholeStageCodegenExec.scala:377)
at scala.collection.Iterator$$anon$11.hasNext(Iterator.scala:408)
at org.apache.spark.shuffle.sort.UnsafeShuffleWriter.write(UnsafeShuffleWriter.java:166)
at org.apache.spark.scheduler.ShuffleMapTask.runTask(ShuffleMapTask.scala:96)
at org.apache.spark.scheduler.ShuffleMapTask.runTask(ShuffleMapTask.scala:53)
at org.apache.spark.scheduler.Task.run(Task.scala:99)
at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:322)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
根据我的阅读,这是因为分配的数组要大于VM在连续内存中可以处理的数组,要么大于数组大小的系统最大值。许多建议是通过拆分更多分区来实现更多并行化。
我有大约6k用户和大约7k的文件名。我注意到死亡的执行者大部分时间都花在垃圾收集中。
到目前为止,我已尝试过以下内容:
作为这个问题的更新:我意识到在这种情况下我正在对数据进行二进制聚类,所以我真的只需要每个文件名中的一个。将collect_list
更改为collect_set
会使我获得所需的输出,并且显然足够小以在给定参数内运行。我仍然会尝试修复原始案例。
答案 0 :(得分:0)
首先,我不太明白为什么你需要这么高的分区值。我不知道你在7名工作人员中拥有多少核心,但我怀疑你需要超过200个分区(你使用的分区数量极高,实际上可以解释为什么你的工人死于垃圾收集)
您的问题看起来像JVM定义中的内存问题,所以我认为没有理由增加驱动程序或工作程序内存。
我认为您需要的是设置Xss或Xmx或MaxPermSize,如下所示:How to fix "Requested array size exceeds VM limit" error in Java?
为此,您需要在运行spark时使用--conf spark.driver.extraJavaOptions和--conf spark.executor.extraJavaOptions。
例如:
--conf spark.driver.extraJavaOptions="-Xss10m -XX:MaxPermSize=512M " --conf spark.executor.extraJavaOptions="-Xss10m -XX:MaxPermSize=128M "