gevent和多进程的区别

问题描述 投票:0回答:2

我正在学习如何让我的脚本运行得更快。我认为并行是一个好方法。所以我尝试了 gevent 和多处理。但我对它不同的结果感到困惑。举两个我遇到的例子吧

例1:

a=np.zeros([3])
def f(i):
    a[i]=1
    print a
def f_para():
    p=multiprocessing.Pool()
    p.map(f, range(3))

def f_asy():
    threads = [gevent.spawn(f, i) for i in xrange(3)]
    gevent.joinall(threads)

f_para()
[ 0.  1.  0.]
[ 0.  0.  1.]
[ 1.  0.  0.]

f_asy()
[ 1.  0.  0.]
[ 1.  1.  0.]
[ 1.  1.  1.]

我发现使用多处理,全局对象

a
永远不会改变脂肪,并且在运行
f_para()
之后,
a
仍然是原始数组。运行时
f_asy()
,不一样了,
a
变了。

前2:

def f2(i):
    subprocess.call(['./a.out', str(i)])
    time.sleep(0.2)

def f2_loop():
    for i in xrange(20):
        f2(i)

def f2_para():
    p=multiprocessing.Pool()
    p.map(f2, range(20))

def f2_asy():
    threads = [gevent.spawn(f2, i) for i in xrange(20)]
    gevent.joinall(threads)

%timeit -n1 f2_loop()
1 loop, best of 3: 4.22 s per loop
%timeit -n1 f2_asy()
1 loop, best of 3: 4.22 s per loop
%timeit -n1 f2_para()
1 loop, best of 3: 657 ms per loop

我发现

f2_asy()
不会减少运行时间。而
f2_asy()
的输出是一一的,就像
f2_loop()
一样,所以我认为
f2_asy()
没有并行。

a.out
是一个简单的C++代码:

 #include <iostream>

 int main(int argc, char* argv[])
 {
   std::cout<<argv[1]<<std::endl;
   return 0;
 }

所以我的问题是:

  1. 为什么在例1中,

    f_para
    可以改变全局数组的值
    a

  2. 为什么在前2中,

    f2_asy
    不能并行?

有人知道 gevent 和 multiprocessing 之间的区别吗?如果您愿意解释,我将非常感激。

python python-2.7 parallel-processing multiprocessing gevent
2个回答
3
投票

ex1:

当您使用多进程时,每个进程都有单独的内存(与线程不同)

ex2:

gevent 不创建线程,它创建 Greenlets(协程)!

Greenlet 都在主程序的操作系统进程内部运行,但协同调度。

在任何给定时间只有一个 greenlet 正在运行。

这与多处理或线程库提供的任何真正的并行结构不同,后者执行由操作系统调度的旋转进程和 POSIX 线程,并且是真正并行的。


0
投票

对于 ex2:

对于 gevent 22.10,您应该在使用文档中介绍的标准模块(如

socket
subprocess
)之前进行猴子修补:

超越插座 当然,标准库的其他几个部分可能会阻塞整个解释器并导致序列化行为。 gevent 还提供了其中许多的合作版本。它们可以通过单独的函数独立修补,但大多数使用猴子修补的程序都希望使用 gevent.monkey.patch_all() 函数修补整个推荐的模块集:

from gevent import monkey; monkey.patch_all()
import subprocess # it's usable from multiple greenlets now

使用猴子补丁,

multiprocess
gevent
的函数的执行时间相似。

© www.soinside.com 2019 - 2024. All rights reserved.