Skip to content
🔗 分享本题
查看我的学习进度 →

24 模块 Q7 教学图:Python 内存管理与 AI 应用的 OOM 问题如何排查?

🧠 图解记忆:AI 应用的 OOM 四大场景;点击图片可查看原图。

💡 答案要点

AI 应用的 OOM 四大场景:

1. 大模型加载:模型太大,显存不够
2. Batch 处理:批量请求堆积,内存暴涨
3. 向量数据库:大规模向量撑爆 RAM
4. 异步任务:并发任务未释放,内存泄漏

诊断工具:

工具用途典型用法
tracemalloc定位内存分配对比快照,找泄漏点
objgraph对象引用链查谁持有对象不释放
memory_profiler行级内存占用@profile 装饰器
psutil进程内存监控实时告警
gdb显存问题CUDA OOM 调试

实战:tracemalloc 排查内存泄漏:

python
import tracemalloc
import gc

# 启动追踪
tracemalloc.start()

# ... 执行你的代码 ...

# 抓取快照
snapshot1 = tracemalloc.take_snapshot()

# 执行可疑代码(N 次循环)
for _ in range(100):
    # 模拟:每次创建大对象但不释放
    data = [list(range(10000)) for _ in range(100)]
    # 正确做法:del data 或在循环内创建

gc.collect()  # 强制垃圾回收

snapshot2 = tracemalloc.take_snapshot()

# 对比快照
top_stats = snapshot2.compare_to(snapshot1, 'lineno')

print("内存增长 Top 10:")
for stat in top_stats[:10]:
    print(stat)

常见泄漏模式 + 修复:

展开 Python 代码示例(49 行)
python
# 泄漏模式 1:全局列表不断追加
class MemoryLeakyCache:
    """有内存泄漏的缓存"""
    def __init__(self):
        self.history = []  # ❌ 不断追加,永不清理
    
    def add(self, key, value):
        self.history.append((key, value))  # 内存持续增长
        return value


# 修复:LRU 缓存或固定大小
from functools import lru_cache

@lru_cache(maxsize=1000)
def cached_result(query: str) -> str:
    """自动 LRU 清理"""
    return expensive_computation(query)


# 泄漏模式 2:未关闭的流式响应
async def leaky_stream():
    async for chunk in llm.stream():
        process(chunk)
        # ❌ 如果中途异常,response 未关闭
    
# 修复:async with 或 try/finally
async def fixed_stream():
    async with llm.stream() as response:
        async for chunk in response:
            process(chunk)
        # ✅ 无论是否异常都会清理


# 泄漏模式 3:大对象序列化残留
def leaky_json_processing():
    data = load_large_json("big_file.json")  # 加载大 JSON
    result = json.dumps(data)  # 序列化
    # ❌ data 还在内存中
    del data  # 需要手动删除
    return result

# 修复:流式 JSON 解析
import ijson

def fixed_streaming_json():
    with open("big_file.json", "rb") as f:
        for item in ijson.items(f, "item"):  # 流式解析
            process(item)

AI 应用专项:大模型显存管理:

展开 Python 代码示例(39 行)
python
# 场景:多模型部署,显存不够
import torch

def load_model_memory_efficient(model_name: str):
    """显存高效加载"""
    if torch.cuda.is_available():
        # 1. 量化加载(INT8/INT4)
        model = AutoModelForCausalLM.from_pretrained(
            model_name,
            torch_dtype=torch.float16,  # FP16 加载
            load_in_8bit=True,           # INT8 量化(bitsandbytes)
            device_map="auto",           # 自动分配到多卡
        )
        
        # 2. 梯度检查点(减少显存)
        model.gradient_checkpointing_enable()
        
        # 3. 使用 Python 垃圾回收
        import gc
        gc.collect()
        torch.cuda.empty_cache()  # 清理未使用的缓存
    
    return model


# 监控显存
def monitor_gpu_memory():
    """每 N 秒监控一次显存"""
    import time
    while True:
        if torch.cuda.is_available():
            allocated = torch.cuda.memory_allocated() / 1024**3  # GB
            reserved = torch.cuda.memory_reserved() / 1024**3
            print(f"Allocated: {allocated:.2f}GB, Reserved: {reserved:.2f}GB")
            
            # OOM 预警
            if allocated > 0.9 * torch.cuda.get_device_properties(0).total_memory / 1024**3:
                print("⚠️ 显存使用率 > 90%,即将 OOM")
        time.sleep(30)

面试话术:

"AI 应用的 OOM 有四种常见原因:大模型加载(用 FP16/INT8 量化)、Batch 堆积(加 Semaphore 限流)、向量库太大(用内存映射或分片)、异步任务泄漏(用 async with 确保清理)。排查用 tracemalloc 对比快照,核心是'谁持有了对象不释放'。我做生产级 AI 服务有个习惯:加 psutil 实时监控内存,超过 80% 自动告警,超过 90% 自动触发 GC,不等到 OOM 才处理。"