C++ 怎么使用内存池消除深度学习推理过程中的频繁动态内存分配抖动

云强姑娘_8839

云强姑娘_8839

2026-10-24

210人浏览

原创

c++oding="utf-8" ?>

深度学习推理中malloc/free成为性能瓶颈,因其单次前向传播触发数百上千次小块分配,引发系统调用开销、arena锁竞争、内存碎片和TLB miss,导致P99延迟毛刺达2–5ms;关键在于将不可控的runtime分配转为可控、预置、无锁的复用。

c++ 怎么使用内存池消除深度学习推理过程中的频繁动态内存分配抖动

为什么深度学习推理中 malloc/free 会成为性能瓶颈

深度学习推理常在单次前向传播中触发数百甚至上千次小块内存分配(比如中间 tensor 的 buffer、临时 workspace),而 malloc 在默认 glibc 实现下对小内存会走 brk 或 mmap,频繁调用会引发系统调用开销、锁竞争(多线程下 malloc 内部有 arena 锁)、内存碎片和 TLB miss。这不是“慢一点”的问题,而是会导致延迟毛刺(jitter)——比如 P99 延迟突然跳高 2–5ms,对实时服务非常致命。

关键不是“能不能避免分配”,而是“能不能把不可控的 runtime 分配,变成可控的、预置的、无锁的复用”。

用 std::pmr::monotonic_buffer_resource 快速构建只增不减的推理内存池

这是 C++17 引入的轻量级内存资源,适合单次推理生命周期:分配只向前推进,不回收单个块,整个池在推理结束时一次性释放。它天然无锁、零系统调用(底层可绑定到大块 mmap 或预分配 std::vector<char></char>)。

实操建议:

  • 为每次推理准备一个独立的 std::pmr::monotonic_buffer_resource,生命周期与推理 session 对齐(例如封装进 InferenceContext 类成员)
  • 不要跨推理复用同一个 monotonic_buffer_resource,否则残留占用会累积;也不要把它设成全局单例
  • 底层内存建议用 mmap(MAP_ANONYMOUS | MAP_PRIVATE) 预分配 64MB–256MB(根据模型大小调整),避免首次分配触发 page fault 抖动
  • 搭配 std::pmr::polymorphic_allocator 使用,所有中间容器(如 std::pmr::vector<float></float>、std::pmr::unordered_map)都显式传入该 allocator
// 示例:一次推理的内存上下文
class InferenceContext {
    std::unique_ptr<char> pool_mem_;
    std::pmr::monotonic_buffer_resource pool_;
    std::pmr::polymorphic_allocator<float> alloc_;
<p>public:
InferenceContext(size_t pool_size = 128 <em> 1024 </em> 1024)
: pool<em>mem</em>(std::make_unique<char>(pool<em>size)),
pool</em>(pool<em>mem</em>.get(), pool<em>size),
alloc</em>(&pool_) {}</char></p>
<pre class="brush:php;toolbar:false;">template<typename t>
std::pmr::vector<t> make_vector() {
    return std::pmr::vector<t>(alloc_);
}</t></t></typename>

};

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载

遇到 std::bad_alloc 或越界踩内存?检查这三处

monotonic_buffer_resource 不做边界检查,也不扩容,一旦预分配空间耗尽就直接抛 std::bad_alloc;更危险的是,某些第三方库(如 ONNX Runtime 的某些 kernel)内部硬编码使用 new,完全绕过你的 pmr allocator。

排查要点:

  • 在 monotonic_buffer_resource 构造时传入 debug wrapper(比如自定义 memory_resource 记录每次 do_allocate 大小和累计用量),确认是否真超限,还是某次分配请求过大(>2MB)触发 fallback 到系统 malloc
  • 检查所有 tensor buffer 创建路径:是否每个 Tensor::data() 都来自你控制的 allocator?ONNX Runtime 的 Ort::Value 默认不用 pmr,需用 Ort::MemoryInfo 指向你的内存区域
  • 禁用编译器的 -fno-exceptions 时,std::bad_alloc 才能被捕获;否则可能静默 abort,看起来像段错误

需要真正“复用+回收”的场景?换 std::pmr::synchronized_pool_resource

