0

可能重复:
多处理启动太多 Python VM 实例

我正在尝试使用 python 多进程来并行化 Web 获取,但我发现调用多进程的应用程序被多次实例化,而不仅仅是我想要调用的函数(这对我来说是个问题,因为调用者对一个实例化缓慢的库 - 失去了我从并行性中获得的大部分性能收益)。

我做错了什么或如何避免?

我的应用程序.py:

from url_fetcher import url_fetch, parallel_fetch
import my_slow_stuff

my_slow_stuff.py:

if __name__ == '__main__':
    import datetime
    urls = ['http://www.microsoft.com'] * 20
    results = parallel_fetch(urls, fn=url_fetch)
    print([x[:20] for x in results])

class MySlowStuff(object):
    import time
    print('doing slow stuff')
    time.sleep(0)
    print('done slow stuff')

url_fetcher.py:

import multiprocessing
import urllib

def url_fetch(url):
    #return urllib.urlopen(url).read()
    return url

def parallel_fetch(urls, fn):
    PROCESSES = 10
    CHUNK_SIZE = 1
    pool = multiprocessing.Pool(PROCESSES)
    results = pool.imap(fn, urls, CHUNK_SIZE)
    return results

if __name__ == '__main__':
    import datetime
    urls = ['http://www.microsoft.com'] * 20
    results = parallel_fetch(urls, fn=url_fetch)
    print([x[:20] for x in results])

部分输出:

$ python my_app.py
doing slow stuff
done slow stuff
doing slow stuff
done slow stuff
doing slow stuff
done slow stuff
doing slow stuff
done slow stuff
doing slow stuff
done slow stuff

...

4

2 回答 2

1

用于 Windows 的 Python 多处理模块的行为略有不同,因为 Python 未os.fork()在此平台上实现。尤其:

安全导入主模块

确保新的 Python 解释器可以安全地导入主模块,而不会导致意外的副作用(例如启动新进程)。

在这里,全局class MySlowStuff总是由 Windows 上新启动的子进程评估。要解决这个问题,class MySlowStuff应该只在__name__ == '__main__'.

16.6.3.2。Windows了解更多详情。

于 2011-10-31T13:31:45.023 回答
0

windows 上的多处理模块与 Unix/Linux 中的工作方式不同。在 Linux 上,它使用 fork 命令,并且所有上下文都被复制/复制到新的进程中,就像它在 fork 时一样。

Windows 上不存在系统调用 fork,并且多处理模块必须创建一个新的 python 进程并再次加载所有模块,这就是为什么在python lib 文档中强制您if __name__ == '__main__'在 Windows 上使用 mutiprocessing 时使用该技巧的原因。

这种情况的解决方案是改用线程。这种情况是一个 IO 绑定进程,而您避免 GIL 问题的优势 os multiprocessing 不会影响您。

http://docs.python.org/library/multiprocessing.html#windows中的更多信息

于 2011-10-31T13:32:21.077 回答