Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/356.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何使用asyncio并行计算?_Python_Python 3.x_Parallel Processing_Python Asyncio - Fatal编程技术网

Python 如何使用asyncio并行计算?

Python 如何使用asyncio并行计算?,python,python-3.x,parallel-processing,python-asyncio,Python,Python 3.x,Parallel Processing,Python Asyncio,我有一个代码块,它需要很长时间来执行,并且占用大量CPU。我想运行该块几次,并希望使用我的CPU的全部功率。查看asyncio我知道它主要用于异步通信,但也是异步任务的通用工具 在下面的示例中,time.sleep(y)是我要运行的代码的占位符。在本例中,每个co例程一个接一个地执行,执行大约需要8秒 import asyncio import logging import time async def _do_compute_intense_stuff(x, y, logger):

我有一个代码块,它需要很长时间来执行,并且占用大量CPU。我想运行该块几次,并希望使用我的CPU的全部功率。查看
asyncio
我知道它主要用于异步通信,但也是异步任务的通用工具

在下面的示例中,
time.sleep(y)
是我要运行的代码的占位符。在本例中,每个co例程一个接一个地执行,执行大约需要8秒

import asyncio
import logging
import time


async def _do_compute_intense_stuff(x, y, logger):
    logger.info('Getting it started...')
    for i in range(x):
        time.sleep(y)
    logger.info('Almost done')
    return x * y

logging.basicConfig(format='[%(name)s, %(levelname)s]: %(message)s', level='INFO')
logger = logging.getLogger(__name__)
loop = asyncio.get_event_loop()
co_routines = [
    asyncio.ensure_future(_do_compute_intense_stuff(2, 1, logger.getChild(str(i)))) for i in range(4)]
logger.info('Made the co-routines')
responses = loop.run_until_complete(asyncio.gather(*co_routines))
logger.info('Loop is done')
print(responses)
当我用
asyncio.sleep(y)
替换
time.sleep(y)
时,它几乎立即返回。使用
等待asyncio.sleep(y)
大约需要2秒钟


有没有一种方法可以使用这种方法来并行化我的代码,或者我应该使用
多处理
还是
线程化
?我是否需要将
time.sleep(y)
放入一个线程中?

执行者使用多线程来完成这项任务(或者多线程处理,如果您愿意的话)。Asyncio用于优化经常等待输入、输出操作运行的代码。有时,这可能是写入文件或加载网站

然而,对于cpu密集型操作(不仅仅依赖于等待IO),建议使用类似于线程的东西,而且在我看来,
concurrent.futures
提供了一个非常好的包装,它类似于Asyncio的包装

之所以Asyncio.sleep会使代码运行更快,是因为它会启动函数,然后开始检查协程以查看它们是否准备就绪。这不适合CPU密集型操作,因为没有IO可等待

要将以下示例从多处理更改为多线程,只需将
ProcessPoolExecutor
更改为
ThreadPoolExecutor

以下是一个多处理示例:

import concurrent.futures
import time

def a(z):
    time.sleep(1)
    return z*12

if __name__ == '__main__':
    with concurrent.futures.ProcessPoolExecutor(max_workers=5) as executor:
        futures = {executor.submit(a, i) for i in range(5)}
        for future in concurrent.futures.as_completed(futures):
            data = future.result()
            print(data)

这是中提供的示例的简化版本。

您不需要使用asyncio。当您遇到等待I/O发生的问题时,Asyncio非常有用。密集的计算不是这样的问题。改用多处理。如果您使用的是一些C扩展支持的库,在执行繁重的计算时会释放GIL,则仅使用线程。Asyncio还需要所有代码配合。每个
wait
都是一个位置,您的任务告诉事件循环,如果其他任务没有等待,它愿意让它们运行
time.sleep()
与合作正好相反。它会阻止一切,因此事件循环无法切换任务。
asyncio.sleep()
生成一个协同路由。如果你不等待它,它不会做任何事情,所以是的,你会看到一个即时的回报。谢谢@MartijnPieters,它消除了一些困惑!谢谢你。它似乎不知怎么起作用了。这些函数是并行执行的,但不是并行执行的(我猜)。当执行我的函数时,它会占用整个内核20秒。当执行2个函数时,需要1分钟,并且没有一个内核达到100%。有什么想法吗?处理器不会达到100%,因为你在一个单核上。如果您希望满载cpu,请使用多处理。请记住,您可能希望在启动进程之前预处理您的数据,因为当第二个进程运行时,队列之间的通信有时会很棘手。@Benjamin更新了使用多进程的答案。来自Java,线程在每个核心上运行[帮助我理解了Python中进程和线程的区别。但是,我的实际代码不想在进程中运行,因为我使用了无法pickle的类。因为我没有进程间通信,所以我放弃了漂亮的libs,只使用了一个包装器,用
Popen
启动脚本并从stdout位于
ThreadPoolExecutor
中。由于您的答案解决了所提出的问题,我将接受它。