GPU使用mps

参考文档: https://blog.csdn.net/weixin_41997940/article/details/124241226

什么是mps

mps简介

mps(Multi-Process Service),多进程服务。一组可替换的,二进制兼容的CUDA API实现,包括三部分: 守护进程 、服务进程 、用户运行时。

mps利用GPU上的Hyper-Q 能力:

  • 允许多个CPU进程共享同一GPU context
  • 允许不同进程的kernel和memcpy操作在同一GPU上并发执行,以实现最大化GPU利用率。

Hyper-Q介绍:

HyperQ 可以视为在设备端的硬件中实现的流: 在没有HyperQ时 ,来自所有流的命令(内核启动、内存传输等)由主机上的驱动程序放置在单个工作队列中。这意味着命令不能相互超越,必须careful issuing them in the right order on the host以达到最佳重叠。 在带有 HyperQ 的 GK110 GPU 和更高版本的设备上,设备上有(至少)32 个工作队列。来自不同队列的命令可以相对于彼此重新排序,直到它们开始执行。

支持的连接类型

  • Multi cuda streams
  • Multi cpu thrreads
  • Multi cpu processes(MPS)

管理可并发的最大连接数:

  • CUDA_DEVICE_MAX_CONNECTIONS = 32 (默认是8)

一般GPU上运行多个任务,都是采用"单任务"的工作模式,既同一个时刻只有一个任务( 用不同的context区分 )在GPU中运行。这种情况下,你同时启动了两个任务A和B,提交到GPU进行运行的时候是顺序进行的, 排队干活、分时复用 ,如下图所示:

gpu_mps_1.png

什么是 CUDA context?

类似于CPU进程上下文,表示与特定进程关联的所有状态

  • 从CPU端分配的GPU上的Global memory (cudaMalloc/cudaMallocManaged)
  • Kernel函数中定义和分配的堆栈空间,例如local memory
  • CUDA streams / events 对象
  • 代码模块(*.cubin, *.ptx)

不同的进程有自己的CUDA context

每个context有自己的地址空间,并且不能访问其他CUDA context的地址空间

使用了mps之后,共用了context,同一时刻两个任务可以一起跑。这样更加充分的利用了GPU的算力。

gpu_mps_2.png

mps带来的好处

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

如何使用mps

单卡使用mps

设置独占 :

sudo nvidia-smi -i 0 -c EXCLUSIVE_PROCESS

启动mps守护进程:

export CUDA_VISIBLE_DEVICES=0
nvidia-cuda-mps-control -d

查看守护进程:

ps -ef | grep mps

关闭:

echo quit | nvidia-cuda-mps-control
sudo nvidia-smi -i 0 -c 0

配置mps的脚本:

设置资源占用量修改OpenMPS 100即可,0-100之间。50即为半卡,25四分之一卡。

#!/bin/bash
echo "please ensure 'nvidia-smi -i 0 -c EXCLUSIVE_PROCESS' "
echo "press any key to continue"
read
 
OpenMPS(){
    nvidia-cuda-mps-control -d
    echo "[MPS]: set mps default_active_thread_percentage: $1"
    echo set_default_active_thread_percentage $1|nvidia-cuda-mps-control  
}
 
CloseMPS(){
    echo "[MPS]: close mps control daemon"
    echo quit | nvidia-cuda-mps-control
}
 
 
CloseMPS
OpenMPS 100

多卡使用mps

只需要修改卡的参数即可:(0为0号卡,1为1号卡)

nvidia-smi -i 0,1 -c EXCLUSIVE_PROCESS
export CUDA_VISIBLE_DEVICES=0,1

使用nvprof抓取log

nvprof --profile-all-processes --csv --log-file output_%p.csv