Memory Leak investigation

用户在使用 Faster Whisper(模型为 small,设备为 CUDA)进行批量音频转写时,以循环方式反复调用 model.transcribe() ,每次处理约 4.5 MB 的 9 分钟音频文件。持续数小时后,系统内存(RAM)被占满,SageMaker 或 EC2 实例上的 Worke

Memory Leak investigation

Memory Leak investigation

快速结论:在重复调用 model.transcribe() 处理短音频时,系统内存(RAM)会持续增长,最终导致进程被 OOM Killer 终止。优先排查音频解码阶段的内存泄漏,尝试在每次转写后手动触发垃圾回收,或复用 faster_whisper.decode_audio() 输出。

问题场景

用户在使用 Faster Whisper(模型为 small,设备为 CUDA)进行批量音频转写时,以循环方式反复调用 model.transcribe(),每次处理约 4.5 MB 的 9 分钟音频文件。持续数小时后,系统内存(RAM)被占满,SageMaker 或 EC2 实例上的 Worker 进程被 SIGKILL 杀死。问题在 AWS SageMaker 和 EC2(ml.g4dn.xlarge,CUDA 11,Python 3.10)上均被复现。

报错原文

[ERROR] Worker (pid:25) was sent SIGKILL! Perhaps out of memory?

以及在内存监控中观察到的持续增长:

Baseline
1430.97856
1431.109632
...
1574.223872
1594.605568
...
1630.000000 (示例增长趋势,单位 MB)

原因分析

可能原因:音频解码(audio decoding)阶段存在内存泄漏。Issue 维护者通过实验发现:在每次调用 model.transcribe() 时,如果每次都传入原始音频文件路径,内存使用会逐步上升;但如果预先将音频解码一次(使用 faster_whisper.decode_audio()),然后将解码后的数据重复传入 model.transcribe(),内存则保持平坦,不再增长。此外,强制在每次转写后运行 gc.collect() 也能抑制内存增长,说明部分内存未及时被 Python 垃圾回收器回收。

环境排查

  • 确认 Python 版本:Python 3.10(已知环境)
  • 确认 CUDA 版本:CUDA 11(已知环境)
  • 确认 faster-whisper 版本:建议检查是否为最新版,或参考 Issue 中对应版本
  • 确认是否使用 GPU 设备:device=”cuda” 或 device=”CUDA”(大小写敏感,建议统一为小写 “cuda”)
  • 确认系统内存(RAM)大小:例如示例中 16 GB,观察基线内存约 1.4 GB
  • 可选:安装 psutil 库用于监控进程内存

解决步骤

  1. 手动触发垃圾回收(可优先尝试):在每次 model.transcribe() 调用后,显式调用 gc.collect()。实测可稳定内存占用。
  2. 复用解码后的音频数据(推荐):对于重复转写相同音频文件的场景,预先使用 faster_whisper.decode_audio() 解码一次,然后将解码后的数组传入 model.transcribe()audio 参数,避免每次重新解码。
  3. 检查 GPU 内存使用(仅涉及 GPU 内存增长的附加场景):如果使用 Large V2 模型及 float16 量化,注意 GPU 内存可能存在峰值,必要时减少同时并发的模型加载数量或降低精度(如使用 int8 量化)。

示例代码调整(结合两种方案):

import gc
import faster_whisper

model = faster_whisper.WhisperModel("small", device="cuda")

# 方案 A:每次转写后主动 GC
while True:
    segments, _ = model.transcribe(audio="audio.mp3", language="en", initial_prompt="...", no_speech_threshold=0.2)
    transcript_text = ''.join([segment.text for segment in segments])
    gc.collect()  # 强制回收

# 方案 B:预先解码
audio_data = faster_whisper.decode_audio("audio.mp3")
for _ in range(n):
    segments, _ = model.transcribe(audio=audio_data, language="en")
    transcript_text = ''.join([segment.text for segment in segments])

验证方法

运行循环转写脚本,同时通过 psutil 或系统监控工具(如 htop、SageMaker/CloudWatch 内存指标)观察进程 RSS 内存。如果内存波动范围稳定(例如基线约 1.48 GB,每个循环后无明显增长),则说明问题已解决。若使用预先解码方案,内存应完全平坦。

参考来源

SYSTRAN/faster-whisper #390

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

celebrityanime
celebrityanime
文章: 7792

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注