【问题标题】:How does CUDA assign device IDs to GPUs?CUDA 如何将设备 ID 分配给 GPU?
【发布时间】:2012-11-26 17:34:32
【问题描述】:

当一台计算机有多个支持 CUDA 的 GPU 时,每个 GPU 都被分配一个device ID。默认情况下,CUDA 内核在device ID 0 上执行。您可以使用cudaSetDevice(int device) 选择其他设备。

假设我的机器中有两个 GPU:一个 GTX 480 和一个 GTX 670。CUDA 如何确定哪个 GPU 是 device ID 0 以及哪个 GPU 是 device ID 1


关于 CUDA 如何分配设备 ID 的想法(只是头脑风暴):

  • 计算能力的降序
  • PCI 插槽号
  • 设备添加到系统的日期/时间(刚刚添加到计算机的设备 ID 号较高)

动机:我正在研究一些 HPC 算法,并且我正在针对多个 GPU 对它们进行基准测试和自动调整。我的处理器有足够的 PCIe 通道以全带宽将 cudaMemcpys 驱动到 3 个 GPU。因此,我打算在我的计算机中只保留 3 个 GPU,而不是不断地在我的机器中进出 GPU。我希望能够预测当我在计算机中添加或更换一些 GPU 时会发生什么。

【问题讨论】:

    标签: cuda gpu gpgpu nvidia


    【解决方案1】:

    设置环境变量CUDA_DEVICE_ORDER为:

    export CUDA_DEVICE_ORDER=PCI_BUS_ID
    

    那么 GPU ID 将按 pci 总线 ID 排序。

    【讨论】:

    • 有了这个集合,CUDA 设备ID 与nvidia-smi 的输出一致! IMO 这是在多 GPU 机器上进行机器学习的必备工具。
    【解决方案2】:

    CUDA 选择最快的设备作为设备 0。因此,当您交换 GPU 时,顺序可能会完全改变。根据 PCI 总线 ID 选择 GPU 可能会更好:

    cudaError_t cudaDeviceGetByPCIBusId ( int* device, char* pciBusId )
       Returns a handle to a compute device.
    
    cudaError_t cudaDeviceGetPCIBusId ( char* pciBusId, int  len, int  device )
       Returns a PCI Bus Id string for the device.
    

    或 CUDA 驱动程序 API cuDeviceGetByPCIBusId cuDeviceGetPCIBusId

    但是 IMO 知道哪个设备是哪个设备的最可靠方法是使用 NVMLnvidia-smi 使用 nvmlDeviceGetUUID 获取每个设备的唯一标识符 (UUID),然后使用 @ 将其与 pciBusId 匹配它做 CUDA 设备987654327@.

    【讨论】:

    • “最快”是指时钟速度吗?
    • 一些启发式方法用于估计 GPU 的理论速度。他们考虑到例如芯片架构、时钟速度、驱动模型(Windows TCC 优先)。
    • 目前,我的机器中有 3 个支持 CUDA 的 GPU:一个 GTX680、一个 GTX9800(我只用于图形的古老、缓慢的 GPU)和一个 C2050。奇怪的是,GTX9800 的数字比 C2050 低……奇怪。
    • 只有索引为 0 的 GPU 是最快的。其余索引不按速度排序。 GTX 9800 是否有索引 0?如果没有,那么一切都按预期工作。
    • 不,GTX9800 没有索引 0。现在更有意义了。
    【解决方案3】:

    CUDA Support/Choosing a GPU 建议

    在具有多个 GPU 的机器上运行 CUDA 程序时,默认情况下 CUDA 内核将在主显卡插槽中安装的任何 GPU 上执行。

    此外,No GPU selected, code working properly, how's this possible? 的讨论表明 CUDA 通常不会将“最佳”卡映射到设备 0。

    编辑

    今天我安装了一台带有用于计算的 Tesla C2050 卡和用于可视化的 8084 GS 卡的 PC,在前两个 PCI-E 插槽之间切换它们的位置。我使用了 deviceQuery 并注意到 GPU 0 始终位于第一个 PCI 插槽中,而 GPU 1 始终位于第二个 PCI 插槽中。我不知道这是否是一个笼统的说法,但它证明了对于我的系统,GPU 的编号不是根据它们的“功率”,而是根据它们的位置。

    【讨论】:

    • 我同意。我曾经遇到过机器有现代 GTX6xx 开普勒和古代 G80 的情况,设备 0 是 G80。相反的情况也发生在我身上。 “PCIe 插槽顺序”的解释听起来很合理。除了尝试为兼容 PCIe_3 的 GPU 保留 PCIe_3 插槽外,我并没有太注意我使用的 PCIe 插槽顺序。
    【解决方案4】:

    我发现的最佳解决方案(在tensorflow==2.3.0 中测试)是在可能导入tensorflow 的任何内容之前添加以下内容:

    import os
    os.environ["CUDA_DEVICE_ORDER"]="PCI_BUS_ID"
    os.environ["CUDA_VISIBLE_DEVICES"]="0,3"  # specify which GPU(s) to be used
    

    这样一来,TensorFlow 订购 GPU 的顺序将与 nvidia-sminvtop 等工具报告的顺序相同。

    【讨论】:

    • 这如何以任何方式解释 CUDA 枚举设备的顺序,这是问题所在?
    • 因为 OP 要求“我希望能够预测当我在计算机中添加或更换一些 GPU 时会发生什么”,而我的回答就是这样做的。
    猜你喜欢
    • 1970-01-01
    • 2017-08-04
    • 2011-11-08
    • 2015-04-22
    • 1970-01-01
    • 2020-05-10
    • 1970-01-01
    • 2019-12-02
    相关资源
    最近更新 更多