You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask中使用Threading并行训练模型失效问题求助

问题:Flask中使用threading实现模型训练并行失败

在Flask中尝试用threading实现模型并行训练,测试代码(含sleep循环)能正常并行并返回状态,但替换为实际的模型训练函数后,必须等待训练完成才会继续执行,无法实现并行。

测试代码:

from threading import Thread
from time import sleep

def model_training():
    global status
    for i in range(1, 11):
        status = i
        sleep(1)

@app.route('/retrain/', methods=['GET', 'POST'])
def retrain():
    for th in threading.enumerate():
        if th.name == "training":
            print("Thread still running")
            message = "Training is already in progress"
            break
    else:
        print("Starting a new job thread")
        message = "Training started"
        t1 = Thread(target=model_training, name="training")
        t1.start()

    return render_template('retrain.html', message=message, models=model_files, num_images=id)

实际模型训练函数:

def model_train():
    dataset, model_config, label_mapping = load_config()
    print("Training: start.")

    model = model_config.model

    model.fit()

    print("Training: end.")
解决方向

核心原因:Python GIL与任务类型不匹配

  • 测试用的model_training是IO密集型任务:sleep()会主动释放全局解释器锁(GIL),让其他线程有机会执行,所以Flask主线程能立即返回响应,实现并行效果。
  • 实际的model_train是CPU/GPU密集型任务:model.fit()执行时,会持续占用GIL(CPU训练场景),导致Python的线程无法真正并行;如果是GPU训练,框架本身可能会占用主线程资源,或者内部线程管理覆盖了你的自定义线程,最终表现为Flask主线程被阻塞,必须等训练结束才返回。

具体解决办法

1. 改用multiprocessing替代threading

多进程绕过GIL限制,每个进程拥有独立的Python解释器和内存空间,适合处理CPU/GPU密集型任务。示例代码:

from multiprocessing import Process

def model_train():
    # 原模型训练代码
    dataset, model_config, label_mapping = load_config()
    print("Training: start.")
    model = model_config.model
    model.fit()
    print("Training: end.")

@app.route('/retrain/', methods=['GET', 'POST'])
def retrain():
    # 检查是否已有训练进程在运行
    from multiprocessing import active_children
    training_running = False
    for p in active_children():
        if p.name == "training":
            training_running = True
            break
    
    if training_running:
        message = "Training is already in progress"
    else:
        message = "Training started"
        p1 = Process(target=model_train, name="training")
        p1.start()
    
    return render_template('retrain.html', message=message, models=model_files, num_images=id)

注意:多进程下全局变量不共享,若需要跟踪训练状态,需用共享内存、文件锁或数据库等外部存储方式。

2. 利用框架自身的异步/多进程支持

比如TensorFlow的model.fit()可以设置workers和use_multiprocessing=True参数,启用多进程数据加载;但这只是优化数据处理环节,若要让训练完全不阻塞Flask主线程,依然推荐用独立的训练进程。

3. 进阶:使用任务队列管理训练任务

如果需要更可靠的任务调度、状态跟踪、失败重试,可采用Celery+Redis(或RabbitMQ)的方案:

  • Flask作为任务生产者,将训练任务提交到队列
  • 后台启动独立的worker进程执行训练任务
  • 通过数据库或缓存记录训练状态,Flask接口可查询状态并返回给前端

内容的提问来源于stack exchange,提问作者iamkk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 04:16:40