OpenCL Platform Information Using C++ and CMake

OpenCL logo

Each OpenCL platform is an implementation of OpenCL on a company hardware. Because OpenCL is an application programming interface (API) each brand chooses how to implement it on their hardware. This implementation can be done over GPUs, CPUs, FPGAs, and other kind of accelerators.

Is the responsibility of each brand to maintain and fix the implementation on their hardware. Those brands like AMD, Nvidia and Intel most commonly, have to offer drivers and runtimes to be able to execute and compile OpenCL programs on their hardware. Not all the functions must be supported on all the hardware that implement OpenCL, for this reason you can request each device of that platform what operations do they support and is the responsibility of the programmer to handle multiple vendors different capabilities.

A platform is used to discover the available hardware and retrieve all the devices. This will be used to discover their capabilities and harvest all their computational power.

Platform C Construct

Programming OpenCL in C++ is a wrapper to the C functions, the C function to initialize the platform structures is the following:

// Provided by CL_VERSION_1_0
cl_int clGetPlatformIDs(
    cl_uint num_entries,
    cl_platform_id* platforms,
    cl_uint* num_platforms);

The parameters of the function are the following

  • num_entries is the number of cl_platform_id entries that can be added to platforms. If platforms is not NULL, num_entries must be greater than zero.
  • platforms returns a list of OpenCL platforms found. The cl_platform_id values returned in platforms can be used to identify a specific OpenCL platform. If platforms is NULL, this argument is ignored. The number of OpenCL platforms returned is the minimum of the value specified by num_entries or the number of OpenCL platforms available.
  • num_platforms returns the number of OpenCL platforms available. If num_platforms is NULL, this argument is ignored.

In C, the function has to be called twice. First to get the number of platforms and second to initialize the structures once allocated.

cl_platform_id *platforms;
cl_uint num_platforms;
clGetPlatformIDs(10, NULL, &num_platforms);
platforms = (cl_platform_id*)
malloc(sizeof(cl_platform_id) * num_platforms);
clGetPlatformIDs(num_platforms, platforms, NULL);

Note:

Note that num_entries is the maximum number of platforms you are interested in finding while num_platforms are the number of platforms found on the system

The C++ Wrapper uses vector to dynamically retrieve the platform classes using the static method get()

public: static cl_int Platform::get(std::vector<Platform> *platforms)

The code to retrieve all the platforms can be with the following two lines:

std::vector<cl::Platform> platforms{};
cl::Platform::get(&platforms);

main.cpp

The following code section uses cl::Platform::get(&platforms); to collect all the platforms into a std::vector<cl::Platform>

#include <iostream>
#include <CL/opencl.hpp>

int main() {
    // initialize a vector to store the platforms
    std::vector<cl::Platform> platforms{};

    // collect the platforms available
    cl::Platform::get(&platforms);

    // make sure at least we have a platform
    if (platforms.empty()){
        std::cerr << "No platforms found!" << std::endl;
        exit(1);
    }

    std::cout << "Number of platforms found: " << platforms.size() << std::endl;
    // iterate over each platform
    for (const cl::Platform& platform : platforms) {
        std::cout << "\tPlatform name: " << platform.getInfo<CL_PLATFORM_NAME>() << std::endl;
        std::cout << "\tPlatform vendor: " << platform.getInfo<CL_PLATFORM_VENDOR>() << std::endl;
        std::cout << "\tPlatform version: " << platform.getInfo<CL_PLATFORM_VERSION>() << std::endl;
        std::cout << "\tPlatform profile: " << platform.getInfo<CL_PLATFORM_PROFILE>() << std::endl;
        std::cout << "\tPlatform extensions: " << platform.getInfo<CL_PLATFORM_EXTENSIONS>() << std::endl;

        // collect the devices
        std::vector<cl::Device> devices;
        platform.getDevices(CL_DEVICE_TYPE_ALL, &devices);

        std::cout << "\tPlatform devices: " << devices.size() << std::endl;
        std::cout << "\n----------\n" << std::endl;
    }

    std::cout << "Done!" << std::endl;
    return 0;
}

CMakeLists.txt Code

cmake_minimum_required(VERSION 3.28)
project(OpenCL_PlatformInformation LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)

add_executable(${PROJECT_NAME} main.cpp)

find_package(OpenCL REQUIRED)
target_link_libraries(${PROJECT_NAME} OpenCL::OpenCL)

target_compile_definitions(${PROJECT_NAME} PRIVATE CL_HPP_TARGET_OPENCL_VERSION=300)

Program Output

This is the output of my current system:

Number of platforms found: 2
	Platform name: Clover
	Platform vendor: Mesa
	Platform version: OpenCL 1.1 Mesa 22.3.6
	Platform profile: FULL_PROFILE
	Platform extensions: cl_khr_icd
	Platform devices: 1

----------

	Platform name: rusticl
	Platform vendor: Mesa/X.org
	Platform version: OpenCL 3.0
	Platform profile: FULL_PROFILE
	Platform extensions: cl_khr_icd
	Platform devices: 0

----------

Done!

Process finished with exit code 0

If you spot any typos, have questions, or need assistance with the build, feel free to contact me at: antonimercer@lthjournal.com

This guide contains no affiliate links or ads. If you'd like to support this or future projects, you can do so here:

By supporting monthly you will help me create awesome guides and improve current ones.


Technologies used

Debian 12, Linux, OpenCL, C++, AMD, Nvidia, Intel, GPU

Books are knowledge and knowledge is power.

After ending my studies, I always tried to dedicate some time to books. They helped me a lot and I want to dedicate a little space here as a greeting. From basics on different languages to more advanced level.