11

有没有办法让 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 配置以自己重新排列设备(如果可能的话)。

4

4 回答 4

5

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

看到那个人的博客文章,说:

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

但是,他指出 nVidia 和 AMD 提供了他们的自定义扩展,cl_amd_device_topology并且cl_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;
于 2016-03-15T20:06:53.230 回答
3
  • 如果您有两个属于一个平台的完全相同类型的设备,您可以通过 clGetDeviceIDs 返回的关联 cl_device_ids 来区分它们。

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

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

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

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

于 2013-11-07T13:16:27.653 回答
0

无论如何,让我们假设您正在尝试提取所有设备的唯一 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() 来找出您想要使用的设备。

于 2012-06-02T02:27:22.703 回答
0

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

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

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

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

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

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

于 2019-04-30T18:30:17.517 回答