【问题标题】:OpenCL device uniquenessOpenCL 设备唯一性
【发布时间】:2019-05-01 02:30:17
【问题描述】:

有没有办法让 OpenCL 为我提供所有具有 OpenCL 实现的唯一物理设备的列表?我知道如何遍历平台/设备列表,但例如,在我的情况下,我有一个 Intel 提供的平台,它为我的 CPU 提供了一个高效的设备实现,以及一个为我的 GPU 提供快速实现的 APP 平台,但是对我的 CPU 来说是一个糟糕的实现。

有没有办法确定这两个 CPU 设备实际上是同一个物理设备,这样我就可以选择最有效的一个并使用它,而不是同时使用它们并让它们相互竞争计算单个物理设备上的时间?

我查看了CL_DEVICE_VENDOR_IDCL_DEVICE_NAME,但它们并没有解决我的问题,CL_DEVICE_NAME 对于相同型号(双 GPU)的两个独立物理设备将是相同的,CL_DEVICE_VENDOR_ID 给了我取决于平台,我的 CPU 的 ID 不同。

理想的解决方案是某种唯一的物理设备 ID,但我很乐意手动更改 OpenCL 配置以自己重新排列设备(如果可能的话)。

【问题讨论】:

  • 我不明白这个问题......所以你想在两个具有相同规格的 CPU 之间进行选择?
  • 我想使用所有可用的物理设备(对于一个易于并行化的问题) - 我只想按物理设备使用单个逻辑设备,否则我会争用。

标签: opencl


【解决方案1】:

就我现在可以调查的问题而言,没有可靠的解决方案。如果您的所有工作都在单个进程中完成,您可以使用 clGetDeviceIDscl_device 值本身返回的条目顺序(本质上它们是指针),但如果您尝试在进程之间共享这些标识符,情况会变得更糟.

请参阅 that guy's blog post 并说:

问题在于,如果您有两个相同的 GPU,则无法区分它们。如果你调用clGetDeviceIDs,它们返回的顺序实际上是未指定的,所以如果第一个进程选择第一个设备,第二个进程选择第二个设备,它们都可能最终超额订阅同一个 GPU 并使另一个空闲.

但是,他指出 nVidia 和 AMD 提供了他们的自定义扩展,cl_amd_device_topologycl_nv_device_attribute_query。您可以检查您的设备是否支持这些扩展,然后按照以下方式使用它们(原作者的代码):

// This cl_ext is provided as part of the AMD APP SDK
#include <CL/cl_ext.h>

cl_device_topology_amd topology;
status = clGetDeviceInfo (devices[i], CL_DEVICE_TOPOLOGY_AMD,
    sizeof(cl_device_topology_amd), &topology, NULL);

if(status != CL_SUCCESS) {
    // Handle error
}

if (topology.raw.type == CL_DEVICE_TOPOLOGY_TYPE_PCIE_AMD) {
    std::cout << "INFO: Topology: " << "PCI[ B#" << (int)topology.pcie.bus
        << ", D#" << (int)topology.pcie.device << ", F#"
        << (int)topology.pcie.function << " ]" << std::endl;
}

或(我的代码,改编自上面链接的帖子):

#define CL_DEVICE_PCI_BUS_ID_NV  0x4008
#define CL_DEVICE_PCI_SLOT_ID_NV 0x4009

cl_int bus_id;
cl_int slot_id;

status = clGetDeviceInfo (devices[i], CL_DEVICE_PCI_BUS_ID_NV,
    sizeof(cl_int), &bus_id, NULL);
if (status != CL_SUCCESS) {
    // Handle error.
}

status = clGetDeviceInfo (devices[i], CL_DEVICE_PCI_BUS_ID_NV,
    sizeof(cl_int), &slot_id, NULL);
if (status != CL_SUCCESS) {
    // Handle error.
}

std::cout << "Topology = [" << bus_id <<
                         ":"<< slot_id << "]" << std::endl;

【讨论】:

  • “它们返回的顺序实际上是未指定的”哇!这比我预期的还要糟糕。无论如何,我的问题不是关于多个进程,而是更多关于暴露相同物理设备的不同平台(例如,英特尔 SDK 和 AMD SDK 都将相同的主 CPU 暴露为各自平台中的逻辑设备),但是这个拓扑扩展也解决了这个问题。感谢您的回答!
  • @Thomas:不客气!顺便说一句,clinfo 程序应该显示 nVidia 和 AMD 设备的拓扑标识符。你绝对应该have a look他们如何处理它,他们的代码似乎比我的更好。
