使用 sge 和名为“gpu.q”的资源复合体,可以管理 gpu 设备的资源(这些都是 nvidia 设备)。但是,系统上有多个 gpu 设备(独占模式),如果两个作业分配在同一节点上,则用户无法在正确的 gpu 上不透明地创建上下文。
有人遇到过这个问题吗?我在想办法管理特定的 GPU 资源并映射主机和设备 ID。比如
hostA -> gpu0:in_use
hostA -> gpu1:free
hostB -> gpu0:free
hostB -> gpu1:in_use
等等...然后在资源请求时,通过 CUDA_VISIBLE_DEVICES 变量显示每个主机上分配的 gpu 资源。
这似乎是一个相当常见的问题 - 随着计算集群中 gpu 的普及,现在一定有人已经解决了这个问题。
答案1
正如我通过艰难的方式发现的那样,您不能只枚举设备然后调用 cudaSetDevice()。如果设备存在并且您尚未创建上下文,则 CudaSetDevice() 始终会成功。我在这里根据 NVidians 的一些提示制定的解决方案是使用 nvidia-smi 将所有 GPU 上的计算模式设置为处理独占,然后使用 cudaSetValidDevices() 过滤掉不能用于您的任务的设备,最后调用 cudaFree() 以强制 CUDA 驱动程序在可用设备上创建上下文。
如果调用 cudaFree 失败,则表示没有可用的设备:
// Let CUDA select any device from this list of device IDs filtered by your
// own criteria (not shown)
status = cudaSetValidDevices(pGPUList, nGpus);
if (status != cudaSuccess)
{
printf(("Error searching for compatible GPU\n");
exit(-1);
}
// Trick driver into creating a context on an available and valid GPU
status = cudaFree(0);
if (status != cudaSuccess)
{
printf("Error selecting compatible GPU\n");
exit(-1);
}
// Get device selected by driver
status = cudaGetDevice(&device);
if (status != cudaSuccess)
{
printf("Error fetching current GPU\n");
exit(-1);
}
// Your amazing CUDA program goes here...
注意:如果 GPU 未处于独占模式,则需要以某种方式从排队系统中明确管理它们。此处描述的方法将允许使用可消耗资源来监视节点上的所有任务,以确保它们从未请求超过节点上可用数量的 GPU,然后利用独占模式来防止冲突。
答案2
这确实是一个应该在代码级别解决的问题。如果您的设备处于独占模式,则可以使用 CUDA API 枚举所有 GPU,然后尝试选择它们,直到找到一个可用的 GPU。如果您尝试选择已在使用的独占模式的设备,CUDA API 将返回错误,在这种情况下,您只需转到下一个设备即可。您不需要对调度做任何花哨的事情。