mps
Published:
本文回顾mps 相关技术。
MPS(Multi-Process Service)是一种支持多任务模式的方法,它跟网络、训练框架(PyTorch/Tensorflow/others)无关,只跟任务数量以及硬件相关。 https://docs.nvidia.com/deploy/pdf/CUDA_Multi_Process_Service_Overview.pdf

GPU利用率到底是什么吗?
在运行任务时,大部分人通过 nvidia-smi 来查看GPU的利用率“Volatile GPU Util”, (或用 nvidia-smi pmon ,对于tegra 产品用户,使用 tegrastats )
NVIDIA官方对利用率(utilization)定义:
Percent of time over the past sample period during which one or more kernels was executing on the GPU.The sample period may be between 1 second and 1/6 second depending on the product.
https://developer.download.nvidia.com/compute/DCGM/docs/nvidia-smi-367.38.pdf
中文是:采样时间段内,1个或更多的核(kernel)运行的时间的占比。这个采样时间段取多长,跟产品相关,可能值1/6s~1s。
注意:“one or more kernels”。这个意味着里面只要有1个kernel在执行,你的GPU利用率也可以很高。 而1个kernel不是一定让GPU内部的运算单元(core)都工作的。
因此,要注意了下面两个错误认识:
- GPU的利用率 = GPU内计算单元干活的比例。 利用率越高,算力就必然发挥得越充分。
- 同条件下,利用率越高,耗时一定越短。
只要记住一个事实:GPU利用率99%,并不能说明你的GPU就拿出了99%的算力。这个利用率只能说明,有kernel在运算,至于算得怎么样,算力发挥出来了没有,sm 中的core 是否都处在计算状态,光看这个利用率是判断不出来的。你可以使用一个空kernel 也会造成GPU利用率达到很高的假象。
__global__ void warmup_kernel() {
while(1){
}
}
void gpu_warmup() {
warmup_kernel<<<1, 1>>>();
CheckCudaErrors(cudaDeviceSynchronize());
}
并不是利用率越高,耗时就会越短,反之亦然。举个例子,用了MPS后,利用率降低了,运行反而更快了。
所以在同条件下,应该是GPU算力用得越充分,耗时才会越短。
提升sm真正利用率
GPU-Util 并不可信。
提升利用率的方法可以从任务本身着手,比如
- 增加数据大小(更大的batch_size、网络)
- 缩减I/O时间
- 提前加载数据等手段
- 同时送入多个任务给GPU,多个任务操作互补(有些操作不需要GPU工作),让GPU运算不闲着
这些方法都是在宏观维度从时间以及空间上压榨算力,接下来说个微观维度的手段:多任务模式。
mps
如果GPU有两个及以上的任务一起运行,那么你就可以考虑用多任务模式来继续压榨GPU算力,目前我们能接触的工具 MPS。
简单介绍一下原理,一般GPU上运行多个任务,都是采用”单任务”的工作模式,既同一个时刻只有一个任务(用不同的context区分)在GPU中运行。通俗一点,假如你起了两个任务A和B
单任务模式下,A和B是排队干活的,(“我怎么感受不到这个排队过程?” — 这个时间非常小,是一种并发的操作,感觉在好像在一起工作); 
多任务模式,就是A和B 可以同时干活
由于共用了context,同一时刻两个可以一起跑。这样更加充分的利用了GPU的算力。有了MPS,原来闲置的sm-core就被调用起来了,这样GPU的算力发挥得更充分了。
需要注意的是:MPS的service下,只要里面一个任务出错/失败,可能使得所有在里面的任务都运行失败。
# ====== 启动 =========
export CUDA_VISIBLE_DEVICES=0 # 这里以GPU0为例,其他卡类似
nvidia-smi -i 0 -c EXCLUSIVE_PROCESS # 让GPU0变为独享模式。
nvidia-cuda-mps-control -d # 开启mps服务,之后启动的任务类型Type都是”M+C“,说明MPS用上了
ps -ef | grep mps # 启动成功后能看到相应的进程
# ====== 停止 =========
nvidia-smi -i 0 -c DEFAULT # 让GPU恢复为默认模式
echo quit | nvidia-cuda-mps-control # 关闭mps服务
ps -ef | grep mps # 启动成功后能看到相应的进程
root@SHJS-PF4ZKYLL:/home/github/lix19937.github.io# export CUDA_VISIBLE_DEVICES=0
root@SHJS-PF4ZKYLL:/home/github/lix19937.github.io# echo $CUDA_VISIBLE_DEVICES
0
root@SHJS-PF4ZKYLL:/home/github/lix19937.github.io# nvidia-smi -i 0 -c EXCLUSIVE_PROCESS
Set compute mode to EXCLUSIVE_PROCESS for GPU 00000000:01:00.0.
All done.
root@SHJS-PF4ZKYLL:/home/github/lix19937.github.io# nvidia-smi
Sat Aug 30 12:10:40 2025
+---------------------------------------------------------------------------------------+
| NVIDIA-SMI 535.230.02 Driver Version: 535.230.02 CUDA Version: 12.2 |
|-----------------------------------------+----------------------+----------------------+
| GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |
| | | MIG M. |
|=========================================+======================+======================|
| 0 NVIDIA RTX 2000 Ada Gene... Off | 00000000:01:00.0 Off | N/A |
| N/A 38C P8 2W / 40W | 8MiB / 8188MiB | 0% E. Process |
| | | N/A |
+-----------------------------------------+----------------------+----------------------+
+---------------------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=======================================================================================|
| 0 N/A N/A 2594 G /usr/lib/xorg/Xorg 4MiB |
+---------------------------------------------------------------------------------------+
root@SHJS-PF4ZKYLL:/home/github/lix19937.github.io# nvidia-cuda-mps-control -d
root@SHJS-PF4ZKYLL:/home/github/lix19937.github.io# nvidia-smi
Sat Aug 30 12:11:05 2025
+---------------------------------------------------------------------------------------+
| NVIDIA-SMI 535.230.02 Driver Version: 535.230.02 CUDA Version: 12.2 |
|-----------------------------------------+----------------------+----------------------+
| GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |
| | | MIG M. |
|=========================================+======================+======================|
| 0 NVIDIA RTX 2000 Ada Gene... Off | 00000000:01:00.0 Off | N/A |
| N/A 39C P4 N/A / 40W | 8MiB / 8188MiB | 0% E. Process |
| | | N/A |
+-----------------------------------------+----------------------+----------------------+
+---------------------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=======================================================================================|
| 0 N/A N/A 2594 G /usr/lib/xorg/Xorg 4MiB |
+---------------------------------------------------------------------------------------+
root@SHJS-PF4ZKYLL:/home/github/lix19937.github.io# ps -ef | grep mps
root 17238 2453 0 12:10 ? 00:00:00 nvidia-cuda-mps-control -d
root 17248 17190 0 12:11 pts/2 00:00:00 grep --color=auto mps
root@SHJS-PF4ZKYLL:/home/github/lix19937.github.io# nvidia-smi -i 0 -c DEFAULT
Set compute mode to DEFAULT for GPU 00000000:01:00.0.
All done.
root@SHJS-PF4ZKYLL:/home/github/lix19937.github.io# echo quit | nvidia-cuda-mps-control
root@SHJS-PF4ZKYLL:/home/github/lix19937.github.io# nvidia-smi
Sat Aug 30 12:11:54 2025
+---------------------------------------------------------------------------------------+
| NVIDIA-SMI 535.230.02 Driver Version: 535.230.02 CUDA Version: 12.2 |
|-----------------------------------------+----------------------+----------------------+
| GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |
| | | MIG M. |
|=========================================+======================+======================|
| 0 NVIDIA RTX 2000 Ada Gene... Off | 00000000:01:00.0 Off | N/A |
| N/A 40C P4 N/A / 40W | 8MiB / 8188MiB | 0% Default |
| | | N/A |
+-----------------------------------------+----------------------+----------------------+
+---------------------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=======================================================================================|
| 0 N/A N/A 2594 G /usr/lib/xorg/Xorg 4MiB |
+---------------------------------------------------------------------------------------+
root@SHJS-PF4ZKYLL:/home/github/lix19937.github.io#
- 执行
nvidia-smi -i 0 -c EXCLUSIVE_PROCESS # 让GPU0变为独享模式。表示独享模式

- 执行
nvidia-cuda-mps-control -d # 开启mps服务之后的任务类型Type都是”M+C“,说明MPS用上了

通常,在多任务的情况下,速度变快了,尤其是在GPU利用率已很高的情况下,给你带来的收益更多。
- 执行 ```bash nvidia-smi -i 0 -c DEFAULT # 让GPU恢复为默认模式 echo quit | nvidia-cuda-mps-control # 关闭mps服务
``` 表示默认模式下启动一个任务

Ref
https://www.nvidia.cn/content/dam/en-zz/zh_cn/assets/webinars/31oct2019c/20191031_MPS_davidwu.pdf
https://docs.nvidia.com/deploy/pdf/CUDA_Multi_Process_Service_Overview.pdf
https://developer.download.nvidia.com/compute/DCGM/docs/nvidia-smi-367.38.pdf
https://docs.nvidia.com/datacenter/dcgm/2.0/dcgm-user-guide/feature-overview.html#profiling-metrics
