基于SpringAI搭建的Rag系统调优分享-混合检索一
2026/7/23 2:51:33
torch.cuda.empty_cache()会加剧显存堆积。# 显式释放GPU缓存 import torch if torch.cuda.is_available(): torch.cuda.empty_cache() # 清理未被引用的缓存asyncio提升吞吐量。uvicorn作为ASGI服务器启动服务transformers流式加载机制缓解。| 优化方式 | 显存降幅 | 适用场景 |
|---|---|---|
| FP16推理 | ~50% | 支持混合精度GPU |
| INT8量化 | ~75% | 边缘设备部署 |
import sys a = [1, 2, 3] print(sys.getrefcount(a)) # 输出: 2 (变量a + getrefcount参数) b = a print(sys.getrefcount(a)) # 输出: 3 del b print(sys.getrefcount(a)) # 输出: 2sys.getrefcount()返回对象的引用计数,注意调用该函数本身也会增加临时引用。import torch torch.cuda.reset_peak_memory_stats() model = torch.load('large_model.pth').cuda() # 加载模型至GPU print(f"峰值显存占用: {torch.cuda.max_memory_allocated() / 1024**3:.2f} GB")上述代码首先重置内存统计,加载模型后输出峰值显存消耗。其中,max_memory_allocated()返回生命周期内的最大分配量,单位为字节。 影响内存的关键因素包括:首先需启动追踪功能:
import tracemalloc tracemalloc.start()调用start()后,Python将记录所有内存分配的调用栈信息。
在关键位置获取内存快照进行对比:
snapshot = tracemalloc.take_snapshot() top_stats = snapshot.statistics('lineno') for stat in top_stats[:5]: print(stat)上述代码输出占用内存最多的前5个代码行。statistics('lineno')按行号聚合数据,便于定位具体位置。
memory_profiler 是 Python 中用于监控程序内存消耗的强大工具,可通过 pip 安装:
pip install memory-profiler安装后即可在脚本中直接调用,对函数或代码段进行逐行内存分析。
通过装饰器@profile标记目标函数,运行时使用mprof命令记录内存变化:
@profile def data_processing(): data = [i ** 2 for i in range(100000)] return sum(data)执行命令mprof run script.py可生成内存使用曲线,mprof plot可视化结果。
cudaMallocManaged(&data, size); // CPU端写入 for (int i = 0; i < N; ++i) data[i] *= 2; // 启动GPU核函数前显式同步 cudaDeviceSynchronize();上述代码分配可被CPU和GPU共同访问的内存,运行时根据访问局部性自动迁移页面。参数 `size` 决定分配总量,需合理规划以避免页错误频繁触发。cudaMemPrefetchAsync可提前将数据预载至目标设备,减少等待延迟:import torch from torch.quantization import quantize_dynamic # 加载预训练模型 model = MyModel().eval() # 对指定层执行动态量化 quantized_model = quantize_dynamic(model, {torch.nn.Linear}, dtype=torch.qint8)该代码将线性层权重转为INT8,推理时动态计算激活值。dtype=torch.qint8指定权重量化类型,有效压缩模型体积并提升CPU推理效率。| 格式 | 每参数字节 | 相对速度 | 适用场景 |
|---|---|---|---|
| FP32 | 4 | 1× | 训练 |
| FP16 | 2 | 2× | GPU推理 |
| INT8 | 1 | 4× | 边缘设备部署 |
# 示例:手动实现激活重计算 def checkpointed_layer(input_tensor, layer_fn, preserve=False): if preserve: return layer_fn(input_tensor) # 保存激活 else: return recompute(layer_fn, input_tensor) # 运行时重建上述代码中,preserve控制是否持久化中间结果,recompute在反向或推理追踪中按需触发计算,降低峰值内存占用。const ProductPage = () => import('./views/ProductPage.vue'); const router = new VueRouter({ routes: [ { path: '/product', component: ProductPage } ] });上述代码通过动态import()实现组件的按需加载,只有用户访问对应路径时才会请求该模块资源,提升首屏渲染性能。| 策略 | 初始加载体积 | 响应延迟 | 适用场景 |
|---|---|---|---|
| 预加载 | 大 | 低 | 高频使用模块 |
| 懒加载 | 小 | 高(首次) | 低频或重型组件 |
type ObjectPool struct { pool chan *Object } func (p *ObjectPool) Get() *Object { select { case obj := <-p.pool: return obj default: return NewObject() // 池空时新建 } } func (p *ObjectPool) Put(obj *Object) { select { case p.pool <- obj: default: // 池满则丢弃 } }上述代码中,`pool` 使用带缓冲的 channel 存储对象,`Get` 尝试从池中取对象,`Put` 归还对象。当池满或空时采取默认策略,避免阻塞。| 策略 | 内存分配次数 | GC暂停时间 |
|---|---|---|
| 直接创建 | 高 | 频繁 |
| 对象池 | 低 | 显著减少 |
import weakref class Node: def __init__(self, value): self.value = value self._parent = None self.children = [] @property def parent(self): return self._parent() if self._parent is not None else None @parent.setter def parent(self, value): self._parent = weakref.ref(value) if value is not None else None def add_child(self, child): self.children.append(child) child.parent = self上述代码中,父节点强引用子节点,而子节点通过weakref.ref()弱引用父节点,避免了双向强引用形成的循环。当父节点被删除时,其引用计数正常降为0,可被垃圾回收,子节点中的弱引用自动失效返回None,有效防止内存泄漏。type BufferPool struct { pool chan *bytes.Buffer } func NewBufferPool(size int) *BufferPool { return &BufferPool{ pool: make(chan *bytes.Buffer, size), } } func (p *BufferPool) Get() *bytes.Buffer { select { case buf := <-p.pool: return buf default: return new(bytes.Buffer) } }该实现利用带缓冲的channel管理空闲缓冲区,Get操作优先从池中获取已有对象,避免重复分配。当池为空时返回新实例,确保可用性。var tlsData = sync.Map{} func setData(key, value interface{}) { tlsData.Store(goroutineID(), map[interface{}]interface{}{key: value}) } func getData(key interface{}) interface{} { if m, ok := tlsData.Load(goroutineID()); ok { return m.(map[interface{}]interface{})[key] } return nil }上述代码利用sync.Map模拟 TLS 行为,以协程 ID 为键实现逻辑隔离。实际生产中可借助语言原生 TLS 支持(如 C++ 的thread_local)提升性能。apiVersion: apps/v1 kind: Deployment metadata: name: payment-service spec: replicas: 6 strategy: rollingUpdate: maxSurge: 1 maxUnavailable: 0该配置支持滚动更新过程中零中断服务切换,保障交易链路稳定性。| 版本 | 流量权重 | 监控指标 |
|---|---|---|
| v1.8.0 | 90% | HTTP 5xx < 0.1% |
| v1.9.0 | 10% | P99 延迟稳定在 120ms |