使用numpy数组和共享内存并行化python循环

tia*_*ago 23 python parallel-processing numpy shared-memory multiprocessing

我知道关于这个主题的几个问题和答案,但是没有找到这个特定问题的满意答案:

什么是简单的共享内存并行化python循环的方法是什么?numpy数组是通过numpy/scipy函数操作的?

我不是在寻找最有效的方法,我只想要一些简单的实现,当循环不是并行运行时不需要重大的重写.就像OpenMP在低级语言中实现一样.

我在这方面看到的最好的答案就是这个,但这是一种相当笨重的方式,需要一个人将循环表达成一个带有单个参数的函数,几行共享数组转换crud,似乎需要并行函数从中调用__main__,它似乎从交互式提示(我花了很多时间)中运行良好.

有了Python的所有简单性,这真的是解决循环问题的最佳方法吗?真?这在OpenMP方式中并行化是微不足道的.

我仔细阅读了多处理模块的不透明文档,但却发现它非常通用,除了简单的循环并行化之外它似乎适合所有东西.我对设置Managers,Proxies,Pipes等不感兴趣.我只是有一个简单的循环,完全并行,在任务之间没有任何通信.使用MPI来平行这样一个简单的情况似乎有些过分,更不用说在这种情况下它将是内存效率低下的.

我没有时间去了解Python的众多不同的共享内存并行包,但是想知道是否有人在这方面有更多经验并且可以向我展示一种更简单的方法.请不要建议串行优化技术,如Cython(我已经使用它),或使用并行numpy/scipy函数,如BLAS(我的情况更一般,更平行).

pv.*_*pv. 18

使用Cython并行支持:

# asd.pyx
from cython.parallel cimport prange

import numpy as np

def foo():
    cdef int i, j, n

    x = np.zeros((200, 2000), float)

    n = x.shape[0]
    for i in prange(n, nogil=True):
        with gil:
            for j in range(100):
                x[i,:] = np.cos(x[i,:])

    return x
Run Code Online (Sandbox Code Playgroud)

在2核机器上:

$ cython asd.pyx
$ gcc -fPIC -fopenmp -shared -o asd.so asd.c -I/usr/include/python2.7
$ export OMP_NUM_THREADS=1
$ time python -c 'import asd; asd.foo()'
real    0m1.548s
user    0m1.442s
sys 0m0.061s

$ export OMP_NUM_THREADS=2
$ time python -c 'import asd; asd.foo()'
real    0m0.602s
user    0m0.826s
sys 0m0.075s
Run Code Online (Sandbox Code Playgroud)

这可以并行运行,因为np.cos(像其他ufuncs一样)会释放GIL.

如果您想以交互方式使用它:

# asd.pyxbdl
def make_ext(modname, pyxfilename):
    from distutils.extension import Extension
    return Extension(name=modname,
                     sources=[pyxfilename],
                     extra_link_args=['-fopenmp'],
                     extra_compile_args=['-fopenmp'])
Run Code Online (Sandbox Code Playgroud)

和(删除asd.soasd.c第一):

>>> import pyximport
>>> pyximport.install(reload_support=True)
>>> import asd
>>> q1 = asd.foo()
# Go to an editor and change asd.pyx
>>> reload(asd)
>>> q2 = asd.foo()
Run Code Online (Sandbox Code Playgroud)

所以是的,在某些情况下,您可以通过使用线程进行并行化.OpenMP只是一个花哨的线程包装器,因此只需要Cython就可以获得更简单的语法.没有Cython,你可以使用threading模块---类似于多处理(并且可能更强大),但你不需要做任何特殊的事情来将数组声明为共享内存.

但是,并非所有操作都会释放GIL,因此YMMV的性能.

***
Run Code Online (Sandbox Code Playgroud)

另一个可能有用的链接从其他Stackoverflow答案中删除 - 另一个多处理接口:http://packages.python.org/joblib/parallel.html