我在新公司用DeepSeek和PyTorch把资源成本砍了四成

周洋
2026-08-14 22:48
阅读 390

入职新公司两个月,组里接了个需求:大屏报表加载要十几秒,客户吐槽“打开页面先去泡杯咖啡”。定位下来,瓶颈不在前端,而是后端一个用PyTorch跑的轻量时序预测模型,每次请求现算一遍,CPU推理耗时占了大头。

领导让我去优化。先看现状:模型是离职同事留下的,PyTorch 1.8,Flask包了一层,代码大概这样:

@app.route("/predict", methods=["POST"])
def predict():
    data = request.json
    model = torch.load("model.pt", map_location="cpu")
    model.eval()
    with torch.no_grad():
        output = model(torch.tensor(data["features"]))
    return jsonify({"result": output.numpy().tolist()})

每个请求都torch.load一次,模型文件十几MB,光IO就够呛。第一件事把模型加载挪到全局,启动时加载一次。五分钟改完,响应时间从十几秒降到三秒左右。但三秒还是太慢。

继续深挖。三秒里大头不是模型计算,而是PyTorch在CPU上的调度开销。模型结构很简单:两层LSTM加一个全连接层,参数量不到一百万。这种小模型用PyTorch跑,框架开销占比极高。

思路是导出成TorchScript,用更轻量的方式加载。问了下DeepSeek,它给了几个方向,最终选定TorchScript方案:

traced_model = torch.jit.trace(model, example_input)
traced_model.save("model_traced.pt")

服务里加载:

model = torch.jit.load("model_traced.pt", map_location="cpu")

推理时间从三秒降到八百毫秒左右。但输入序列长度固定、batch size永远是1,还有更极端的优化空间:把模型推理手动改写成NumPy实现,省掉PyTorch的autograd图和算子调度开销。

我试着让Devin帮我做这件事。它代码写出来了,但结果对不上——LSTM的gate计算里把sigmoid和tanh激活顺序搞反了。我手动修正后,NumPy版本跑通,推理时间直接干到两百毫秒以内。Devin在写样板代码和单元测试方面确实省了不少时间,但核心逻辑还得自己把关。

整个优化过程里,DeepSeek帮我理清技术路线,Devin帮我写部分重复代码,关键的架构决策和代码审计靠人。最终上线效果:接口P99延迟从十几秒降到不到五百毫秒,原来需要三台4核8G机器扛并发,现在一台2核4G绰绰有余,月度成本降了约四成。

总结几个踩坑点:

第一,torch.load绝不能放在请求处理函数里。

第二,TorchScript导出时注意动态控制流,trace对if-else分支处理容易出问题,必要时用script代替。

第三,DeepSeek给的代码要自己跑一遍再上线。它给的ONNX导出脚本里opset_version写成了opset_verison,报错报得一头雾水。

第四,NumPy手写推理虽然快,但可维护性差。模型结构后续会变的话,建议用TorchScript或ONNX Runtime这类标准方案。

这次经历让我觉得,后端性能优化跟前端动画优化有相通之处——都是搞清楚每一毫秒花在哪里。区别在于前端卡顿用户能直接看到,后端慢用户只会觉得“这系统真垃圾”,然后默默流失。下次再遇到类似需求,应该不会像这次一样手忙脚乱了。

评论 0

最热最新
暂无评论
周洋Lv.1
0
影响力
0
文章
0
粉丝