【解决方案2】:
  • 如果您有两个属于一个平台的完全相同类型的设备,您可以通过 clGetDeviceIDs 返回的关联 cl_device_ids 来区分它们。

  • 如果您有可供两个不同平台使用的设备,您可以通过比较 CL_DEVICE_NAME 中的设备名称来消除第二个平台的条目。

  • 如果您想找到设备的预期平台,请分别比较来自 clGetPlatformInfo() 和 clGetDeviceInfo 的 CL_PLATFORM_VENDOR 和 CL_DEVICE_VENDOR 字符串。

您可以将所有平台及其所有关联设备读入单独的特定于平台的列表中,然后通过比较单独列表中的设备名称来消除双精度。这应该确保您不会为不同的平台获得相同的设备。

最后,您可以通过命令行参数或配置文件等方式,为您的应用程序提供参数,以将某种类型的设备(CPU、GPU、加速器)与特定平台相关联(如果存在不同平台的选择)设备类型。希望这能回答您的问题。

【讨论】:

    【解决方案3】:

    无论如何,我们假设您正在尝试提取所有设备的唯一 ID,实际上您可以简单地使用 clGetDeviceIDs 进行查询:

    cl_int clGetDeviceIDs(cl_platform_id platform,
                          cl_device_type device_type,
                          cl_uint num_entries,
                          cl_device_id *devices,
                          cl_uint *num_devices)
    

    然后您的设备列表将被插入到 *devices 数组中,然后您可以执行 clGetDeviceInfo() 来找出您想要使用的设备。

    【讨论】:

    • 我想使用所有这些,但我不希望多个逻辑设备访问任何物理设备。
    • 如果我没有弄错,您想在所有设备同时运行的情况下进行多线程吗?如果是这样,那么您可能想查看 CUDA 的 OpenCL 计算 SDK,即 oclMultiThreads 源代码,您可以在其中手动划分工作,然后使用可用设备异步运行它们
    • 不,我的问题比这更微妙。我知道我可以列出所有设备并对它们进行多线程处理。但问题是单个物理设备(例如,我唯一的 CPU)作为两个逻辑设备(每个 OpenCL 平台中的一个)出现 - 两个逻辑设备上的多线程将导致对唯一物理 CPU 的资源争用(这甚至更多对 GPU 来说是真的)所以我想检测这两个逻辑设备指向同一个物理设备并且只使用其中一个。
    • 啊,我终于明白了你的问题。我不知道您是如何对设备进行分区并告诉他们运行相同的 opencl 程序的,但是还有一种方法可以将设备划分为具有 OpenCL 扩展名的子设备,您可以查看此处的说明: khronos.org/registry/cl/extensions/ext/…。我认为它同时支持 Intel 和 AMD,但我不保证它与您的环境兼容。
    【解决方案4】:

    结合上面的答案,我的解决方案是:

    long bus = 0; // leave it 0 for Intel
    // update bus for NVIDIA/AMD ...
    // ...
    long uid = (bus << 5) | device_type;
    

    变量 bus 是根据 NVIDIA/AMD 设备特定信息查询计算得出的,如 firegurafiku 所述,变量 device_typeclGetDeviceInfo(clDevice, CL_DEVICE_TYPE, sizeof(cl_device_type), &amp;device_type, nullptr) API 调用的结果,如 Steinin 建议的那样。

    这种方法解决了集成 GPU 的 Intel CPU 具有相同唯一 ID 的问题。由于CL_DEVICE_TYPE 的不同,现在两个设备都有唯一的标识符。

    令人惊讶的是,在Oclgrind 模拟设备Oclgrind simulator 设备上运行代码的情况也获得唯一标识符15,与我系统上的任何其他设备不同。

    建议的方法可能失败的唯一情况 - 单个主板上的多个相同型号的 CPU。

    【讨论】:

    • 现在事情稍微简单了一点,如果设备支持的话,还有 2 个 Khronos 扩展。第一个是cl_khr_device_uuid,它根据需要返回唯一的uid。最后一个是cl_khr_pci_bus_info,它提供了与平台无关的方法来提取 PCI 总线信息。英特尔酷睿 i7 6700 hq 与英特尔高清显卡和最新驱动程序支持cl_khr_pci_bus_info。带有最新驱动程序的 Nvidia geforce 940 mx 支持cl_khr_device_uuid
    猜你喜欢
    • 1970-01-01
    • 2015-11-03
    • 1970-01-01
    • 1970-01-01
    • 2016-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-26
    相关资源
    最近更新 更多