私は20GBのデータを最初にメモリにロードするプログラムを実行しています。次に、N(> 1000)個の独立したタスクを行い、それぞれが20 GBのデータの一部を使用する(読み取り専用)ようにします。私は現在、マルチプロセッシングを介してこれらのタスクを実行しようとしています。しかし、this answerのように、グローバル変数全体がプロセスごとにコピーされます。私の場合、メモリは96GBしかないので、4つ以上のタスクを実行するのに十分なメモリがありません。この種の問題に対する解決策があるかどうか疑問に思うので、あまりにも多くのメモリを消費することなく、すべてのコアを完全に使用することができます。マルチプロセッシンググローバル変数メモリコピー
答えて
linuxでは、フォークされたプロセスには、親アドレス空間のコピーライト時のビューがあります。フォークは軽量であり、同じプログラムが親と子の両方で実行されますが、子が異なる実行パスを取る点が異なります。小さなexmample、マルチプロセッシングにこれを適用する
parent: 22642 unchanged
child: 22643 unchanged
22643 changed
22642 unchanged
で
import os
var = "unchanged"
pid = os.fork()
if pid:
print('parent:', os.getpid(), var)
os.waitpid(pid, 0)
else:
print('child:', os.getpid(), var)
var = "changed"
# show parent and child views
print(os.getpid(), var)
結果として、この例では、私はグローバル変数にデータをロードします。 Pythonはプロセスプールに送られたデータをpickleするので、私はそれをインデックスのような小さなものにして、グローバルデータ自体を取得させるようにします。
import multiprocessing as mp
import os
my_big_data = "well, bigger than this"
def worker(index):
"""get char in big data"""
return my_big_data[index]
if __name__ == "__main__":
pool = mp.Pool(os.cpu_count())
for c in pool.imap_unordered(worker, range(len(my_big_data)), chunksize=1):
print(c)
Windowsにはプログラムを実行するためのfork-and-execモデルがありません。 Pythonインタプリタの新しいインスタンスを開始し、関連するすべてのデータを子にクローンする必要があります。これは重いリフトです!
Aha。さて、何が起こっているのかを理解する鍵は、コピーオンライトです。あなたがもっと深い理解を持っていなければ、 'mp'について読むときにいくつかのことは矛盾していると感じます。その説明をありがとう、upvote。好奇心のせいで、私はWindowsのせいで 'Managers'を使わなければならない。私の場合は、まず共有リソースを初期化するために別の20GBオブジェクト(元の+ 'Manager' = 40GB)を作成しますか? Docsは、プロセスが_Manager_へのプロキシを介して共有リスト/ dictにアクセスすることを提案しますが、私はテストするために 'mp'で十分なデータを扱ったことがありません。 – roganjosh
ありがとう@tdelaney、結論はPythonのバージョン(私の場合は2.7)と実装方法(pool.map、imap、imap_unordered)に依存していますか? – wh408
@whan - 'map'と' imap'は、すべての処理が完了するのを待って、送信された順に結果を返します。あなたが返品順序を気にしなければ、 'imap_unordered'はより効率的で、結果が大きい場合にはより少ないメモリしか使用しません。マルチプロセッシングは、Python 2.xと3.xではほとんど同じです。 'map'と' imap_unordered'は、順序付けされた結果を望むかどうかによって、どちらも良いオプションです。 – tdelaney
- 1. メモリアクセスとメモリコピー
- 2. メモリコピーがIOSのオリジナル
- 3. トーチ - メモリコピーなしの狭い()
- 4. メモリコピーとメモリは、Delphiでシングル
- 5. メモリコピー速度の比較CPU <-> GPU
- 6. テンソルフローconvert_to_tensorまたはメモリコピーを実行しますか?
- 7. DtoDとPtoPのメモリコピーの違いは何ですか?
- 8. それ自身のメモリコピーを使用しない子プロセスをforkする
- 9. cからgolangにスライスを渡すとメモリコピーが行われますか?
- 10. 2D numpy配列のリストを3D配列にキャストするときのメモリコピー
- 11. 大雑把に、私はすべての場所で、このAPIを持っ割り当てとメモリコピー
- 12. TCPソケットから読み取ったときにメモリコピーがいくつ発生するか
- 13. 変数グローバル変数?
- 14. コンパイラは、通常、複数の連続したメモリコピーを1回の操作に凝縮できますか?次のような
- 15. $ _GETの変数変数
- 16. タイプ(変数)対変数(タイプ)
- 17. 変数スコープとグローバル変数
- 18. Jinja2変数の変数
- 19. マルチレベルオブジェクト内の変数変数
- 20. 変数の玉変数
- 21. 変数内の変数
- 22. ドットソース変数とグローバル変数
- 23. 変数とisExecuting変数
- 24. 変数fetch_assoc()を変数
- 25. UNIX:変数内の変数
- 26. 変数$ 1を変数
- 27. PHP変数変数(CodeIgniter)
- 28. PHP変数が変数
- 29. ローカル変数対インスタンス変数?
- 30. 一息変数変数名
なぜ大量のデータをメモリにロードしていますか?あなたはそのデータで何をしていますか?理想的には、可能な限り小さなチャンクでデータをロードしたいと考えています。 – sytech
@sytech私の仕事の本質は必要です。私は、各プロセスで必要なデータだけをロードすることを考えていましたが、これは同じデータを複数回ロードすることにつながります。 – wh408
各プロセスはデータ全体を処理する必要がありますが、独自の作業、つまり作業の重複の可能性はありませんか?その場合、あなたは 'Manager.dict()' [ここ](https://docs.python.org/2/library/multiprocessing.html#managers)や 'Manager.list(' ) 'を呼び出し、複数の'プロセス 'を生成します。彼らがすべて同じ作業をしている場合、データをチャンクして、各プロセスに独自のチャンクを渡すことができます。私はあなたがコアよりも多くのプロセスを有効に起動できるとは思っていません。あなたは '> 1000'プロセスを望んでいるようですか? – roganjosh