【问题标题】:Spark Java Heap errorSpark Java 堆错误
【发布时间】:2016-09-06 21:28:50
【问题描述】:

我不确定这里发生了什么以及为什么。

我有一个数据框,它同时作为 pandas 和 spark 数据框加载。

数据框是稀疏的,主要是零。它的尺寸是 56K X 9K。所以没那么大

我还将以下命令放入我的 spark/conf/spark-defaults.conf 文件中

spark.driver.memory              8g
spark.executor.memory            2g
spark.driver.maxResultSize       2g
spark.executor.extraJavaOptions  -XX:+PrintGCDetails -Dkey=value

spark.jars.packages    com.databricks:spark-csv_2.11:1.4.0

如果你看到了,我已经为 Driver 分配了 8GB,为 executor 分配了 2G。我正在使用本地安装在我的 Macbook Pro 上的 Spark。

当我这样做时

recommender_ct.show() 

看到前 5 行,这是我得到的:

---------------------------------------------------------------------------
Py4JJavaError                             Traceback (most recent call last)
<ipython-input-7-8c71bfcdfd03> in <module>()
----> 1 recommender_ct.show()

/Users/i854319/spark/python/pyspark/sql/dataframe.pyc in show(self, n, truncate)
    255         +---+-----+
    256         """
--> 257         print(self._jdf.showString(n, truncate))
    258 
    259     def __repr__(self):

/Users/i854319/spark/python/lib/py4j-0.9-src.zip/py4j/java_gateway.py in __call__(self, *args)
    811         answer = self.gateway_client.send_command(command)
    812         return_value = get_return_value(
--> 813             answer, self.gateway_client, self.target_id, self.name)
    814 
    815         for temp_arg in temp_args:

/Users/i854319/spark/python/pyspark/sql/utils.pyc in deco(*a, **kw)
     43     def deco(*a, **kw):
     44         try:
---> 45             return f(*a, **kw)
     46         except py4j.protocol.Py4JJavaError as e:
     47             s = e.java_exception.toString()

/Users/i854319/spark/python/lib/py4j-0.9-src.zip/py4j/protocol.py in get_return_value(answer, gateway_client, target_id, name)
    306                 raise Py4JJavaError(
    307                     "An error occurred while calling {0}{1}{2}.\n".
--> 308                     format(target_id, ".", name), value)
    309             else:
    310                 raise Py4JError(

Py4JJavaError: An error occurred while calling o40.showString.
: java.lang.OutOfMemoryError: Java heap space

此数据框是使用 Spark 数据框的交叉表创建的,如下所示:

recommender_ct=recommender_sdf.crosstab('TRANS','ITEM')

使用 .show() 时,Recommender_sdf 上面的 spark 数据帧可以正常工作。

熊猫数据框使用相同的交叉表方法,当我在下面这样做时,它工作得很好。

# Creating a new pandas dataframe for cross-tab
recommender_pct=pd.crosstab(recommender_pdf['TRANS'], recommender_pdf['ITEM'])

recommender_pct.head()

这立即生效。

这表明文件很容易被加载到内存中并且可以被 pandas 使用,但是在使用 .show() 或 .head() 时,spark 中的相同数据帧会引发 java heap 错误。并且在抛出错误之前需要很多时间。

我不明白为什么会这样。当可以使用 pandas 轻松访问和打印相同的数据帧时,Spark 不应该比 pandas 更快并且不应该有这个内存问题。

编辑:

好的。当我从对应的 pandas 数据框中获取前几行和几列时,交叉选项卡的 spark 数据框看起来像这样

    TRANS   Bob Iger: How Do Companies Foster Innovation and Sustain Relevance  “I Will What I Want” - Misty Copeland   "On the Lot" with Disney Producers  "Your Brain is Good at Inclusion...Except When it's Not" with Dr. Steve Robbins (please do not use) WDW_ER-Leaders of Minors    1. EAS Project Lifecycle Process Flow   10 Life Lessons from Star Wars  10 Simple Steps to Exceptional Daily Productivity   10 Steps to Effective Listening
0   353 0   0   0   0   0   0   0   0   0
1   354 0   0   0   0   0   0   0   0   0
2   355 0   0   0   0   0   0   0   0   0
3   356 0   0   0   0   0   0   0   0   0
4   357 0   0   0   0   0   0   0   0   0

列名基本上是长文本字符串。并且列值是 0 或 1

【问题讨论】:

  • 你的action操作是什么?可能是一些代码示例?某些动作操作可能会积累数据并产生OOM错误。
  • 上述错误是由于在上面的spark数据帧上做了.show()。基本上我知道 .show() 会将数据从执行程序获取到驱动程序,但是如果相同的数据帧可以由 pandas 加载到内存中并且甚至可以显示结果,那么我不确定为什么这是 spark 的问题
  • "在抛出错误之前需要很长时间。" --> 您正在应用哪些转换?看来转型是罪魁祸首,而不是行动。您是否为转换传递了任何递归函数?
  • 嗯..好点。我在做 .show() 之前应用的唯一转换如下:推荐器_ct=recommender_sdf.crosstab('TRANS','ITEM') 所以基本上将火花数据框的交叉表分成两列。但是请注意,由于我之前已经完成了 .show() ,因此已经评估了采用交叉表的推荐器_sdf spark数据框。因此,只有上述转换应该是有效的。我已经在错误之后的问题中提到了这一点。请检查
  • 我可能是错的,但是当我更多地考虑这个并查看堆栈时,这似乎是 py4j 问题。如果您查看堆栈,show-->gateway_client.send_command --> get_return_value (813) 做了一些事情来创建 OOM,我不确定 py4j 的用途或它是如何工作的,抱歉!

标签: python pandas apache-spark py4j


【解决方案1】:

我如何在 Java 中解决同样的问题: 将需要执行的查询分成 2 个(或更多)部分。执行前半部分,将结果保存到 HDFS(作为 parquet)。创建第二个 SqlContext,从 HDFS 读取前半部分的结果,然后执行后半部分的查询。

【讨论】:

  • 为什么要这样做,因为我认为 pyspark 的全部意义在于自动为您处理任何分区,这样您就可以分析大于 ram 数据集,而无需手动将所有内容解析为块。
猜你喜欢
  • 1970-01-01
  • 2011-03-27
  • 1970-01-01
  • 2015-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-03
  • 2013-03-01
相关资源
最近更新 更多