CUDA多进程服务MPS

警告
本文最后更新于 2020-04-15,文中内容可能已过时。

Reference:

Hyper-Q Example

MULTI-PROCESS SERVICE

IMPROVING GPU UTILIZATION WITH MULTI-PROCESS SERVICE (MPS)

多个docker容器如何共享GPU

基于Volta MPS执行资源配置下的多容器共享GPU性能测试

MPS

  • 类似于CPU进程上下文,表示与特定进程关联的所有状态
    • 从CPU端分配的GPU上的Global memory (cudaMalloc/cudaMallocManaged)
    • Kernel函数中定义和分配的堆栈空间,例如local memory
    • CUDA streams / events 对象
    • 代码模块(*.cubin, *.ptx)
  • 不同的进程有自己的CUDA context
  • 每个context有自己的地址空间,并且不能访问其他CUDA context的地址空间

image-20200414150825492

image-20200414150919287

image-20200414151016618

时间片轮转调度,相当于串行执行,每个时刻只有一个进程在GPU上执行,吞吐率不会发生变化,而且由于上下文context切换的开销,延迟增加的同时,吞吐量反而是下降的.

  • 允许多个CPU 线程或进程同时加载任务到一个GPU上,实现CUDA kernels的并发执行 –- 硬件特性

  • 支持的连接类型

    • Multi cuda streams
    • Multi cpu threads
    • Multi cpu processes——MPS
  • 管理可并发的最大连接数

    1
    2
    
    # (默认是8)
    CUDA_DEVICE_MAX_CONNECTIONS = 32 
    
  • 好处

    • 增加GPU利用率(utilization)和占用率(occupancy)
    • 减少CPU空闲时间
    • 增加吞吐率并减少延
  • 使用限制

    • 当kernel A正在执行时, 只有当GPU上任意SM上有足够的资源( 寄存器, 共享内存, 线程块槽位等等)来执行kernel B中的1个线程块时, kernel B才会被发射
    • 要求GPU计算能力大于等于3.5
    • 最大连接数限制: 32
  • 示例代码

    1
    
    $CUDA_PATH/samples/6_Advanced/simpleHyperQ
    

    image-20200414152818622

image-20200414152854056

  • 什么是MPS

    • 一组可替换的,二进制兼容的CUDA API实现,包括:守护进程,服务进程,用户运行时
    • 利用GPU上的Hyper-Q 能力
      • 允许多个CPU进程共享同一GPU context
      • 允许不同进程的kernel和memcpy操作在同一GPU上并发执行,以实现最大化 GPU利用率.

    image-20200414153922257

    image-20200414154004787

  • 好处

    • 提升GPU利用率(时间上)和占用率(空间上)
    • 减少GPU上下文切换时间
    • 减少GPU上下文存储空
  • 使用限制

    • 操作系统: 仅支持linux
    • GPU版本: 大于等于CC 3.5
    • CUDA版本:大于等于5.5
    • 最大用户连接数量:
      • Pascal及之前GPU: 16
      • Volta及之后GPU: 48
  • 启动

    • 设置GPU compute mode 为 exclusive mode (非必须,但推荐设置)

      1
      
      sudo nvidia-smi -i 0 -c EXCLUSIVE_PROCESS
      
    • 启动MPS 守护进程

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    # 指定要启动MPS的GPU,不指定默认对所有GPU生效
    export CUDA_VISIBLE_DEVICES=0
    
    # cuda 7.0 以后非必须
    export CUDA_MPS_PIPE_DIRECTORY=/tmp/nvidia-mps 
    
    # cuda 7.0 以后非必须
    export CUDA_MPS_LOG_DIRECTORY=/tmp/nvidia-log 
    
    nvidia-cuda-mps-control –d
    
    • 查看MPS 守护进程是否正在运行

      1
      
      ps -ef | grep mps
      
    • 运行应用程序

      1
      
      mpirun –np 4 ./test
      

      应用程序运行前:

      image-20200414155300462

      应用程序运行后:

      image-20200414155446902

  • 停止

    1
    2
    
    echo quit | nvidia-cuda-mps-control
    sudo nvidia-smi -i 0 -c 0
    
  • 监视

    1
    
    nvidia-smi
    

    image-20200414155727800

  • 分析

    1
    2
    
     nvprof --profile-all-processes -o output.%p
     mpirun –np 4 ./test