OpenCL device uniqueness

  • If you have two devices of the exact same kind belonging to a platform, you can tell them apart by the associated cl_device_ids return by clGetDeviceIDs.

  • If you have devices that can be used by two different platforms you can eliminate the entries for the second platform by comparing the device names from CL_DEVICE_NAME.

  • If you want to find the intended platform for a device, compare the CL_PLATFORM_VENDOR and CL_DEVICE_VENDOR strings from clGetPlatformInfo() and clGetDeviceInfo respectively.

You can read in all platforms and all their associated devices into separate platform-specific lists and then eliminate doubles by comparing the device names in the separate lists. This should ensure that you do not get the same device for different platforms.

Finally you can, by command line arguments or configuration file for example, give arguments to your application to associate devices of a certain type (CPU, GPU, Accelerator) with a specific platform if there exists a choice of different platforms for a device type. Hopefully this will answer your question.


As far as I could investigate the issue now, there is no reliable solution. If all your work is done within a single process, you may use the order of entries returned by clGetDeviceIDs or cl_device values themselves (essentially they're pointers), but things get worse if you try to share those identifiers between processes.

See that guy's blog post about it, saying:

The issue is that if you have two identical GPUs, you can’t distinguish between them. If you call clGetDeviceIDs, the order in which they are returned is actually unspecified, so if the first process picks the first device and the second takes the second device, they both may wind up oversubscribing the same GPU and leaving the other one idle.

However, he notes that nVidia and AMD provide their custom extensions, cl_amd_device_topology and cl_nv_device_attribute_query. You may check whether these extensions are supported by your device, and then use them as the following (the code by original author):

// 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;
}

or (code by me, adapted from the above linked post):

#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;

Tags:

Opencl