181、NPU的编译器开发:内存泄漏检测凌晨三点,服务器告警。NPU编译器在连续编译第37个模型时,内存占用从2.1G暴涨到14.7G,然后OOM被kill。我盯着监控面板上那条陡峭的上升曲线,心里清楚——又是内存泄漏。这不是第一次,也不会是最后一次。NPU编译器这种长期运行的服务进程,内存泄漏就像慢性病,不发作则已,一发作就是生产事故。泄漏的源头:一个被遗忘的IR节点先讲一个真实案例。我们的NPU编译器后端有一个Pass,负责将ONNX的BatchNormalization融合进卷积层。代码逻辑很简单:遍历计算图,找到BN节点,把它的权重参数合并到前一个Conv节点的bias中,然后删除BN节点。问题出在“删除”这一步。当时写的代码是这样的:// 别这样写!这是有问题的voidFoldBatchNorm(Graph*graph){
181、NPU的编译器开发:内存泄漏检测
181、NPU的编译器开发:内存泄漏检测凌晨三点,服务器告警。NPU编译器在连续编译第37个模型时,内存占用从2.1G暴涨到14.7G,然后OOM被kill。我盯着监控面板上那条陡峭的上升曲线,心里清楚——又是内存泄漏。这不是第一次,也不会是最后一次。NPU编译器这种长期运行的服务进程,内存泄漏就像慢性病,不发作则已,一发作就是生产事故。泄漏的源头:一个被遗忘的IR节点先讲一个真实案例。我们的NPU编译器后端有一个Pass,负责将ONNX的BatchNormalization融合进卷积层。代码逻辑很简单:遍历计算图,找到BN节点,把它的权重参数合并到前一个Conv节点的bias中,然后删除BN节点。问题出在“删除”这一步。当时写的代码是这样的:// 别这样写!这是有问题的voidFoldBatchNorm(Graph*graph){