monotonic_buffer_resource 适合单次推理;但如果你做 batch 推理(多个 input 共享 workspace)、或需要 pipeline 流水(prefill + decode 阶段复用 memory),就得支持“分配 → 使用 → 释放 → 再分配”。这时 std::pmr::synchronized_pool_resource 更合适:它按固定 size class 维护多个空闲链表,线程安全,释放后内存可被同 size 请求复用。

但要注意:

  • 它比 monotonic 慢约 15–30%,因为有锁和链表操作;不过仍远快于系统 malloc
  • size class 划分由实现决定(libstdc++ 和 libc++ 行为不同),大块内存(>128KB)可能直接 fallback 到 upstream resource(即你配的 monotonic_buffer_resource 或 new_delete_resource)
  • 务必用 upstream 参数把它链到一个大块预分配资源上,否则它自己还是会调 new
std::pmr::synchronized_pool_resource pool{
    std::pmr::pool_options{.max_blocks_per_chunk = 32},
    &monotonic_pool  // ← upstream,必须提供
};

真正难的不是选哪个 resource,而是把 allocator 透传到每一层 tensor 创建、kernel launch、host-to-device copy 的入口点。很多抖动不是来自 malloc 本身,而是某处隐式 new 没被拦截住——得靠 ASan + malloc trace 双验证。

C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!

相关专题

更多
c++和c语言的区别有哪些
c++和c语言的区别有哪些

c++和c语言的区别:1、面向对象编程(OOP)支持不同;2、新增特性不同;3、标准库不同;4、编译方式不同;5、命名空间不同等等。想了解更多c++的相关内容,可以阅读本专题下面的文章。

2024.03.14

2248

9

c++和python学习顺序推荐
c++和python学习顺序推荐

一般建议先学习C++,再学习Python,因为这样可以逐步从较为底层的编程语言向更高级的语言过渡。想了解更多python的相关内容,可以阅读本专题下面的文章。

2024.03.14

1039

6

python和c++学习性价比分析
python和c++学习性价比分析

Python易于学习,广泛应用于Web开发、数据科学和人工智能等领域,但性能较低。C语言性能高,适用于对性能要求较高的场景,如游戏开发和系统编程,但学习曲线陡峭,错误处理复杂。想了解更多python的相关内容,可以阅读本专题下面的文章。

2024.03.14

447

5

c语言和c++一样吗
c语言和c++一样吗

c语言和c++是两种不同的编程语言,虽然有相似之处,但存在显著差异。c语言专注于过程式编程和系统级开发,以简洁、高效著称。c++作为c语言的超集,引入了面向对象编程,增强了代码组织和管理能力,但学习曲线也更陡峭。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.03.14

327

5

c语言和c++先学哪个好
c语言和c++先学哪个好

初学者选择学习c语言还是c++语言,需要根据个人学习目标、背景以及编程兴趣和预期应用方向来决定。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.03.14

426

5

c语言和c++的区别和联系
c语言和c++的区别和联系

c语言和c++是计算机科学领域应用广泛的编程语言。虽然它们有着相似的基础,但它们在语言类型、语法功能和内存管理方面存在着显著差异。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.03.14

600

5

c++软件中文更改教程
c++软件中文更改教程

对于 ide,可通过打开设置,找到语言设置,选择中文,并保存更改。对于非 ide 应用程序,可查找设置或选项,选择语言设置,更改为中文,并保存更改。想了解更多c++的相关内容,可以阅读本专题下面的文章。

2024.03.21

1409

9

python和java和c++学习性价比分析
python和java和c++学习性价比分析

Python以其易学性、丰富的库和活跃的社区而著称,适合数据科学、人工智能和Web开发。Java以其跨平台性、企业级应用开发和Android应用开发而闻名。C++以其底层控制能力、高效性能和游戏开发而著称。选择哪种语言取决于个人兴趣、职业方向和特定需求。想了解更多python和java和c++的相关内容,可以阅读本专题下面的文章。

2024.03.22

1217

7

c++和c语言学习顺序推荐
c++和c语言学习顺序推荐

对于初学者,建议先学习C语言,掌握编程基础后再转入C++,便于理解面向对象编程概念。有编程经验者可直接学习C++,快速接触高级编程技术。想了解更多c++和c语言的相关内容,可以阅读本专题下面的文章。

2024.03.25

1325

9

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习