Python Asynio:无法运行并行Asynio例程

Python Asynio:无法运行并行Asynio例程,python,python-asyncio,Python,Python Asyncio,我使用Asyncio并行处理58个摄像头。首先,我尝试从opencv python的imread方法加载所有图像。我尝试了这两种方法,正常的方法(顺序)和Asynio,但它们都花费了几乎相同的时间 async def loadImage(i): return base64.b64encode(cv2.imread(my_local_path)).decode('utf-8') def loadImageSync(i): return base64.b64encode(cv2.

我使用Asyncio并行处理58个摄像头。首先,我尝试从opencv python的imread方法加载所有图像。我尝试了这两种方法,正常的方法(顺序)和Asynio,但它们都花费了几乎相同的时间

 async def loadImage(i):
    return base64.b64encode(cv2.imread(my_local_path)).decode('utf-8')

def loadImageSync(i):
    return base64.b64encode(cv2.imread("frames_set/Kamera {}.jpg".format(i))).decode('utf-8')
主功能

async def main():

        starttime_lmSync = time.time()
        lm = [loadImageSync(i) for i in range(1,59)]
        print("Loading Images {}".format(time.time() - starttime_lmSync))

        starttime_lm = time.time()
        lm = [loadImage(i) for i in range(1,59)]
        rawImage = await asyncio.gather(*lm)
        print("Loading Images aSync {}".format(time.time() - starttime_lm))
输出:

正在加载图像1.320235013961792

加载映像异步1.3253769874572754

我做错了什么?或者这是预期的结果

加载一批图像后,我想对它们进行解码并将其转换为numpy数组。对于单个图像,它需要约0.02秒,因此为了在Parralel中处理所有图像,我使用asynio

async def process_image(im):
    return  np.asarray(np.frombuffer(base64.b64decode(im), np.uint8),dtype=np.float32).reshape((1080,1920,3))

starttime_process = time.time()
futures = [process_image(img_b64) for img_b64 in rawImage]
res = await asyncio.gather(*futures)
print("total time taken {}".format(time.time() - starttime_process))
输出

总耗时1.2220990657806396

同样,它所花费的时间几乎等于顺序调用所花费的时间。有什么东西我遗漏了吗

Python版本:3.7
OS:Ubuntu16.04

你的
loadImage
函数不是一个合作的协同程序,因此即使你使用了
asyncio.gather
来并行生成它们,它们也会阻塞线程

您需要通过使用线程池将任务委派给不同的线程,以便每个协同程序在单独的线程中运行,而不会相互阻塞

下面是一种使用
线程池执行器的方法:

executor = concurrent.futures.ThreadPoolExecutor(max_workers=60)
由于大多数线程都是I/O绑定的,所以生成60应该不是一个大问题

现在,您可以修改
loadImage
如下:

async def loadImage(i, event_loop, executor):
    return base64.b64encode(await event_loop.run_in_executor(executor, cv2.imread, my_local_path)).decode('utf-8')
上面的内容应该使
loadImage
成为一个(合作的)协同程序,并且您应该看到I/O绑定任务的速度提高


(产生这么多线程和分配资源可能会对速度造成一定的损失)。

嘿,我希望你能从其他人那里得到更全面的答案-->但我认为你只会看到在等待时间很长的代码中使用asyncio可以显著提高速度。据我所知,代码只是在处理数据,这就是为什么您没有看到显著的性能差异。谢谢@ilamaaa。有道理。那么,python中有没有一种方法可以在不使用asynio的情况下加快速度呢。我也试过穿线,但结果几乎是一样的。我一直想好好测试一下这些家伙,巩固我对这些优点和缺点的理解,但我从来没有真正去做过。希望看到您使用多个进程的结果。我尝试了POOL、Threadpool和进程,但时间没有变化:/谢谢。然而,在我的例子中,在使用asyncio之前,我一直在使用线程,但在阅读了您的评论之后,我意识到这个实现也将使用线程,所以我必须不断地聆听这60个流。所以我有一些问题,asyncio在我的案例中值得吗?从python线程转移到asyncio会给我带来一些好处吗?你能为我的用例推荐一个更好的方法吗@heemayl@shahidammer我的经验法则是:如果任务是I/O绑定的,那么选择
async
;如果任务是CPU绑定的,那么选择
multiprocessing
。在我的用例中,这60个工人将全天候(在无限循环中)获得实时流。考虑到这一点,在资源方面,使用asyncio比使用线程有什么好处吗?@shahidammer
asyncio
尝试在单个线程中进行协作多任务处理。在这种情况下,您需要生成一个线程池,将任务推送到线程池中进行工作,因为您的函数不是天生的协作例程。但由于事件循环将完成编排,我认为您肯定会从纯线程中获益。@shahidammer很高兴我能提供帮助。我想强调的是,就性能而言,在做出决定之前,您应该始终进行基准测试。