Saf*_*hre 3 python python-3.x python-asyncio
我有一个 Python C 扩展,它从套接字获取数据并处理它,在处理过程中它会释放 GIL。目前我使用 2 个 Python 线程,由于 GIL 释放,它们很好地交织在一起,导致 2 个 CPU 内核上的负载为 90%。
我将如何在 Python 3 asyncio 中实现相同的目标?我找不到正确的 Python-C-API 命令来告诉事件循环它可以去做其他事情。
或者换句话说:如果我的扩展释放了 GIL,这是否自动意味着它不会阻止事件循环中可用的下一项的执行?例如,当我的 C 扩展正在处理第一个套接字的数据时,会读取下一个套接字吗?这是我在任何地方都找不到的。根据我的理解,我可以从多个套接字获取数据,并让更多的 CPU 内核工作。
如果您的扩展是从事件循环内部调用的,则释放 GIL 不会导致事件循环继续。
也就是说,说我做这样的事情:
async def process():
call_your_extension()
asyncio.get_event_loop.create_task(process())
Run Code Online (Sandbox Code Playgroud)
然后在您的扩展中释放 GIL 不会导致事件循环继续。你的例程是同步的。
相反,您可以返回或创建某种类型的可等待对象,然后执行
async def process()
await call_your_extension()
Run Code Online (Sandbox Code Playgroud)
在这个模型中,您的扩展可能是一个带有__await__方法的类。最终,asyncio.futures.Future需要生成一个。事件循环会将完成回调附加到该未来,并且当该完成回调被调用时,process可以恢复。这可能不太适合想要使用多核的东西。事件循环只会在一个线程中运行。
您可以通过使用concurrent.futures和生成可以跨线程运行的未来来获得一些优势。然后,您可以使用asyncio.ensure_future将其转换为asyncio Future. 然而,所有这些都假设事件循环以某种方式使您的扩展受益。如果您可以将套接字中的读数移出扩展程序并移至事件循环代码中,则可能是这种情况。否则,您当前的设计可能是理想的。如果您需要与事件循环模型进行互操作,请查看asyncio.get_event_loop().run_in_executor
| 归档时间: |
|
| 查看次数: |
1317 次 |
| 最近记录: |