OpenCL设备的唯一性

时间:2012-06-01 15:00:31

标签: opencl

有没有办法让OpenCL为我提供所有可用OpenCL实现的独特物理设备的列表?我知道如何遍历平台/设备列表但是,例如,在我的情况下,我有一个英特尔提供的平台,它为我的CPU提供了高效的设备实现,以及为我的GPU提供快速实现的APP平台但是我的CPU实施得很糟糕。

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

我查看了CL_DEVICE_VENDOR_IDCL_DEVICE_NAME但是他们没有解决我的问题,CL_DEVICE_NAME对于同一型号的两个独立的物理设备是相同的(双GPU' s和CL_DEVICE_VENDOR_ID根据平台为我的CPU提供了不同的ID。

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

4 个答案:

答案 0 :(得分:5)

就我现在可以调查的问题而言,没有可靠的解决方案。如果您的所有工作都在一个过程中完成,您可以使用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;

答案 1 :(得分:3)

  • 如果您有两个属于某个平台的完全相同类型的设备,您可以通过clGetDeviceIDs返回相关联的cl_device_ids来区分它们。

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

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

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

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

答案 2 :(得分: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()来找出你想要使用的设备。

答案 3 :(得分:0)

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

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), &device_type, nullptr) API调用的结果,如{{3 }}。

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

令人惊讶的是,在Steinin模拟的设备Oclgrind simulator设备上运行代码的情况下,也获得了唯一的标识符15,与我的系统上的其他标识符都没有区别。

建议的方法失败的唯一情况是-一块主板上有多个相同型号的CPU。