在多 GPU 系统中,给定 PCI 供应商、设备和总线 ID,如何将 OpenCL 设备与特定 GPU 匹配?
Posted
技术标签:
【中文标题】在多 GPU 系统中,给定 PCI 供应商、设备和总线 ID,如何将 OpenCL 设备与特定 GPU 匹配?【英文标题】:How to match OpenCL devices with a specific GPU given PCI vendor, device and bus IDs in a multi-GPU system? 【发布时间】:2011-11-08 18:08:05 【问题描述】:我希望能够在由 PCI ID 标识的多 GPU 系统上将 OpenCL 设备与系统中的 GPU 进行匹配。
例如,如果我有一个带有多个 GPU 的系统,可能来自不同的供应商,我可以通过枚举 PCI 总线来列出设备。这给了我 PCI 供应商、设备和总线 ID。如果我根据某些选择标准选择这些 (GPU) PCI 设备之一用于 OpenCL 计算,如何将其与 OpenCL 设备匹配?
我可以使用 clGetDeviceIDs() 在 OpenCL 中枚举 GPU 设备,但是没有明显的方法可以将 OpenCL 设备与 PCI 设备匹配。 OpenCL 函数 clGetDeviceInfo() 提供对 PCI 供应商 ID 和设备名称的访问,但不提供对 PCI 设备或总线 ID 的访问。我可以尝试将 PCI 设备名称与 OpenCL 设备名称进行匹配,但您可能拥有多个相同类型的设备,而且名称并不总是相同。
为什么这是必要的?假设我知道程序 X 在 GPU A 上运行 CUDA 或其他东西。我想避免也将 GPU A 用于 OpenCL 操作,所以我选择 GPU B。然后我需要确定哪个 OpenCL 设备是 GPU A,哪个是 GPU B. PCI ID 似乎是识别 GPU 设备的唯一一致且跨平台的方式。
顺便说一句,CUDA API 确实为您提供了 PCI、总线和插槽 ID(CU_DEVICE_ATTRIBUTE_PCI_BUS_ID、CU_DEVICE_ATTRIBUTE_PCI_DEVICE_ID),但 CUDA 仅适用于 NVidia 设备。
理想情况下,我需要使用 C 或 C++ 的解决方案。
【问题讨论】:
规范说 CL_DEVICE_VENDOR_ID “可能是 PCIe ID”。如果这不能得到你想要的,那么我认为规范中没有任何东西可以。不过,仍然不确定为什么需要这个。听起来像是过早的优化。 @vocaro:是的,我可以获得供应商 ID。我认为你没有理解这个问题。 您说您想知道 PCI 设备 ID 以避免与可能正在使用特定 PCI 设备 ID 的另一个进程发生争用。我想知道您如何知道正在使用哪些 PCI 设备?我猜你没有为此使用 OpenCL? 最近它添加了一个新的 Khronos 扩展,可以在这里提供帮助:khronos.org/registry/OpenCL/specs/3.0-unified/html/… 【参考方案1】:这样做的方法是使用两个特定于供应商的扩展。对于 AMD,您必须使用CL_DEVICE_TOPOLOGY_AMD
,它适用于 Windows 和 Linux,并将返回 PCIe 总线 ID,这是 GPU 独有的。在 NVIDIA 上,查询设备以获取 CL_DEVICE_PCI_BUS_ID_NV。另见:https://anteru.net/2014/08/01/2483/
【讨论】:
我还没有尝试过,但这似乎是正确的答案。太棒了,感谢您的回答和近 3 年的等待。 抱歉拖了这么久,我之前没有遇到问题 :) 感谢您将此标记为正确答案。CL_DEVICE_PCI_BUS_ID_NV
是否适用于 Windows 上的 Nvidia 驱动程序?我正在 PyOpenCL 中尝试此操作,但不断收到错误提示它是无效值。
应该做,不知道那里发生了什么。很遗憾,我现在无法检查。【参考方案2】:
不幸的是,由于 openCL 的抽象性质,您正在寻找的答案并不漂亮。
我发现可靠地做到这一点的唯一方法是在 openCL 中将要求苛刻的工作负载分配给平台 + 设备 ID,然后通过 AMD 的 ADL 和 Nvidia 的 NVML 等工具监控进程使用情况。即使是像 cgminer 这样的成熟应用程序也有这个问题,并且经常将 openCL 工作负载与卡指标混为一谈,以至于他们分配配置变量来手动更正它(“gpu-map”)。
我希望现在有一个更好的答案,因为通过 openCL 知道端点后面的设备会很棒!这可能会在未来发生变化,正如 arsenm 指出的那样,AMD 正在努力将此层添加到 openCL。
【讨论】:
【参考方案3】:似乎 Anteru 的答案是正确的,但前提是您运行的是 linux/mac。 经过我做的一些测试,Windows 似乎无法识别这些供应商特定的扩展。 (我已经在 Geforce GTX Titan 和 ATI Radeon R9 上测试过)
我对您的解决方案是使用带有“CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR”参数的 clGetGLContextInfoKHR() 函数(自 openCL 规范 1.1 起可用),这将确保您获得与执行渲染的同一 GPU 匹配的 openCL 设备 ID。
没错,这不会为您提供物理总线插槽,但可以确保渲染的 GPU 与计算的 GPU 相同!
另外,假设一个人使用 Nvidia Quadro 卡,那么他可以使用 wgl_nv_gpu_affinity 来确保 openGL 访问特定的 GPU,然后使用 GL 上下文并从中获取 openCL 设备 ID。
【讨论】:
【参考方案4】:最新的 AMD 版本在 Linux 上具有 cl_device_topology_amd 扩展,它将 CL_DEVICE_TOPOLOGY_AMD 选项添加到 clGetDeviceInfo(),但这是一个非常狭窄的解决方案。
【讨论】:
是的,还需要覆盖 NVidia 卡。【参考方案5】:我为此开发了一个库:防止 OpenCL 模拟相互踩踏。
你会在这里找到它:https://github.com/nbigaouette/oclutils/
它首先枚举机器上存在的每个平台的所有平台和每个设备。您选择想要的平台,它将选择可用的最佳设备。我在带有 3 个 nvidia 卡的工作站上使用它:两个 GTX 580 用于 OpenCL 计算,一个 GT 210 用于显示。同时运行两个模拟将分别在两个 GTX 上运行。无需干预。
还有一个很好的类可以保持两个缓冲区同步:一个在主机上,一个在设备上。调用 OpenCL_Array::Host_to_Device() 和 OpenCL_Array::Device_to_Host() 使来回传输变得简单。
它适用于这些平台:
nvidia(仅限 GPU) amd(CPU 和/或 GPU) 英特尔(仅限 CPU) 苹果(CPU 和/或 GPU)请注意,它不会让您选择使用哪个设备,而是为您选择一个。如果一个程序的两个实例使用该库,它们会知道它并且不会在同一设备上运行(当然,如果你也有的话)。目前,它也无法检测视频卡是否用于显示。但至少这是一个开始!
【讨论】:
据我了解,您的回答并未解决将 PCI 设备 ID 与 OpenCL 计算设备匹配的问题。你正在解决一个相关的问题,但它对我需要的没有帮助。如果我错了,请解释。请记住,我还希望能够使用 CUDA 并仍然跟踪哪个设备是哪个。以上是关于在多 GPU 系统中,给定 PCI 供应商、设备和总线 ID,如何将 OpenCL 设备与特定 GPU 匹配?的主要内容,如果未能解决你的问题,请参考以下文章