TensorFlow资源驻留由图缓存爆炸、模型对象隐式持有和数据集迭代器未释放共同导致;需统一input_signature、避免全局模型引用、用try/finally释放迭代器。

不是真正的内存泄漏,而是计算图缓存、Python 引用滞留和设备内存池策略共同导致的资源驻留。
tf.function 动态输入触发图缓存爆炸
每次输入 shape 或 dtype 变化,TensorFlow 就会缓存一个新图。比如 batch size 从 1→2→3…连续变化,len(tf.get_default_graph().get_operations()) 会线性增长,显存持续上涨但 tf.keras.backend.clear_session() 无效。
- 强制统一签名:
@tf.function(input_signature=[tf.TensorSpec(shape=[None, 224, 224, 3], dtype=tf.float32)]) - 预处理动态输入:对文本做
padding、对图像做resize或clip_by_value - 禁用自动追踪:
@tf.function(autograph=False)(仅当无控制流时安全)
模型对象被长生命周期变量隐式持有tf.keras.models.load_model() 返回的对象内部绑定了 ConcreteFunction 和底层 Graph。一旦赋值给模块级变量、self.model 或闭包,整个图结构就无法被 GC 回收。
-
del model只删 Python 引用,C++ 层图仍在 - 不要将
model = load_model(...)放在文件顶层 - 长周期服务中改用函数封装,推理前加:
with tf.device("/CPU:0"): model = ...,再del model,最后tf.keras.backend.clear_session()
tf.data.Dataset 迭代器未耗尽残留资源
用 from_generator 或复杂 pipeline 构建数据集时,Iterator 对象持有图节点和 CUDA 缓冲区引用。HTTP 请求中断、异常退出或只取部分 batch,都会让底层资源卡住。
- 必须用
try/finally显式释放:it = iter(dataset); try: next(it) finally: del it - 替代方案:优先用
Dataset.from_tensor_slices().map(...),避免from_generator - 验证线索:
tf.data.experimental.cardinality(dataset)返回-2(unknown)且显存不降
真正难处理的是叠加效应——比如全局 list 里 append 了中间 tf.Tensor,它既拖住计算图,又让 clear_session() 失效。这种混合问题不会在单次调用中暴露,只在高并发、长时间运行的服务里逐步显现。


















