异步运行同一函数多实例并获取输出:机器学习模型训练异步代码协程未被await报错求助
解决异步协程未被await的问题&实现并行模型训练
首先,你遇到的RuntimeWarning确实是因为直接调用异步函数(async def定义的函数)只会返回一个协程对象,不会实际执行它——必须通过await关键字或者asyncio.run()来触发协程的执行。另外你的示例代码里还有个关键问题:用了同步的time.sleep(),这会阻塞整个异步事件循环,应该换成异步的asyncio.sleep()。
我们一步步来修正并实现你的需求:
第一步:修正单个异步函数的执行逻辑
先把你的示例代码改成可正常运行的版本,解决警告问题并正确获取返回值:
import asyncio nrs_list = [1, 2, 3, 4, 5] def subtract(n): return n - 1 async def subtract_nrs(nrs): # 模拟模型训练逻辑 numbers = {nr: subtract(nr) for nr in nrs} # 替换为异步sleep,避免阻塞事件循环 await asyncio.sleep(5) # 原代码里的循环检查逻辑其实没必要,因为subtract是同步执行的,直接返回结果即可 return numbers # 用asyncio.run()启动顶层协程,这是Python 3.7+推荐的异步入口方式 result = asyncio.run(subtract_nrs(nrs_list)) print(result)
运行这段代码后,你会看到正确输出{1: 0, 2: 1, 3: 2, 4: 3, 5: 4},且不再出现警告。
第二步:实现多个异步任务的并行执行
你的核心需求是并行运行多个模型训练任务,这里可以用asyncio.gather()来同时启动多个协程,等待所有任务完成后统一收集返回值。
比如,假设你要给不同的数据集/模型参数启动多个训练任务:
import asyncio # 模拟不同的训练数据集 dataset_1 = [1,2,3] dataset_2 = [4,5,6] dataset_3 = [7,8,9] # 创建多个并行执行的协程任务 tasks = [ subtract_nrs(dataset_1), subtract_nrs(dataset_2), subtract_nrs(dataset_3) ] # 定义主协程,用于调度所有并行任务 async def main(): # 用gather等待所有任务完成,返回结果列表 all_results = await asyncio.gather(*tasks) # 遍历输出每个任务的结果 for idx, res in enumerate(all_results): print(f"模型训练任务{idx+1}结果: {res}") # 启动主协程 asyncio.run(main())
运行这段代码,三个任务会并行执行(总耗时约5秒,而非串行的15秒),最后会依次输出每个任务的返回值。
针对机器学习训练的额外提示
如果你的模型训练代码是同步的(比如用scikit-learn、PyTorch的同步API),直接放到async函数里可能无法真正并行——因为同步代码会阻塞异步事件循环。这种情况下,建议用asyncio.to_thread()把同步训练任务放到线程池执行,既能利用异步框架的调度能力,又不会阻塞事件循环:
# 假设这是你的同步模型训练函数 def sync_train_model(dataset): # 这里写实际的模型训练逻辑(比如数据加载、训练、评估) return f"训练完成,数据集长度: {len(dataset)}" async def train_model(dataset): # 将同步训练任务提交到线程池,避免阻塞事件循环 result = await asyncio.to_thread(sync_train_model, dataset) return result # 之后同样用asyncio.gather启动多个并行训练任务 async def main(): tasks = [train_model(dataset_1), train_model(dataset_2), train_model(dataset_3)] results = await asyncio.gather(*tasks) print(results) asyncio.run(main())
这样就能真正实现多个模型训练任务的并行执行,同时正确获取所有返回值。
内容的提问来源于stack exchange,提问作者Tim Stack
相关产品推荐
相关产品推荐

