【问题标题】:Multiprocessing issue on Windows 10Windows 10 上的多处理问题
【发布时间】:2020-08-17 12:42:54
【问题描述】:

我正在尝试使用多处理收集网站列表的主页大小。以下是代码:

import time
from multiprocessing import Pool, TimeoutError

start = time.time()


def sitesize(url):
    for url in sites:
        with urllib.request.urlopen(url) as u:
            page = u.read()
            print(url, len(page))


sites = [
    'https://www.yahoo.com',
    'http://www.cnn.com',
    'http://www.python.org',
    'http://www.jython.org',
    'http://www.pypy.org',
    'http://www.perl.org',
    'http://www.cisco.com',
    'http://www.facebook.com',
    'http://www.twitter.com',
    'http://arstechnica.com',
    'http://www.reuters.com',
    'http://www.abcnews.com',
    'http://www.cnbc.com',
]

if __name__ == '__main__': 

    with Pool(processes=4) as pool:
        for result in pool.imap_unordered(sitesize, sites):
            print(result)

print(f'Time taken : {time.time() - start}')

我有一台运行 Python 3.9 的 Windows 10 笔记本电脑。我没有使用 venv。

此代码进入循环 - 执行 4 次,耗时 4 倍。

这里的错误是什么?有人可以帮忙吗?

提前致谢

萨钦

【问题讨论】:

    标签: python multiprocessing windows-10 pool


    【解决方案1】:

    我认为您误解了pool.imap_unordered 的工作原理,提供的函数将使用来自sites 的值之一调用,而在您的情况下,您实际上完全丢弃了提供的url 并循环所有值siteslist。

    你应该这样做

    def sitesize(url):
        with urllib.request.urlopen(url) as u:
            page = u.read()
            print(url, len(page))
    

    请参阅doc

    【讨论】:

    • 非常感谢 - 这解决了它。时间仍然不是 1/4,但我认为这很好。大约是 0.5 倍,可以接受。
    • @Sachin D 1/4 运行时是不可预料的。使用多处理,您会获得一些额外的开销(进程间通信、调度、锁定/管理共享资源,如标准输出和网络堆栈)。
    • 另外,如果你只需要并发来做 IO 的事情,我推荐使用多线程,因为你的瓶颈不是 CPU 而是 IO。看到这个nice tutorial
    【解决方案2】:

    几个问题:

    def sitesize(url):
        result = {}
        for url in sites:
            with urllib.request.urlopen(url) as u:
                page = u.read()
                result[url] = len(page)
        return result
    
    • sitesize 不返回任何内容 --> 请参阅上文了解您需要的内容
    • 不需要循环for result in pool.imap_unordered(sitesize, sites): --> 改为result = pool.map(sitesize, sites)

    【讨论】:

    • pool.imap_unordered(sitesize, sites) 返回一个迭代器。如果我删除 for 循环,它将如何返回结果?
    • 为什么不使用地图呢?
    • 好的,你是说我应该使用 map 创建一个列表吗?我不是在寻找那个。我只是在查看打印 url 和文件大小的输出。如果没有多处理,代码很简单,可以在我的机器上运行 11 秒。根据我的代码进行多处理,需要 44 秒,每个 url 运行 4 次。
    • 如果你按我的方式行事,这将需要 11/4 秒,因为每个核心将在同一时间内处理 1/4 的 URL 列表。
    • 尝试了这两个建议。该代码返回 url 和文件大小的字典(如预期的那样)。但这需要将近 72 秒...
    猜你喜欢
    • 2018-08-07
    • 2020-06-01
    • 2021-01-23
    • 2019-02-16
    • 2017-09-19
    • 1970-01-01
    • 2010-10-03
    • 2018-09-02
    • 2019-08-06
    相关资源
    最近更新 更多