[关闭]
@MatheMatrix 2025-03-17T14:58:00.000000Z 字数 6001 阅读 17

如何“合理的”共享 GPU 资源?提升资源利用率?


由于 GPU 特别是高端 GPU 的价格高昂,企业常常会有这样的想法:GPU 的利用率往往不是总 100%,能不能把 GPU 做一下切分,类似于服务器上启动多个虚拟机那样,每个人分配一部分来使用,岂不是可以大大提升 GPU 的利用率

然而现实上,GPU 的虚拟化远远落后于 CPU 的虚拟化,其背后有几点原因:

  1. GPU 工作方式与 CPU 的天然不同
  2. GPU 的使用场景与 CPU 的天然不同
  3. 厂家和行业的发展进程造成虚拟化进展的不同

image.png-37.7kB

今天我们就从 GPU 的工作原理几种 GPU 共享的方法谈起,最终讨论对于大部分企业来说,AI 时代究竟需要怎样的 GPU 共享如何提升 GPU 的利用率和效率

1. GPU 的工作原理概述

  1. 高度并行的硬件架构
    GPU(Graphics Processing Unit)最初专注于图形加速,是一种为大规模数据并行计算而设计的处理器。相较于 CPU 的通用性,GPU 内部包含大量的流处理器(Streaming Multiprocessors/SM 等称呼),能够在单一指令多数据(SIMD,也可以近似理解成 SIMT)的模式下同时执行数百甚至数千个线程。

  2. Context(上下文)与 显存(VRAM)

    • Context:在 CUDA 编程环境下,如果不同的进程(或容器)要使用 GPU,需要各自拥有自己的 CUDA Context。GPU 会在不同 Context 之间进行时间片切换合并共享(如 NVIDIA MPS 合并多个进程到同一个 Context)等模式。
    • 显存(VRAM):GPU 自带的显存容量往往比较固定,同时 GPU 对其管理也区别于 CPU(CPU 主要通过操作系统内核 MMU 进行内存分页等),GPU 常常需要显式地分配显存空间。从下图可以看到 GPU 具有大量的 ALU,同时各自有自己的 Cache 空间:
      image.png-8kB
  3. GPU 侧硬件与调度模式

    • GPU 上下文切换频率与效率明显比 CPU 要复杂。因为 GPU 往往需要将 Kernel(GPU 端的计算函数)完整运行完才会进行调度切换,不同进程间还需保存并恢复 GPU Context 数据,这比 CPU 上下文切换的代价大。
    • GPU 资源包括两个主要维度:算力(对应流处理器、SM 等)与显存。GPU 在实际使用中既要考虑算力是否占满,也要考虑显存是否充足。

2. GPU 共享技术落后于 CPU 共享的原因

  1. CPU 虚拟化成熟且指令集与硬件支持完善
    CPU 上的虚拟化(如 KVM、Xen、VMWare 等)已经发展了数十年,硬件层面(Intel VT-x、AMD-V)也对虚拟化提供了大量支持。CPU 的上下文较为简单,且硬件厂商和虚拟化厂商之间已经深度合作。

  2. GPU 的高并行与上下文切换成本高
    由于 GPU 上下文切换(Context Switch)的复杂度和代价明显高于 CPU,想要在 GPU 上做“共享”时,需要灵活地处理不同进程对 GPU 并发访问、对显存的争抢、内核态闭源驱动的兼容适配等问题。对于 GPU 这种数百乃至数千个内核的软硬件协作,厂商难以像 CPU 一样在指令集层面做完整的硬件虚拟化抽象,或需要相当长的演进过程才能做到。

(下图为 GPU 上下文切换示意图,可以看到上下文切换造成了非常高的延时)
image.png-249.3kB

  1. 场景需求差异
    CPU 常见地为大规模多用户虚机、容器做共享,且大部分使用场景对 CPU 效率要求较高,但绝对不会像深度学习训练那样激烈调用数千线程进行矩阵乘法或卷积操作。GPU 的训练与推理等场景中,往往希望最大化利用 GPU 的峰值算力,一旦进行虚拟化或者共享,会出现上下文切换开销资源 QoS 保证的冲突问题,因而存在各种技术上的割裂。

  2. 厂商之间的差异性
    目前 CPU 厂商相对比较集中,海外主要以 Intel、AMD 为主,均为 x86 架构,而国内厂商主要也是 X86(或 C86)ARM 居多,个别厂商采用 LoongArch 等自有指令集。但 GPU 厂商的差异度非常大,至少可以分为 CUDA 流派CUDA 兼容流派ROCm 流派以及包含 CANN 架构在内的各种自有生态流派,导致生态的割裂性较重。

综合来看,这些原因导致 GPU 共享技术一直落后于 CPU 虚拟化的成熟度与灵活性。


二、常见 GPU 共享方式的优缺点与适用场景

