OmniSheep
@OmniSheep

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

Pythonにおけるメモリ利用について

解決したいこと

Pythonにおける各オブジェクトのメモリ仕様について疑問があり質問させていただきました。

google colaboratoryにおいて、itertoolsを用いて母数が大きい順列を列挙する場合、
itertools.permutations objectを生成することは可能なのにもかかわらず
それをlist()を用いてリスト化しようとするとRAMが不足しクラッシュしてしまいます。

例えば

main.py
import itertools
l = [i for i in range(100)]
all_permutation = itertools.permutations(l,5)

上記コードの場合処理は正常に終了しますが

main2.py
import itertools
l = [i for i in range(100)]
all_permutation = list(itertools.permutations(l,5))

とすると

使用可能な RAM をすべて使用した後で、セッションがクラッシュしました。

となります。

itertools.permutations objectでもそれをリスト化したものでも保存されている順列数と中身は変わらない様に思えるのですが、どういった差でメモリの使用量が変化しているのでしょうか。

端的な回答でなくても、こういったワードで調べて理解を深めればよいといったアドバイスでもよいのでご教授願います。

初学者であり稚拙な文、質問である点ご容赦ください。

0

2Answer

値を返す部分でreturnではなくyieldが使われていることにお気づきでしょうか?
ジェネレータが活躍する良い具体例と出会いましたね。
詳しくは「Python ジェネレータ」などと検索してみてください。

1Like

Comments

  1. @OmniSheep

    Questioner

    回答・アドバイスありがとうございます。
    質問前に上記ドキュメントは一読してreturnではなくyeildになっていることには気が付き、さらっとその差も調べてみてはいたのですがそこがキモだったことには気が付けていませんでした。
    イテレータ・ジェネレータに関する知識が不足していることに気が付けたため、今後学んでいきたいと思います。
    大変参考になるアドバイスありがとうございました。

itertoolsには詳しくなく、Pythonの実装も存じませんが、私は以下のような理解をしています。

itertools.permutations(l,5)は、イテレータです。
イテレータというのは、繰り返しを定義する情報で、この場合は「lから5個取り出す順列」という情報を持っているだけです。
この時点では、結果の数列は生成されていません。

それに対して、list(itertools.permutations(l,5))は、「lから5個取り出す順列」に従い「生成した結果の数列」です。
ここで初めて、先の繰り返しを実際に処理して、[(0, 1, 2, 3, 4), (0, 1, 2, 3, 5), (0, 1, 2, 3, 6), ...というデータが生成されます。

このため、前者に比べて後者はPCのリソースを多く消費します。

イテレータを理解するために、以下を試してみてください。

a = range(100) # イテレータ
b = list(range(100)) # 生成されたリスト
print (a)
print (b)
0Like

Comments

  1. @OmniSheep

    Questioner

    回答・アドバイスありがとうございます。
    イテレータの時点ではまだ作業はしていなく、「どういう風な作業をしろ」といった指令が生成されている感じなのですね。
    イテレータ関連の知識が不足していると実感できたため、今後学んでいきたいと思います。
    具体例も含め大変参考になる回答ありがとうございました。

Your answer might help someone💌