TensorFlow Keras多进程训练遗留进程挂起、线程资源无法清理问题咨询
问题根因
你遇到的报错和资源泄漏是两个独立问题叠加导致的:
- Keras多进程模式下,
fit结束后不会主动销毁生成器关联的进程池和全局持有的生成器引用,旧进程持有的资源没有释放,新轮次读写全局生成器字典时触发RuntimeError: dictionary changed size during iteration报错 - 每轮循环中反复保存、加载、清空会话的操作会重复触发模型重编译,导致
tensorflow retracing警告,额外占用资源
修复方案
1. 主动清理Keras全局生成器缓存
Keras会将所有多进程模式下使用的生成器存在全局变量keras.utils.data_utils._SHARED_SEQUENCES中,每轮训练结束后清空该缓存即可解决字典读写冲突问题,同时释放子进程持有的生成器引用:
from keras.utils import data_utils # fit执行结束后立即运行 data_utils._SHARED_SEQUENCES.clear()
2. 关闭生成器持有的文件句柄与进程资源
你使用的HDF5ImageGenerator自带stop()方法,会主动关闭H5文件句柄、终止关联的子进程,每轮训练结束后调用即可:
# fit执行结束后立即运行 traingen.stop() validgen.stop() # 清理对象引用 del traingen, validgen
3. 删除冗余的模型保存加载逻辑
你当前每轮保存、加载模型、清空会话的操作完全没有必要,直接修改优化器学习率即可,删除以下冗余代码:
time.sleep(1) model.save(r'./model') time.sleep(1) backend.clear_session() time.sleep(1) model = models.load_model(r'./model') time.sleep(1)
删除后即可消除tf.function重编译的警告,也避免了不必要的IO和内存占用。
4. 强制回收系统残留资源
Windows平台下多进程资源回收有延迟,可配合垃圾回收和多进程模块的活跃子进程检查强制释放资源:
import gc import multiprocessing as mp # 每轮清理后执行 gc.collect() # 调用该方法会自动回收已结束的子进程残留资源 mp.active_children()
优化后训练循环示例
from keras.utils import data_utils import gc import multiprocessing as mp for i in range(1,300): traingen, validgen = getGenerators() lr = 0.003*(0.99**i) print("Round {:}, lr = {:}".format(i,lr)) backend.set_value(model.optimizer.learning_rate, lr) model.fit( x=traingen, epochs=1, verbose=2, validation_data=validgen, shuffle=False, steps_per_epoch=int(len(traingen)), validation_steps=1, max_queue_size=60, workers=10, use_multiprocessing=True ) # 核心清理逻辑 traingen.stop() validgen.stop() del traingen, validgen data_utils._SHARED_SEQUENCES.clear() gc.collect() mp.active_children()
内容的提问来源于stack exchange,提问作者Nyxeria
相关产品推荐
相关产品推荐

