mans
mans

Reputation: 18148

How to find all opencl devices on a system?

I have this code:

// http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clGetPlatformIDs.html
cl_uint platformIdCount = 0;
clGetPlatformIDs(0, nullptr, &platformIdCount);

if (platformIdCount == 0) {
    std::cerr << "No OpenCL platform found" << std::endl;
    return 1;
}
else {
    std::cout << "Found " << platformIdCount << " platform(s)" << std::endl;
}

std::vector<cl_platform_id> platformIds(platformIdCount);
clGetPlatformIDs(platformIdCount, platformIds.data(), nullptr);

for (cl_uint i = 0; i < platformIdCount; ++i) {
    std::cout << "\t (" << (i + 1) << ") : " << GetPlatformName(platformIds[i]) << std::endl;
}

// http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/clGetDeviceIDs.html
cl_uint deviceIdCount = 0;
clGetDeviceIDs(platformIds[1], CL_DEVICE_TYPE_ALL, 0, nullptr,
    &deviceIdCount);

if (deviceIdCount == 0) {
    std::cerr << "No OpenCL devices found" << std::endl;
    return 1;
}
else {
    std::cout << "Found " << deviceIdCount << " device(s)" << std::endl;
}

std::vector<cl_device_id> deviceIds(deviceIdCount);
clGetDeviceIDs(platformIds[1], CL_DEVICE_TYPE_ALL, deviceIdCount,
    deviceIds.data(), nullptr);

for (cl_uint i = 0; i < deviceIdCount; ++i) {
    std::cout << "\t (" << (i + 1) << ") : " << GetDeviceName(deviceIds[i]) << std::endl;
}

and I am running it on a laptop that has 2 gpu, one HD4400 and GForce 750.

When I run it, I am getting two platform and each platform has the device for that specific manufacturer, for example on platform 0, I am getting i7 and HD4400 and on platform 1, I am getting GeForce 750.

I thought that I can get all devices from one platform?

Am I correct to believe to find a suitable device, I need to go over all platforms and find devices which are for GPU and then I have the list of all devices?

What is the correct way to find suitable device for a task?

Say I want to find GPU with maximum memory or maximum worker?

Is there any library that can help me on this?

Upvotes: 4

Views: 14446

Answers (3)

ProjectPhysX
ProjectPhysX

Reputation: 5736

The OpenCL platform basically denotes the manufacturer. If you would have two (can be different models) Nvidia GPUs, they would be on the same platform. But Intel and Nvidia are different platforms.

Yes, you need to specifically select one device for your OpenCL computations. Therefore you iterate over all platforms and for every platform over all of its devices in order to get a list of all available OpenCL devices. Then from this list you can select the best/fastest one (in your case the GForce 750 as it is both faster than the HD4400 and has more video memory).

Here is some code that will give you a list of all available devices in the devices vector. Select the GeForce 750 with devices[1].

std::vector<Device> devices;
int find_devices() {
    std::vector<Platform> platforms; // get all platforms
    std::vector<Device> devices_available;
    int n = 0; // number of available devices
    Platform::get(&platforms);
    for(int i=0; i<(int)platforms.size(); i++) {
        devices_available.clear();
        platforms[i].getDevices(CL_DEVICE_TYPE_ALL, &devices_available);
        if(devices_available.size()==0) continue; // no device found in plattform i
        for(int j=0; j<(int)devices_available.size(); j++) {
            n++;
            devices.push_back(devices_available[j]);
        }
    }
    if(platforms.size()==0||devices.size()==0) {
        std::cout << "Error: There are no OpenCL devices available!" << std::endl;
        return -1;
    }
    for(int i=0; i<n; i++) std::cout << "ID: " << i << ", Device: " << devices[i].getInfo<CL_DEVICE_NAME>() << std::endl;
    return n; // return number of available devices
}

For an easy start with OpenCL, I created a lightweight wrapper that vastly simplifies the OpenCL C++ bindings and eliminates the entire code overhead that comes with it. You can get the list of all available devices with get_devices() and automatically find the fastest device with select_device_with_most_flops(): https://github.com/ProjectPhysX/OpenCL-Wrapper

Upvotes: 5

把友情留在无盐
把友情留在无盐

Reputation: 279

clinfo[1] utility and clinfo[2] utility show available platforms and devices information. They are good for local use. khronos clGetPlatformIDs and clGetDeviceIDs are good for runtime detection when distributing software.

1: https://github.com/Oblomov/clinfo 1: https://sf.net/p/clinfo

Upvotes: 1

Dithermaster
Dithermaster

Reputation: 6333

You cannot get all devices in one platform.

At most, you'll just see devices from the same vendor grouped together (e.g., AMD CPU and AMD GPU, or Intel CPU and GPU). On Windows (and I presume Linux) you might see multiple platforms. On Mac OS X, I've only ever seen one (with the CPU and all GPUs).

You are correct that you need to iterate all platforms and all devices to find them all. You can filter to what you'll support, and sort based on capabilities.

Upvotes: 1

Related Questions