Python の内包表記とジェネレータ式のメモリ使用量比較
リストを構築する際に Python ではリスト内包表記とジェネレータ式の2種類が存在する。 今回、リスト構築時にメモリ使用量にどれだけ差異が発生するのか調査をしてみた。 メモリ使用量の調査には、memory_profilerというパッケージを使用した。
まず、2つのリストのデカルト積のタプルを表示するプログラムでの比較
from memory_profiler import profile
@profile
def main():
"""
Comparision List comprehension VS generator memory usage
"""
colors = "colors" * 1000
sizes = "S" * 100
for shirts in ((color, size) for color in colors for size in sizes):
print(shirts)
[print((color, size)) for color in colors for size in sizes]
if __name__ == "__main__":
main()
Filename: src/listcomp_vs_generator.py
Line # Mem usage Increment Line Contents
================================================
4 10.5 MiB 10.5 MiB @profile
5 def main():
6 """
7 Comparision List comprehension VS generator memory usage
8 """
9 10.5 MiB 0.0 MiB colors = "colors" * 1000
10 10.5 MiB 0.0 MiB sizes = "S" * 100
11 10.5 MiB 0.0 MiB for shirts in ((color, size) for color in colors for size in sizes):
12 10.5 MiB 0.0 MiB print(shirts)
13 15.1 MiB 0.1 MiB [print((color, size)) for color in colors for size in sizes]
次に、1000x1000 のデカルト積を作成した場合
from memory_profiler import profile
@profile
def main():
"""
Comparision List comprehension VS generator memory usage
"""
colors = "colors" * 1000
sizes = "S" * 1000
((color, size) for color in colors for size in sizes)
[(color, size) for color in colors for size in sizes]
if __name__ == "__main__":
main()
Line # Mem usage Increment Line Contents
================================================
4 10.5 MiB 10.5 MiB @profile
5 def main():
6 """
7 Comparision List comprehension VS generator memory usage
8 """
9 10.5 MiB 0.0 MiB colors = "colors" * 1000
10 10.5 MiB 0.0 MiB sizes = "S" * 1000
11 10.5 MiB 0.0 MiB ((color, size) for color in colors for size in sizes)
12 434.6 MiB 5.8 MiB [(color, size) for color in colors for size in sizes]
結果を見ると一目瞭然で、ジェネレータ式の場合だとイテレータプロトコルが要素を一つ一つ作成するので、メモリ使用量もリスト内包表記と比べると 40 倍以上と一目瞭然の差になった
機械学習でも大規模なデータを扱うことが多い、なのでジェネレータ式を意識して書いてメモリ使用量を抑えていきたい。
関連しているかもしれない記事
- AOJの「ITP I」40問をPythonで解いた
- How to write the UnitTest with stdin at Pytest
- 自走プログラマーを読み終えた
- Pythonの関数のデフォルト引数はmutable(上書きされる)
- 遅すぎる `pandas.read_gbq` を使わずに、Google BigQueryから高速にデータを読み込む
📮 📧 🐏: 記事への感想のおたよりをおまちしてます。 お気軽にお送りください。 メールアドレス入力があればメールで返信させていただきます。 もちろんお返事を希望せずに単なる感想だけでも大歓迎です。
このサイトの更新情報をRSSで配信しています。 お好きなフィードリーダーで購読してみてください。
このウェブサイトの運営や著者の活動を支援していただける方を募集しています。 もしよろしければ、Buy Me a Coffee からサポート(投げ銭)していただけると、著者の活動のモチベーションに繋がります✨
Amazonでほしいものリストも公開しているので、こちらからもサポートしていただけると励みになります。