一句话定义
CUDA Context(CUDA 上下文)是某个进程和某块 GPU 之间建立的「会话」,这个会话本身在显存里要占一块固定区域;它跟你有没有加载模型无关,进程一连上 GPU,显存就先被扣掉一笔。这笔钱就是 CUDA Context 的显存开销。
打个比方:还没搬进去,押金先交了
租办公室时,你付的钱不只有租金(模型权重),还有押金、物业费、门禁卡工本费。这些费用在搬进去之前就发生了,而且不管你租多大面积,它们基本固定。CUDA Context 就是这笔「进场费」:驱动要在显存里放上下文状态、内核代码与常量区、内存管理的元数据、页表等结构,框架还要建自己的句柄和工作区。典型量级在几百 MB,具体数值随驱动版本、GPU 架构、CUDA 工具包和框架而异,以官方文档和实测为准。
和相邻概念的区别
| 名称 | 什么时候产生 | 大致规模 | 能否省 |
|---|---|---|---|
| CUDA Context 固定开销 | 进程第一次操作 GPU 时 | 几百 MB 量级,基本与模型大小无关 | 部分可省,基本开销省不掉 |
| 模型权重(weights) | 加载 checkpoint 时 | 由参数量和精度决定,通常最大 | 可量化、可换精度 |
| 激活值/中间张量(activation) | 前向计算时 | 随 batch 增大而增大 | 调 batch、用AI 词典:梯度检查点">梯度检查点 |
| 分配器缓存与碎片 | 反复申请释放显存后 | 可达已用显存的相当比例 | 调分配策略、及时释放 |
关键区别在于:前三者里只有 Context 这部分,是你「什么都没干」时就已经付出的。
哪些能省,哪些省不掉
- 省不掉的基本开销:一个进程对一块可见 GPU 通常有一个 primary context,它是后面一切的前提;单卡单进程的部署里,这笔开销就是必须付出的固定成本。
- 可以减少的部分:一是「重复的 context」——多个进程各自导入 PyTorch 去碰同一块卡,就会各交一份;能用单进程多卡或多线程共享 context,就别开一堆进程。二是模块加载:较新的 CUDA 支持惰性模块加载(lazy module loading),不必把用不到的 kernel 全部塞进显存。三是通信库(如 NCCL)初始化的缓冲区、cuBLAS/cuDNN 的句柄工作区,可以按需配置。四是框架的缓存分配器(caching allocator)会「留着不还」,看着像泄漏,其实是预留池,可通过配置收紧。
对实际工作的意义
看到 nvidia-smi 显示空卡没有全部显存可用,先别怀疑显卡坏了——扣掉的就是这类固定开销。做显存预算时,习惯写成「Context 开销 + 权重 + 激活 + 余量」,比只算权重靠谱得多;在多进程服务化部署里,尤其要按进程数乘一遍这笔开销,否则很容易出现「单跑没问题、并发就 OOM」的情况。
