推理基础设施 · Python6.1 协程与 async/await
06
asyncio 基础 · 1 / 5

6.1 协程与 async/await

💡 GPU 一边在算,下一波请求就该开始 tokenize 了,同步写法会浪费 GPU 时间

6.1 协程与 async/await

async def 定义的是“协程函数”,调用它不执行,而是返回一个 coroutine 对象

import asyncio

async def fetch(prompt):
    await asyncio.sleep(0.1)     # 模拟 IO 等待
    return f"[done] {prompt}"

async def main():
    result = await fetch("hi")
    print(result)

asyncio.run(main())

两个关键关键字

  • async def:定义协程函数
  • await:等另一个协程(只能在 async def 里用

同步 vs 异步

  • 同步:必须等这一步做完才能做下一步
  • 异步:发起 IO 后可以先去干别的,IO 好了再回来

示范

import asyncio

async def tokenize(text):
    await asyncio.sleep(0.1)
    return text.split()

async def main():
    toks = await tokenize("hello world")
    print(toks)

asyncio.run(main())

✍️ 练习

写一个协程 fake_infer(prompt, latency_ms=50)

  • await asyncio.sleep(latency_ms / 1000)
  • 返回 f"[fake] {prompt}"

写一个 main()

  • 创建一个 list,包含三个 prompt:"hi""hello""long story please"
  • 用 for 循环依次 await fake_infer(prompt),每次把返回值 appendresults
  • 最后 print(results

注意:main 也是 async def,最后用 asyncio.run(main()) 启动。

💡 思路提示

点开看提示
  1. await 只能用在 async def 函数里
  2. asyncio.run(main()) 是入口
  3. latency_ms / 1000 把毫秒转成秒

✅ 参考解法

写不出来再打开
import asyncio

async def fake_infer(prompt, latency_ms=50):
    await asyncio.sleep(latency_ms / 1000)
    return f"[fake] {prompt}"

async def main():
    prompts = ["hi", "hello", "long story please"]
    results = []
    for p in prompts:
        r = await fake_infer(p)
        results.append(r)
    print(results)

asyncio.run(main())

🔍 进阶思考

现在的代码是“串行”——和同步几乎一样快(甚至更慢,因为有调度开销)。下一节我们用 gather 并发起来。