私はPython Multiprocessingモジュールを使用してメモリ使用量に関する投稿をいくつか見ました。しかし、質問はここでの問題に答えているようには見えません。私を助けることができます。
マルチプロセッシングを使用してタスクを並行して実行していますが、ワーカープロセスによるメモリ消費が無限に増加することに気付きました。私が気づいたことを再現する小さなスタンドアロンの例があります。
_import multiprocessing as mp
import time
def calculate(num):
l = [num*num for num in range(num)]
s = sum(l)
del l # delete lists as an option
return s
if __== "__main__":
pool = mp.Pool(processes=2)
time.sleep(5)
print "launching calculation"
num_tasks = 1000
tasks = [pool.apply_async(calculate,(i,)) for i in range(num_tasks)]
for f in tasks:
print f.get(5)
print "calculation finished"
time.sleep(10)
print "closing pool"
pool.close()
print "closed pool"
print "joining pool"
pool.join()
print "joined pool"
time.sleep(5)
_
Windowsを実行していますが、タスクマネージャーを使用してメモリ使用量を監視しています。私はPython 2.7.6。
2つのワーカープロセスによるメモリ消費量を以下にまとめました。
_+---------------+----------------------+----------------------+
| num_tasks | memory with del | memory without del |
| | proc_1 | proc_2 | proc_1 | proc_2 |
+---------------+----------------------+----------------------+
| 1000 | 4884 | 4694 | 4892 | 4952 |
| 5000 | 5588 | 5596 | 6140 | 6268 |
| 10000 | 6528 | 6580 | 6640 | 6644 |
+---------------+----------------------+----------------------+
_
上記の表では、タスクの数を変更し、すべての計算の最後で、join
-pool
を実行する前に消費されるメモリを観察しようとしました。 'del'オプションと 'without del'オプションは、それぞれcalculate(num)
関数内の_del l
_行のコメントを解除するかコメントするかどうかです。計算前のメモリ消費量は約4400です。
この例に基づいたプロセスがあり、長期間実行することを意図しています。一晩実行した後、このワーカープロセスが大量のメモリ(〜4GB)を占有していることがわかります。 join
を実行してメモリを解放することはオプションではなく、join
- ingを使用しない方法を見つけようとしています。
これは少し不思議なようです。誰かが似たようなものに遭遇しましたか?この問題を修正するにはどうすればよいですか?
私は多くの研究を行いましたが、問題自体を解決する解決策を見つけることができませんでした。ただし、サーバー側で長時間実行されるコードでは特に価値があるメモリブローアウトをわずかなコストで防止するための適切な作業があります。
解決策は、基本的に、一定数のタスクの後に個々のワーカープロセスを再起動することでした。 pythonのPool
クラスは、maxtasksperchild
を引数として取ります。maxtasksperchild=1000
したがって、各子プロセスで実行される1000のタスクを制限します。 maxtasksperchild
の数に達すると、プールはその子プロセスを更新します。最大タスクに慎重な数を使用すると、消費される最大メモリと、バックエンドプロセスの再起動に関連する起動コストのバランスを取ることができます。 Pool
の構築は次のように行われます:
pool = mp.Pool(processes=2,maxtasksperchild=1000)
私はここに完全なソリューションを置いているので、他の人に役立つでしょう!
import multiprocessing as mp
import time
def calculate(num):
l = [num*num for num in range(num)]
s = sum(l)
del l # delete lists as an option
return s
if __== "__main__":
# fix is in the following line #
pool = mp.Pool(processes=2,maxtasksperchild=1000)
time.sleep(5)
print "launching calculation"
num_tasks = 1000
tasks = [pool.apply_async(calculate,(i,)) for i in range(num_tasks)]
for f in tasks:
print f.get(5)
print "calculation finished"
time.sleep(10)
print "closing pool"
pool.close()
print "closed pool"
print "joining pool"
pool.join()
print "joined pool"
time.sleep(5)