综合来看,可将 GPU 共享的主要思路大致分为以下几类(名称可能不同,但原理类似):

  1. vGPU(基于硬件/内核态/用户态的多种实现,如 NVIDIA vGPU、AMD MxGPU、内核态 cGPU/qGPU 等)
  2. MPS(Nvidia Multi-Process Service,合并 Context 方案)
  3. MIG(Nvidia 多实例 GPU,A100/H100 等最新架构的硬件隔离)
  4. CUDA Hook(API 劫持/拦截,如 GaiaGPU、VirtAI 等用户态劫持方式)

1. vGPU

(下图为 vGPU 原理图,可以看到一个物理 GPU 被切割为 3 个 vGPU 并透传到虚拟机)
image.png-116.9kB

2. MPS(Multi-Process Service)

3. MIG(Multi-Instance GPU)

(下图为 A100 MIG 所支持的 profile
image.png-270.9kB

4. CUDA Hook(API 劫持/拦截)

image.png-50.9kB

5. 远程调用(rCUDA 等)简述


三、模型层面的“共享”与 GPU 切割的对比

随着大语言模型(LLM)如 Qwen、Llama、DeepSeek 等的兴起,模型规模、参数量以及需要的显存占用越来越高。“单卡甚至单机”往往不足以完全装下模型,更别提大批量的推理和训练消耗。因此衍生出基于模型层面的“切分”和“共享”思路,例如:

  1. 张量并行(Tensor Parallelism)、流水并行(Pipeline Parallelism)、专家并行(Expert Parallelism)等。
  2. Zero Redundancy Optimizer (ZeRO) 技术或各种分布式训练框架下的显存优化。
  3. 小模型推理场景下,通过切分 GPU 的方式处理多用户请求。

image.png-44.3kB

在实际部署大模型时,往往会将一个模型切分到多个 GPU/节点上,以获得更大的总显存和算力。此时,模型的并行切分其实就变成了“通过分布式训练/推理框架自身来管理多 GPU 资源”。这在一定意义上是一种更高层次的“GPU 共享”:

哪些情形下适合“模型并行”哪些情形适合“GPU 虚拟化”

  1. 超大模型场景
    如果单卡显存工作不下,必须要多卡甚至多机分布式并行。这时候,硬件层面的 GPU 切分意义并不大,因为你要的不是把一块物理卡“分”给多任务,而是把更多卡“合”起来支撑一个巨大模型。(下图为张量并行示意,将一个矩阵运算拆分为小矩阵)
    image.png-150.7kB

  2. 成熟的推理与训练应用
    在产品级别的大模型推理或训练流水线上,大多已经有一整套多卡并行、批量调度的体系。一旦 GPU 切分或远程调用,会增加额外管理复杂度、降低性能,还不如直接在多卡集群上做分布式训练或推理。

  3. 小模型、测试场景
    对于那些临时测试、小模型应用、或推理批次较小的场景,需要藉由 GPU 虚拟化/共享技术来提升利用率。一块高端 GPU 可能只利用了 10% 的算力或显存,例如运行 Embedding 模型只需要几百 MB 或者几 GB 的显存即可,通过 GPU 切割可以有效提升利用率。

是否建议远程调用

image.png-200.2kB


四、总的建议与结论

  1. 大模型或需要高性能的应用

    • 单卡显存肯定不足时,应该依赖模型本身的分布式并行(如张量并行、流水并行、MoE 等),让 GPU 资源在更高层次进行 “合并” 式利用,而非在物理卡层面“切分”。这样可以最大化性能、避免过多的上下文切换损失。
    • 远程调用(rCUDA 等)不建议在此场景大量使用,除非在特殊网络架构下(非常高速低延迟)且对性能要求不高。
  2. 在 GPU 利用率不足的小模型测试场景

    • 虚拟机上考虑使用 MIG(如在 A100/H100 上)、vGPU(如 NVIDIA vGPU 或开源 cGPU/qGPU),把大卡分给多个并行任务使用;或者在容器利用 CUDA Hook 方案做灵活限额,提升资源使用率。
    • 要注意故障隔离和性能开销。如果是对 QoS 与稳定性要求高,可以优先选择 MIG(隔离度最优)、或官方 vGPU(license 预算充足的前提下)。
    • 如果是明确的使用场景或者测试场景,CUDA Hook/劫持类方案部署相对最灵活。
  3. 远程调用不适合作为大规模 GPU 共享的主要方式

    • 通过 API Remoting 的方式对 GPU 进行虚拟化,会带来明显的网络开销、序列化延迟,除非对延时不敏感,且仅在极少数分布式虚拟化场景中才值得考虑。

五、总结

由此可见,若是大语言模型(尤其是极大参数量)场景,最佳实践还是在分布式并行模型(如张量并行、流水线并行)来“共享”与“分配”算力,而不是对单卡再做虚拟化切分。针对于小型模型、多用户测试、推理批量低的情况,可以用 GPU 虚拟化或切割来提高单卡利用率。这样才是有理有据且有策略分层的做法。

但是如何进一步提升 GPU 的效率,如何尽可能的让有限的 GPU 发挥更高的吞吐?如果大家感兴趣的话我们会在后面继续详细讲述这一话题,欢迎大家点赞、关注、转发!

注:本文部分图片来自网络,部分图片借助 AI 工具生成

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注