2016-11-15 12 views
0

Python初心者として、私は最適化ルーチンへの入力として機能する関数のいくつかのセクションを並列化しようとしています。この関数fは、与えられたベクトルbの対数尤度、勾配およびヘッセ行列を返します。この関数には、3つの独立したループ関数、loop_1,loop_2、およびloop_3があります。Pythonでネストされた関数を並列化する

最も効率的な実装は何ですか? 3つの並行プロセスで3つのループ関数を並列化するか、一度に1つのループを並列化するか?そして、これはどのように実装できますか?私の入れ子のループ関数が一般的な名前空間にないので、マルチプロセッシングパッケージを使用するとき、私は 'pickle'エラーを受け取ります。

def f(b): 

    # Do something computational intensive on b 

    def calc(i, j): 
    return u, v, w 

    def loop_1(): 
    for i in range(1:1000): 
     c, d, e = calc(i, 0) 

     for j in range(1:200): 
     f, g, h = calc(i, j) 

    return x, y, z 

    def loop_2(): 
    # similar to loop_1 

    def loop_3(): 
    # similar to loop_1 

    # Aggregate results from the three loops 

    return u, v, w 

答えて

0

プロセスのプールで機能を開始する必要があります。

import multiprocessing 

pool = multiprocessing.Pool() 
for i in range(3): 
    if i == 0: 
     pool.apply_async(loop_1) 
    elif i == 1: 
     pool.apply_async(loop_2) 
    if i == 2: 
     pool.apply_async(loop_3) 
pool.close() 

loop_1、loop_2、loop_3が同じ操作の同じ関数で、loop_3を3回呼び出すことができます。

+0

このメソッドは、関数の関数に対して酸洗いエラーを生成します。 – Simon

0

受け取った酸洗エラーを避けるにはいくつかの方法があります。

オプションは非同期である可能性があります。ときには遅くなることもありますが、遅くなることもあります。

import asyncio 


def f(): 
    async def factorial(n): 
     f.p = 2 
     await asyncio.sleep(0.2) 
     return 1 if n < 2 else n * await factorial(n-1) 

    async def multiply(n, k): 
     await asyncio.sleep(0.2) 
     return sum(n for _ in range(k)) 

    async def power(n, k): 
     await asyncio.sleep(0.2) 
     return await multiply(n, await power(n, k-1)) if k != 0 else 1 

    loop = asyncio.get_event_loop() 
    tasks = [asyncio.ensure_future(power(2, 5)), 
      asyncio.ensure_future(factorial(5))] 
    f.p = 0 
    ans = tuple(loop.run_until_complete(asyncio.gather(*tasks))) 
    print(f.p) 
    return ans 

if __name__ == '__main__': 
    print(f()) 

非同期とのpython3中で、そのような、デフなどの組み込みのキーワードであるために待っています:私は物事を忘れたときに、それは、コード怒鳴るようになりますその場合

は、私はテンプレットとしてそれを使用します.5。

関数で関数を使用する別の回避策は、代わりにスレッドを使用することです。

from concurrent.futures import ThreadPoolExecutor 
import time 

def f(): 
    def factorial(n): 
     f.p = 2 
     time.sleep(0.2) 
     return 1 if n < 2 else n*factorial(n-1) 

    def multiply(n, k): 
     time.sleep(0.2) 
     return sum(n for _ in range(k)) 

    def power(n, k): 
     time.sleep(0.2) 
     return multiply(n, power(n, k-1)) if k != 0 else 1 

    def calculate(func, args): 
     return func(*args) 

    def calculate_star(args): 
     return calculate(*args) 

    pool = ThreadPoolExecutor() 
    tasks = [(power, (2, 5)), (factorial, (5,))] 
    f.p = 0 
    result = list(pool.map(calculate_star, tasks)) 
    print(f.p) 
    return result 

if __name__ == '__main__': 
    print(f()) 
+0

ありがとうございました!複数のオブジェクトを返す関数に対してコードをどのように適合させることができるか知っていますか? – Sebastiaan

+0

使用する関数では、通常の場合と同様にオブジェクトを返します。私がテストに使用した関数では、タプル、リスト、またはdict、または再帰で続く変数を使用する必要があります。 – Simon

関連する問題