在Python中并行化嵌套函数

时间:2016-11-15 17:52:29

标签: python multithreading parallel-processing

作为Python初学者,我试图并行化函数的某些部分,作为优化例程的输入。该函数f返回给定向量b的对数似然,梯度和粗糙度。在此函数中,有三个独立的循环函数:loop_1loop_2loop_3

最有效的实施是什么?在三个并发进程中并行化三个循环函数或一次并行化一个循环?这怎么可以实现?使用多处理软件包时,我会得到一个' 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

2 个答案:

答案 0 :(得分:1)

有几种方法可以避免您收到的酸洗错误。

如果有意义,选项可以是异步的。有时它会使它变慢,有时会使它变慢。

在这种情况下,它看起来像下面的代码,当我忘记了事情时,我将它用作模板:

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())

Async和await是内置的关键字,如def,for,in等在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())

答案 1 :(得分: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三次。