2017-04-11 11 views
0

私はPythonでマルチプロセッシングプールを使用してバイナリツリーのマルチスレッドビルディングを実装しようとしています。主な考え方は、N個のハードウェアスレッドを利用できるということです。特定のレベルでは、ツリーの各ブランチを別々のスレッドに作成したいと考えています。データの依存関係はなく、再帰呼び出しのそれぞれは独自のデータで動作するため、データ競合に関わる問題はありません。従って私は私がマルチプロセッシング・プールを使用することを決めた、GILの制約について精通しています:マルチプロセッシングプールを備えたPythonツリービルド - スピードアップなし

​​

問題は、私は任意のスピードアップを取得することはできませんよです。ツリーを作成する関数は次のようになります。

def createTreeMT(points, pool, level = 2): 
    # If there are no more points to process 
    if len(points) < 1: 
     return 

    # Divide points into two groups: 
    left_points = .... 
    right_points = .... 

    tree = Tree() 

    if(level == 0): 
     if len(left_points) > 0: 
      leftPointsResult = pool.apply_async(createTree, (left_points)) 
     if len(right_points) > 0: 
      rightPointsResult = pool.apply_async(createTree, (right_points)) 

     if(leftPointsResult): 
      tree.left = leftPointsResult.get() 
     if(rightPointsResult): 
      tree.right = rightPointsResult.get() 
    else: 
     if len(left_points) > 0: 
      tree.left = createTreeMT(left_points, pool, level-1) 

     if len(right_points) > 0: 
      tree.right = createTreeMT(right_points, pool, level-1) 

    return tree 


def createTree(points): 
    # If there are no more points to process 
    if len(points) < 1: 
     return 

    # Divide points into two groups: 
    left_points = .... 
    right_points = .... 

    tree = Tree() 

    if len(left_points) > 0: 
     tree.left = createTree(left_points) 

    if len(right_points) > 0: 
     tree.right = createTree(right_points) 

    return tree 

私は何か間違っていますか?標準のPython 2.7でこのようなタスクを実行するより良い方法はありますか?

答えて

0

apply_asyncは、AsyncResultオブジェクトを返します。メインプロセスがget関数を呼び出すと、結果が計算されるまでブロックされます。したがって、メインプロセスは、作成中の各サブタスクを常にブロックしています。したがって、スピードアップはありません!

1つのオプションは、apply_asyncで "callback"オプションを使用することです。

if(level == 0): 
    if len(left_points) > 0: 
     leftPointsResult = pool.apply_async(
      createTree, (left_points), 
      callback=lambda x: tree.left=x) 
    if len(right_points) > 0: 
     rightPointsResult = pool.apply_async(
      createTree, (right_points), 
      callback=lambda x: tree.right=x) 

if(level == 0): 
    if len(left_points) > 0: 
     leftPointsResult = pool.apply_async(createTree, (left_points)) 
    if len(right_points) > 0: 
     rightPointsResult = pool.apply_async(createTree, (right_points)) 

    if(leftPointsResult): 
     tree.left = leftPointsResult.get() 
    if(rightPointsResult): 
     tree.right = rightPointsResult.get() 

結果の準備ができたら、コールバックラムダ関数が呼び出されます:つまり、あなたの次のコードを交換してください。コードでわかるように、結果がプールプロセスによって計算されるので、ツリーは適切に並列に埋められます。

+0

ありがとうございました!コールバックラムダに 'tree'をバインドするにはいくつかの回避策が必要でしたが、それはcurrecltyを実行します。それは私にどんなスピードアップも与えません - コードはさらに遅く走ります。 – pSoLT

+0

あなたはいくつのポイントでテストしていますか?あなたがこれを実行しているマシンにいくつのコアがありますか? –

+0

コードは4コアのi7-6700 CPUを実行し、〜50000ポイントでテストしていますが、ちょっと見えるかもしれませんが、1000〜10000の整数のベクトルであると考えてください。 – pSoLT

関連する問題