web-dev-qa-db-ja.com

リソースを解放する目的でPySparkでRDDを削除するにはどうすればよいですか?

不要になったRDDがある場合、それをメモリから削除するにはどうすればよいですか?これを行うには、次の情報で十分でしょうか。

del thisRDD

ありがとう!

21
Ego

いいえ、_del thisRDD_では不十分です。RDDへのポインタを削除するだけです。キャッシュされたデータを削除するには、thisRDD.unpersist()を呼び出す必要があります。

参考までに、Sparkは遅延計算のモデルを使用しています。つまり、このコードを実行すると、

_>>> thisRDD = sc.parallelize(xrange(10),2).cache()
_

実際にキャッシュされるデータはなく、RDD実行プランでは 'to be cached'としてのみマークされます。次の方法で確認できます。

_>>> print thisRDD.toDebugString()
(2) PythonRDD[6] at RDD at PythonRDD.scala:43 [Memory Serialized 1x Replicated]
 |  ParallelCollectionRDD[5] at parallelize at PythonRDD.scala:364 [Memory Serialized 1x Replicated]
_

ただし、このRDDの上でアクションを少なくとも1回呼び出すと、キャッシュされます。

_>>> thisRDD.count()
10
>>> print thisRDD.toDebugString()
(2) PythonRDD[6] at RDD at PythonRDD.scala:43 [Memory Serialized 1x Replicated]
 |       CachedPartitions: 2; MemorySize: 174.0 B; TachyonSize: 0.0 B; DiskSize: 0.0 B
 |  ParallelCollectionRDD[5] at parallelize at PythonRDD.scala:364 [Memory Serialized 1x Replicated]
_

Spark UIで、アドレス_http://<driver_node>:4040/storage_を使用して永続化データと永続性のレベルを簡単に確認できます。_del thisRDD_が永続性を変更しないことがわかります。このRDDの、しかしthisRDD.unpersist()は永続化しませんが、コードでthisRDDを使用することはできます(メモリ内に永続化されなくなり、クエリが実行されるたびに再計算されます)

13
0x0FFF

短い答え:次のコードでうまくいくはずです:

_import gc
del thisRDD
gc.collect()
_

説明:

PySparkを使用している場合でも、RDDのデータはJava側で管理されるため、最初に同じ質問をしてみましょう。ただし、PythonではなくJavaを使用します。

Javaを使用していて、RDDへのすべての参照を解放するだけの場合、自動的に永続化を解除するのに十分ですか?

Javaの場合、答えはYESです。 この答え によると、RDDはガベージコレクションされると自動的に永続化されません。 (どうやらその機能は this PR のSparkに追加されました。)

OK、Pythonでは何が起こりますか? PythonでRDDへのすべての参照を削除すると、Java側でそれらが削除されますか?

PySparkは Py4J を使用して、オブジェクトをPythonからJavaに、またはその逆に送信します。 Py4Jメモリモデルドキュメント によると:

オブジェクトがPython VM(参照カウント== 0)でガベージコレクションされると、Java VMで参照が削除されます

ただし、注意してください。RDDへのPython参照を削除しても、RDDはすぐに削除されません。 Pythonガベージコレクターが参照をクリーンアップするまで待つ必要があります。詳細については、Py4Jの説明を参照してください。

gc.collect()の呼び出しも通常は機能します。

では、元の質問に戻りましょう。

これを行うには、次で十分でしょう:

_del thisRDD
_

ほぼ。最後の参照(つまり、_del thisRDD_)を削除し、RDDをすぐに永続化する必要がある場合**、gc.collect()を呼び出します。

**まあ、技術的には、これはJava側のreferenceをすぐに削除しますが、Javaのガベージコレクターが実際にRDDを実行するまで、少し遅延がありますファイナライザにより、データが非永続化されます。

8
Stuart Berg

短い答え:場合によります。

pyspark v.1.3.0ソースコード によると、PipelinedRDDにはdel thisRDDで十分です。これは、Pythonによって生成されるRDDです。マッパー/リデューサー:

class PipelinedRDD(RDD):
    # ...
    def __del__(self):
        if self._broadcast:
            self._broadcast.unpersist()
            self._broadcast = None

一方、RDDクラスには__del__メソッドがないので(おそらく必要です)、自分でunpersistメソッドを呼び出す必要があります。

編集:__del__メソッドが this コミットで削除されました。

5
nonsleepr

参考までに、delの後にgc.collect()をお勧めします(rddが大量のメモリを使用する場合)。

3
joshsuihn