将 CUDA_VISIBLE_DEVICES 与 sge 结合使用

将 CUDA_VISIBLE_DEVICES 与 sge 结合使用

使用 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 将返回错误,在这种情况下,您只需转到下一个设备即可。您不需要对调度做任何花哨的事情。

相关内容