Python 3.13自由线程速度提升探索:能用于 CPU 密集型任务吗?

随着 Python 3.13 的发布,我想看看 Python 即将发生的最大变化,我认为到目前为止最令人兴奋的功能是来自 PEP-703 的自由线程 Python,因为它让Python抛弃GIL成为可能,大大提升了python性能。
在 Python 3.13 之前,由于 GIL 的原因,线程用于 IO 绑定任务,Asyncio 也用于 IO,我们可以使用 asyncio.to_thread 包装线程。例如:
await asyncio.to_thread(io_bound_task, "first_arg", optional="optional")但我们可以将它用于 CPU 密集型任务吗?以下是直接从 Asyncio 文档中提取的引述:
注意 由于 GIL 的原因,asyncio.to_thread() 通常只能用于使 IO 绑定的函数成为非阻塞函数,但是,对于发布 GIL 的扩展模块或没有 GIL 的替代 Python 实现,asyncio.to_thread() 也可用于 CPU 绑定的函数,唯一阻止我们的是 GIL,因此 CPU 密集型任务应该不是问题,但是 AsyncIO 这个名字仍然让人感觉有点傻。
以下是使用 AsyncIO 测试脚本:
import argparseimport osimport sysimport timefrom asyncio import get_running_loop, run, to_thread, TaskGroupfrom concurrent.futures import ThreadPoolExecutorfrom contextlib import contextmanagerdef timer():start = time.time()yieldprint(f"Elapsed time: {time.time() - start}")def cpu_bound_task(n):"""A CPU-bound task that computes the sum of squares up to n."""return sum(i * i for i in range(n))async def main():parser = argparse.ArgumentParser(description="Run a CPU-bound task with threads")parser.add_argument("--threads", type=int, default=4, help="Number of threads")parser.add_argument("--tasks", type=int, default=10, help="Number of tasks")parser.add_argument("--size", type=int, default=5000000, help="Task size (n for sum of squares)")args = parser.parse_args()get_running_loop().set_default_executor(ThreadPoolExecutor(max_workers=args.threads))with timer():async with TaskGroup() as tg:for _ in range(args.tasks):tg.create_task(to_thread(cpu_bound_task, args.size))if __name__ == "__main__":print("Parallel with Asyncio")print(f"GIL {sys._is_gil_enabled()}") # type: ignorerun(main())
我在 M3 Macbook Pro 上运行了有和没有 GIL的对比:
不带GIL(python3.13版本)
python parallel_asyncio.pyParallel with AsyncioGIL FalseElapsed time: 0.5552260875701904
带GIL运行:
python parallel_asyncio.pyParallel with AsyncioGIL TrueElapsed time: 1.6787209510803223
结果正如预期的那样,当我们使用 AsyncIO 并发运行代码时,我们观察到了我们期望的结果,速度上的确进行了提升。
        THE END
    
        
        





