如何使用Nvidia多进程服务(MPS)运行多个非MPI CUDA应用程序?
我是否可以使用MPS在NVIDIA开普勒GPU上同时运行非MPI CUDA应用程序?我想这样做是因为我的应用程序不能充分利用GPU,所以我希望它们一起运行。是否有代码示例可以执行此操作?MPS服务的中包含了必要的说明。您会注意到,这些指令实际上并不依赖于或调用MPI,因此它们实际上没有任何MPI特定的内容 下面是一个演练/示例如何使用Nvidia多进程服务(MPS)运行多个非MPI CUDA应用程序?,cuda,gpu,gpgpu,nvidia,kepler,Cuda,Gpu,Gpgpu,Nvidia,Kepler,我是否可以使用MPS在NVIDIA开普勒GPU上同时运行非MPI CUDA应用程序?我想这样做是因为我的应用程序不能充分利用GPU,所以我希望它们一起运行。是否有代码示例可以执行此操作?MPS服务的中包含了必要的说明。您会注意到,这些指令实际上并不依赖于或调用MPI,因此它们实际上没有任何MPI特定的内容 下面是一个演练/示例 阅读上述链接文件的第2.3节,了解各种要求和限制。为此,我建议使用CUDA 7、7.5或更高版本。与以前版本的CUDA MPS存在一些配置差异,我将在这里不介绍这些差异。
$ cat t1034.cu
#include <stdio.h>
#include <stdlib.h>
#define MAX_DELAY 30
#define cudaCheckErrors(msg) \
do { \
cudaError_t __err = cudaGetLastError(); \
if (__err != cudaSuccess) { \
fprintf(stderr, "Fatal error: %s (%s at %s:%d)\n", \
msg, cudaGetErrorString(__err), \
__FILE__, __LINE__); \
fprintf(stderr, "*** FAILED - ABORTING\n"); \
exit(1); \
} \
} while (0)
#include <time.h>
#include <sys/time.h>
#define USECPSEC 1000000ULL
unsigned long long dtime_usec(unsigned long long start){
timeval tv;
gettimeofday(&tv, 0);
return ((tv.tv_sec*USECPSEC)+tv.tv_usec)-start;
}
#define APPRX_CLKS_PER_SEC 1000000000ULL
__global__ void delay_kernel(unsigned seconds){
unsigned long long dt = clock64();
while (clock64() < (dt + (seconds*APPRX_CLKS_PER_SEC)));
}
int main(int argc, char *argv[]){
unsigned delay_t = 5; // seconds, approximately
unsigned delay_t_r;
if (argc > 1) delay_t_r = atoi(argv[1]);
if ((delay_t_r > 0) && (delay_t_r < MAX_DELAY)) delay_t = delay_t_r;
unsigned long long difft = dtime_usec(0);
delay_kernel<<<1,1>>>(delay_t);
cudaDeviceSynchronize();
cudaCheckErrors("kernel fail");
difft = dtime_usec(difft);
printf("kernel duration: %fs\n", difft/(float)USECPSEC);
return 0;
}
$ nvcc -arch=sm_35 -o t1034 t1034.cu
$ ./t1034
kernel duration: 6.528574s
$
$ cat stop_as_root.bash
#!/bin/bash
echo quit | nvidia-cuda-mps-control
nvidia-smi -i 2 -c DEFAULT
$
mps\u run
脚本启动我们的测试应用程序时,在没有实际启用mps服务器的情况下,我们得到了预期的行为,即应用程序的一个实例需要大约5秒的时间,而另一个实例需要大约两倍的时间(~10秒),因为,由于它不会与来自另一进程的应用程序同时运行,因此在另一个应用程序/内核运行时,它会等待5秒,然后花5秒运行自己的内核,总共约10秒:
$ ./mps_run
kernel duration: 6.409399s
kernel duration: 12.078304s
$
$ su
Password:
# ./start_as_root.bash
Set compute mode to EXCLUSIVE_PROCESS for GPU 0000:82:00.0.
All done.
# exit
exit
$ ./mps_run
kernel duration: 6.167079s
kernel duration: 6.263062s
$
我们发现这两个应用程序运行的时间相同,因为由于MPS,内核同时运行使用上述通用方法证明这一点的另一种方法可能是使用由多个循环设置的内核持续时间,而不是通过读取SM时钟设置的内核持续时间,如前所述。在这种情况下,必须小心避免编译器“优化”循环。CUDA是否可以从头开始实现MPS?我不相信。@RobertCrovella您能分享一下您对这个问题的想法吗?你为什么认为这是不可能的?MPS似乎使用了一些未记录的驱动程序API或类似的东西吗?MPS接受从不同进程发出的工作(例如CUDA内核启动),并在设备上运行它们,就像它们从单个进程发出一样。就像它们在单个上下文中运行一样。我不知道如何使用我熟悉的当前公开的API做到这一点。除此之外,我没有任何进一步的想法,也不太可能回答关于这个话题的进一步问题。
$ ./mps_run
kernel duration: 6.409399s
kernel duration: 12.078304s
$
$ su
Password:
# ./start_as_root.bash
Set compute mode to EXCLUSIVE_PROCESS for GPU 0000:82:00.0.
All done.
# exit
exit
$ ./mps_run
kernel duration: 6.167079s
kernel duration: 6.263062s
$