2017-09-22 8 views
3

map()と一緒に使用した場合、multiprocessingライブラリにはかなり新しく、Poolモジュールに関する質問があります。私は4つのワーカースレッドと6つのタスクが完了すると仮定します。私は私がPool.map()は、タスクを処理する方法を理解したいpool.map()は内部的にワークをどのように割り当てますか?

from multiprocessing.dummy import Pool as ThreadPool 

def print_it(num): 
    print num 

def multi_threaded(): 
    tasks = [1, 2, 3, 4, 5, 6] 
    pool = ThreadPool(4) 
    r = pool.map(print_it, tasks) 
    pool.close() 
    pool.join() 

multi_threaded() 

(私はスレッドではなくプロセスを起動したいのでmultiprocessing.dummyを使用して)されていますか? 3つのオプション:

  1. 最初に4つのスレッドを生成し、最初の4つのタスクを完了してスレッドを終了させますか?その後、残りのタスクのために2つの新しいスレッドを生成しますか?
  2. いくつかのスレッドがタスクを完了するとすぐに4スレッドを割り当て、4スレッドを割り当てます。同じスレッドに新しいタスクを割り当てます。
  3. 他の方法です。

この洞察は、Pool.map()をより効果的に使用することを考えるのに役立ちます。

+0

私が知っているプールはすべて実際には(2)です。しかし、私はこの特定のライブラリを知らないし、一般的に私は主にPython +マルチスレッドの経験が残念ながらある。私はいくつかの限られたスマートな解決策はかなり可能だと思います。詳細な解答は幸運です。 – peterh

+0

'print_it'関数を' sleep'とすることで何が起こるかを調べるためのテストを行うことができます。そして、Python 3.6でこのテストを行うと、それを処理する余分なスレッドがあるとすぐに新しいタスクが始まるように見えます。 – quamrana

+0

なぜ[ソースを読む](https://github.com/python/cpython/blob/5e02c7826f9797fb3add79b608ef51f7a62b3e5a/Lib/multiprocessing/pool.py#L146)、自分で見てみませんか? 'ThreadPool'クラスは通常の' multiprocessing.pool.Pool'のサブクラスで、いくつかのものをオーバーライドします(望むなら、ファイルの最後に定義があります)。 – Blckknght

答えて

1

プールの定義方法によって異なります。

あなたの例でやったように、あなたの(2)が起こります。あなたのプールを初期化するとすぐにプールに応じたスレッドやプロセスが起動します(Pool__init__()で発生します - これを実行するためにタスクを送信する必要はありません)。タスクが到着して実行されると、スレッドまたはプロセスは終了せず、待機する状態に戻り、より多くの作業を待っています。

しかし、それは異なる方法で動作すると定義できます。プールにmaxtasksperchildパラメータを追加できます。作業者がこの量の作業を完了するとすぐに終了し、新しい作業者がすぐに立ち上げられます(作業を最初に行う必要はなく、作業者が出るとすぐに起動します)。これはプールクラスPool._maintain_pool()Pool._repopulate_pool()の機能で管理されます。

作業者が無期限に起動して実行するようにするには、今やっていることをやってください。これが起こります。あなたの労働者が開始時に起動して終了し、いくつかのタスク(必要であれば1つでも)の後に終了して更新するには、maxtasksperchildを使用します。プロセスやスレッドが必要になる前にプロセスやスレッドを起動したくない場合は、Poolを使用しないでください。スレッドやプロセスを必要に応じて起動し、自分で管理します。

これが役に立ちます。

+0

それは素晴らしい答えです。ありがとうございます。 – Pranjal