1. GPU上下文切换:多任务环境的"生命线"
现代GPU早已不再是单纯的图形渲染工具,而是承担着通用计算、深度学习等多样化工作负载的并行处理器。就像CPU需要处理多任务一样,GPU也需要在多个应用进程之间快速切换执行环境。这就是GPU上下文切换机制存在的根本原因。
我在开发移动端GPU驱动时,曾遇到过这样的场景:当用户一边玩游戏一边录屏时,系统需要在游戏渲染上下文和视频编码上下文之间频繁切换。如果切换效率低下,就会导致游戏卡顿或视频掉帧。通过优化上下文切换流程,我们最终将切换耗时从毫秒级降低到微秒级。
上下文切换的本质是保存当前任务的执行状态(寄存器值、内存映射等),并恢复下一个任务的状态。这个过程需要硬件和软件的紧密配合:
- 硬件层面:提供VMID(虚拟内存标识符)支持、状态寄存器组等基础设施
- 软件层面:设计高效的数据结构和切换流程,实现状态保存/恢复的原子性操作
关键认知:上下文切换不是开销,而是投资。优秀的切换机制能让GPU利用率提升30%以上。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 上下文切换的硬件基础
2.1 VMID(Virtual Memory ID)支持
VMID是现代GPU架构中最重要的硬件特性之一。它相当于给每个进程分配了一个独立的"身份证",使得不同进程的GPU内存访问可以完全隔离。以ARM Mali GPU为例:
c复制struct mali_context {
u32 vmid; // 虚拟内存空间标识
u64 page_table; // 页表基地址
u32 as_nr; // 地址空间编号
};
当GPU执行上下文切换时,硬件会自动根据VMID切换内存映射关系。这个过程完全由MMU(内存管理单元)硬件完成,不需要软件参与,因此几乎没有性能开销。
2.2 GPU状态寄存器
GPU内部有数百个甚至上千个状态寄存器,包括:
- 着色器核心状态(PC、SP等)
- 纹理单元配置
- 光栅化参数
- 输出混合设置
这些寄存器需要在上下文切换时保存和恢复。现代GPU通常采用两种设计:
- 影子寄存器组:为每个VMID维护独立的寄存器副本,切换时硬件自动选择对应组
- 上下文保存区:将寄存器状态保存到特定内存区域,需要软件参与
第一种方案性能更好但硬件成本高,第二种更灵活但切换延迟较大。以高通Adreno GPU为例,其采用混合方案:
code复制寄存器类型 | 保存方式
-------------------|-----------
着色器核心状态 | 影子寄存器
纹理/混合单元配置 | 内存保存区
3. 上下文切换的软件实现流程
3.1 标准上下文切换流程
一个完整的上下文切换包含以下步骤:
-
触发条件检测:
- 时间片耗尽
- 高优先级任务抢占
- 显式切换请求(如glFlush)
-
当前上下文保存:
c复制void save_context(struct gpu_context *ctx) { ctx->registers = read_gpu_registers(); ctx->fence = get_last_completed_fence();
