web-dev-qa-db-ja.com

Python 3のConcurrent.futuresとMultiprocessing

Python 3.2は Concurrent Futures を導入しました。これは、古いスレッドと multiprocessing モジュールの高度な組み合わせのようです。

古いマルチプロセッシングモジュールよりもCPUにバインドされたタスクにこれを使用する利点と欠点は何ですか?

この記事 は、作業がはるかに簡単であることを示唆しています-そうですか?

117
GIS-Jonathan

私はconcurrent.futuresより「高度な」とは呼ばないでしょう-それはsimplerインターフェースで、複数のスレッドを使用するかどうかに関係なく同じように動作しますまたは、基礎となる並列化のギミ​​ックとして複数のプロセス。

したがって、「シンプルなインターフェイス」のほぼすべてのインスタンスと同様に、ほぼ同じトレードオフが関係します。利用可能なto学習する;ただし、提供されるオプションが少ないため、最終的には、豊富なインターフェイスでは得られない方法であなたをイライラさせる可能性があります。

CPUにバインドされたタスクに関する限り、それはあまりにも指定が少なすぎてあまり意味がありません。 CPythonでのCPUにバインドされたタスクの場合、高速化を実現するには、複数のスレッドではなく複数のプロセスが必要です。ただし、高速化の程度(ある場合)は、ハードウェア、OSの詳細、特に特定のタスクに必要なプロセス間通信の量に依存します。内部では、すべてのプロセス間並列化の仕掛けが同じOSプリミティブに依存しています。これらのプリミティブを取得するために使用する高レベルAPIは、最終的な速度の主要な要因ではありません。

編集:例

参照した記事に示されている最終コードは次のとおりですが、機能させるために必要なimportステートメントを追加しています。

from concurrent.futures import ProcessPoolExecutor
def pool_factorizer_map(nums, nprocs):
    # Let the executor divide the work among processes by using 'map'.
    with ProcessPoolExecutor(max_workers=nprocs) as executor:
        return {num:factors for num, factors in
                                Zip(nums,
                                    executor.map(factorize_naive, nums))}

代わりにmultiprocessingを使用してもまったく同じことが言えます。

import multiprocessing as mp
def mp_factorizer_map(nums, nprocs):
    with mp.Pool(nprocs) as pool:
        return {num:factors for num, factors in
                                Zip(nums,
                                    pool.map(factorize_naive, nums))}

Python 3.3では、multiprocessing.Poolオブジェクトをコンテキストマネージャーとして使用する機能が追加されたことに注意してください。

どちらが使いやすいですか? LOL ;-)これらは本質的に同一です。

違いの1つは、Poolが非常に多くのさまざまな方法をサポートしているため、登るまでそれがどれほど簡単かcanを認識できないことです。学習曲線をかなり上回っています。

繰り返しますが、これらすべての異なる方法は、長所と短所の両方です。状況によっては柔軟性が必要になる場合があるため、これらは強みです。それらは「できればそれを行う唯一の明白な方法」のために弱点です。 (可能であれば)concurrent.futuresのみに固執するプロジェクトは、そのミニマルなAPIの使用方法に無償の新規性がないため、おそらく長期的に維持しやすいでしょう。

107
Tim Peters

@TimPetersの回答は私にはとてもよく似合いますが、関連する可能性のある経験を追加したかっただけです。

かつて、クラスター間で通信するときに子プロセスが子プロセスを作成することを望んでいました。マルチプロセッシングでこれを行うことはできませんでしたが、concurrent.futuresでは簡単にできました。これは、マルチプロセッシングにこの機能がないためだと思いますが、100%確信はありません。少なくとも、concurrent.futuresの方がはるかに簡単であり、最大で、concurrent.futuresで利用可能な機能ですが、マルチプロセッシングでは利用できません。誰かがこれを確認または拒否できる場合、それは素晴らしいでしょうか?

0
ojunk