3. 运行时系统概述

AI 编译器负责把高层模型图转换为可在目标硬件上执行的指令序列,但编译产物真正跑起来,还需要一个“现场管理者”——运行时系统(Runtime System)。它位于编译产物与操作系统、硬件之间,负责资源分配、内存管理、算子调度、数据搬运和错误处理。理解运行时系统,是理解 AI 编译器“从图到执行”闭环的关键一步。

3.1 运行时系统的定义

运行时系统是伴随编译产物一起部署、在程序执行期间提供支撑服务的软件层。它不同于编译期做静态优化的编译器前端/后端,而是动态地响应执行请求。对于 AI 场景,运行时系统通常包含:设备抽象层、内存池、内核调度器、流/队列管理、算子库绑定以及性能计数器等。

运行时系统 = 编译产物 + 执行期服务。它把“静态图”变成“动态执行”,把“逻辑算子”映射到“物理设备”。

3.2 核心功能

主流 AI 运行时系统的核心功能可以归纳为以下五类:

  • 设备与上下文管理:枚举 GPU/NPU/CPU,创建 context、stream、event,管理设备句柄与生命周期。
  • 内存管理:通过内存池(memory pool)复用显存,减少 cudaMalloc 等昂贵调用;支持张量生命周期分析与原地复用。
  • 算子调度与执行:按依赖关系下发 kernel,处理同步/异步、流间依赖与事件等待。
  • 数据搬运:管理 H2D、D2H、D2D 拷贝,处理 pinned memory 与零拷贝路径。
  • 性能与容错:采集时间线、显存占用、kernel 耗时;捕获异常并支持重试或降级。

下面这张图展示了运行时系统在“模型—编译器—运行时—OS/硬件”链路中的位置与内部结构:

AI 模型 / 计算图(PyTorch、ONNX、TensorFlow) 算子、张量、依赖关系 AI 编译器(图优化、算子融合、代码生成) 输出:可执行计划 / 内核二进制 / 调度描述 运行时系统(Runtime System) 设备/上下文管理 context · stream · event 内存池管理 复用 · 生命周期 · 对齐 算子调度器 依赖 · 异步 · 流 数据搬运与性能 H2D/D2H · 计时 · 容错 操作系统(驱动、内存映射、线程/进程调度、PCIe 管理) 硬件:CPU · GPU · NPU · 加速卡 · 显存 / HBM

3.3 与操作系统和硬件的关系

运行时系统并不直接“裸奔”在硬件上,它依赖操作系统提供的驱动与资源抽象,同时又要屏蔽硬件差异。具体关系如下:

层次 职责 与运行时的交互
AI 编译器 图优化、算子融合、代码生成 向运行时输出可执行计划与内核句柄
运行时系统 资源分配、调度、内存复用、数据搬运 调用 OS 驱动接口,管理设备上下文
操作系统 驱动加载、内存映射、线程调度、中断 提供 ioctl、mmap、DMA、事件通知
硬件 计算单元、显存、互联总线 执行 kernel,完成数据读写与同步

一个典型调用链如下:

// 伪代码:运行时下发一个卷积算子
rt_stream_t stream = rt_stream_create(device);
rt_tensor_t* input  = rt_tensor_alloc(pool, shape, dtype);
rt_tensor_t* weight = rt_tensor_alloc(pool, shape, dtype);
rt_tensor_t* output = rt_tensor_alloc(pool, out_shape, dtype);

rt_memcpy_h2d(input, host_ptr, bytes, stream);
rt_memcpy_h2d(weight, host_ptr, bytes, stream);

rt_kernel_t* k = rt_kernel_lookup("conv2d_fwd");
rt_kernel_launch(k, grid, block, stream, input, weight, output);

rt_stream_sync(stream);
rt_memcpy_d2h(host_out, output, bytes, stream);

可以看到,运行时系统承担了“翻译官”和“调度员”的双重角色:对上接收编译器的执行计划,对下把计划翻译成驱动能理解的命令,并管理好内存与同步。

3.4 主流 AI 运行时对比

不同厂商和框架的运行时系统设计目标不同,下面从几个维度进行对比:

运行时 所属生态 核心特点 典型场景
CUDA Runtime NVIDIA API 简洁,隐式上下文管理,生态成熟 GPU 训练与推理
CUDA Driver API NVIDIA 显式上下文与模块加载,控制粒度细 需要精细控制的推理引擎
ROCm/HIP Runtime AMD 类 CUDA 接口,跨平台可移植 AMD GPU 训练推理
CANN Runtime 华为昇腾 面向 NPU 的流与内存管理,图执行模式 昇腾推理与训练
TVM Runtime 开源 轻量、可嵌入,支持多种后端 端侧与异构部署
ONNX Runtime 微软/开源 图执行器 + 多 EP 插件,跨平台 通用推理服务
选择运行时系统时,优先看三点:目标硬件是否原生支持、内存管理是否高效、是否支持异步流与事件。不要只看 API 是否“像 CUDA”。

3.5 常见误区与复盘

在实际开发中,初学者容易把运行时系统当成“透明层”,忽略它的开销与约束。常见误区包括:

  • 频繁申请释放显存:每次推理都 cudaMalloc/cudaFree,导致性能抖动。应使用内存池并复用张量。
  • 忽略流同步:异步 kernel 未正确同步就读取结果,得到脏数据。应使用 event 或 stream sync。
  • 混淆编译期与运行期:把本可在编译期确定的形状、布局拖到运行期处理,增加调度开销。
  • 忽视设备上下文切换:多卡场景频繁切换 context,导致额外延迟。
运行时系统的性能问题往往不是“算得慢”,而是“等得久”。排查时先看时间线:拷贝、同步、调度各占多少,再决定优化方向。

复盘一个真实场景:某推理服务在 GPU 上单次延迟 8ms,其中 kernel 计算仅 2ms,其余 6ms 花在 H2D 拷贝与 stream 同步上。通过启用 pinned memory、合并小拷贝、使用双缓冲流,延迟降到 3.5ms。这说明运行时系统的内存与流管理,往往比算子本身更影响端到端性能。

综上,运行时系统是 AI 编译器落地执行的“最后一公里”。它向上承接编译器的执行计划,向下驱动操作系统与硬件,核心在于资源管理、调度与数据搬运。理解它的定义、功能、层次关系与主流实现差异,是后续深入学习内存池、流调度与多设备并行的基础。