如何在Python中编写递归斐波那契算法的多线程版本

时间:2019-01-21 21:05:03

标签: python concurrency

我试图更好地理解Python中的并行化。我在实施并行Fibonacci算法时遇到麻烦。

我一直在阅读有关多处理和线程的文档,但是没有运气。

# TODO Figure out how threads work
# TODO Do a Fibonacci counter

import concurrent.futures


def fib(pos, _tpe):
    """Return the Fibonacci number at position."""
    if pos < 2:
        return pos

    x = fib(pos - 1, None)
    y = fib(pos - 2, None)

    return x + y


def fibp(pos, tpe):
    """Return the Fibonacci number at position."""
    if pos < 2:
        return pos

    x = tpe.submit(fib, (pos - 1), tpe).result()
    y = tpe.submit(fib, (pos - 2), tpe).result()

    return x + y


if __name__ == '__main__':
    import sys

    with concurrent.futures.ThreadPoolExecutor() as cftpe:
        fun = fibp if len(sys.argv) is 3 else fib
        position = int(sys.argv[1])
        print(fun(position, cftpe))
        print(fun.__name__)

命令行输出:

$ time python test_fib_parallel.py 35
9227465
fib

real    0m3.778s
user    0m3.746s
sys     0m0.017s

$ time python test_fib_parallel.py 35 dummy-var
9227465
fibp

real    0m3.776s
user    0m3.749s
sys     0m0.018s

我认为时间应该有很大的不同,但是没有。


更新

好的,所以这些技巧对我有所帮助,并且我使它起作用(比原始版本快得多)。我忽略了原始文章中的玩具代码,只是一小段我要解决的实际问题,这就是要增加决策树(用于家庭作业)。这是CPU限制的问题。它使用ProcessPoolExecutor和Manager进行了解决。

def induce_tree(data, splitter, out=stdout, print_bool=True):
    """Greedily induce a decision tree from the given training data."""

    from multiprocessing import Manager
    from concurrent.futures import ProcessPoolExecutor

    output_root = Node(depth=1)
    input_root = Node(depth=1, data=data)
    proxy_stack = Manager().list([(input_root, output_root)])
    pool_exec = ProcessPoolExecutor()

    while proxy_stack:
        # while proxy_stack:
        #   pass proxy stack to function
        # return data tree
        current = proxy_stack.pop()
        if current[0] is not ():
            pool_exec.submit(grow_tree, proxy_stack, current, splitter)

    finish_output_tree(input_root, output_root)

    return output_root

再次更新

这仍然是错误的,因为我没有正确地在两个进程之间管理splitter。我将尝试其他东西。


最后更新

我试图并行化我的代码中的某个级别。我必须深入挖掘拆分器对象中瓶颈所在的部分。并行版本的速度大约是其两倍。 (错误率很高,因为这只是一个测试样本,而没有足够的数据来实际训练一棵好树。)

代码最终看起来像这样

inputs = [(data, idx, depth) for idx in range(data.shape[1] - 1)]

if self._splittable(data, depth):
      with ProcessPoolExecutor() as executor:
          for output in executor.map(_best_split_help, inputs):
          # ... ...

SEQUENTIAL

$ time python main.py data/spambase/spam50.data
Test Fold: 1, Error: 0.166667
Test Fold: 2, Error: 0.583333
Test Fold: 3, Error: 0.583333
Test Fold: 4, Error: 0.230769
Average training error: 0.391026

real    0m29.178s
user    0m28.924s
sys     0m0.106s

平行

$ time python main.py data/spambase/spam50.data
Test Fold: 1, Error: 0.166667
Test Fold: 2, Error: 0.583333
Test Fold: 3, Error: 0.583333
Test Fold: 4, Error: 0.384615
Average training error: 0.429487

real    0m14.419s
user    0m50.748s
sys     0m1.396s

0 个答案:

没有答案