【OpenCL开发入门】02 - 获取当前设备所有OpenCL的信息

【OpenCL开发入门】02 - 获取当前设备所有OpenCL的信息


本系列文章汇总:

  1. 【OpenCL开发入门】01 - 搭建Visual Studio 2022+OpenCL开发环境
  2. 【OpenCL开发入门】02 - 获取当前设备所有OpenCL的信息
  3. 【OpenCL开发入门】03 - 使用NVIDIA CUDA GPU 进行乘法运行算

本章只是OpenCL的入门代码,我们先来获取获取当前设备所有支持OpenCL的平台下的所有设备的信息。
代码中配有详细注释,就不额外单独写代码解读了。

一、未封装前的代码

#include <cstdlib>
#include <iostream>
#include <iomanip>
#include <cstring>
#include <cassert>

#include <CL/cl.h>

using namespace std;

// 检查返回值错误
#define CHECK_ERRORS(ERR) \
	if(ERR != CL_SUCCESS){ \
		cerr << "OpenCL error code" << ERR << "file: " << __FILE__  << "line: " << __LINE__ << ".\nExiting..." << endl; \
		exit(1); \
	}

int main(int argc, const char** argv)
{
	cl_int err = CL_SUCCESS;

	// 1. 获取当前设备所有支持OpenCL的平台的数量
	cl_uint num_of_platforms = 0;
	err = clGetPlatformIDs(0, 0, &num_of_platforms);
	CHECK_ERRORS(err);

	// 2. 获取当前设备所有支持OpenCL的平台的信息
	cl_platform_id* platforms = new cl_platform_id[num_of_platforms];
	err = clGetPlatformIDs(num_of_platforms, platforms, 0);
	CHECK_ERRORS(err);

	cl_char platform_names[10][50];
	// 3. 打印平台信息
	cout << "平台信息:\n";
	for (cl_uint i = 0; i < num_of_platforms; i++)
	{
		// 获取平台字符串的长度
		size_t platform_name_length = 0;
		err = clGetPlatformInfo(platforms[i], CL_PLATFORM_NAME, 0, 0, &platform_name_length);
		CHECK_ERRORS(err);

		// 获取平台字符串
		char* platform_name = new char[platform_name_length];
		err = clGetPlatformInfo(platforms[i], CL_PLATFORM_NAME, platform_name_length, platform_name, 0);
		CHECK_ERRORS(err);

		cout << "    [" << i << "] " << platform_name << endl;

		// 备份platform name
		if (i < 10) {
			memset(platform_names[i], 0, 50);
			memcpy(platform_names[i], platform_name, platform_name_length);
		}

		delete[] platform_name;
	}

	// 4. 查询各平台设备数量
	struct {
		cl_device_type type;
		const  char* name;
		cl_uint count;
	}devices[] = {
		{CL_DEVICE_TYPE_GPU, "CL_DEVICE_TYPE_GPU", 0},					// GPU
		{CL_DEVICE_TYPE_CPU, "CL_DEVICE_TYPE_CPU", 0},					// CPU
		{CL_DEVICE_TYPE_ACCELERATOR, "CL_DEVICE_TYPE_ACCELERATOR", 0}	// 加速器
	};

	// 5. 遍历查询各个平台下拥有的设备数量
	for (cl_int j = 0; j < num_of_platforms; j++) {
		cl_platform_id platform = platforms[j];
		cout << "\nplatform:" << platform_names[j] << endl;

		// 6. 遍历查询GPU、CPU、ACCELERATOR设备的数量
		for (cl_int i = 0; i < (sizeof(devices) / sizeof(devices[0])); i++)
		{
			err = clGetDeviceIDs(platform, devices[i].type, 0, 0, &devices[i].count);
			if (err == CL_DEVICE_NOT_FOUND) {
				devices[i].count = 0;
				err = CL_SUCCESS;
			}
			CHECK_ERRORS(err);

			cout << "\tdevices:" << devices[i].name
				<< "\tcount:" << devices[i].count;

			if (devices[i].count != 0) {
				// 7. 遍历查询GPU、CPU、ACCELERATOR 所有设备的信息
				cl_device_id* device = new cl_device_id[devices[i].count];
				err = clGetDeviceIDs(platform, devices[i].type, devices[i].count, device, 0);

				cout << "\t\tdevice name:";
				for (cl_int k = 0; k < devices[i].count; k++)
				{
					// 8. 获取和打印各个设备的name
					size_t length = 0;
					cl_device_id each_device = device[k];
					err = clGetDeviceInfo(each_device, CL_DEVICE_NAME, 0, 0, &length);
					CHECK_ERRORS(err);

					char* value = new char[length];
					err = clGetDeviceInfo(each_device, CL_DEVICE_NAME, length, value, 0);
					CHECK_ERRORS(err);
					cout << value << " ";

					// 9. 获取和打印各个设备的version
					err = clGetDeviceInfo(each_device, CL_DEVICE_VERSION, 0, 0, &length);
					CHECK_ERRORS(err);

					char* version = new char[length];
					err = clGetDeviceInfo(each_device, CL_DEVICE_VERSION, length, version, 0);
					CHECK_ERRORS(err);
					cout << version << " ";

					delete[] value;
					delete[] version;
				}

				delete[] device;
			}
			cout << endl;
		}
	}

	delete[] platforms;

	return 0;
}

运行结果如下:
在这里插入图片描述


二、封装后的代码

C:\Program Files (x86)\Intel\oneAPI\compiler\2022.0.0\windows\lib\oclfpga\host\include\CL\cl.h 头文件中定义了很多设备信息类型,当我们需要获取很多信息的时候,就需要写很多调用 clGetDeviceInfo() 函数的代码,其实这些代码都是可以折叠在一起的,我们用宏控来对它进行封装下:

#include <cstdlib>
#include <iostream>
#include <iomanip>
#include <cstring>
#include <cassert>

#include <CL/cl.h>

using namespace std;

static int call_nums = 0;

// 检查返回值错误
#define CHECK_ERRORS(ERR) \
	if(ERR != CL_SUCCESS){ \
		cerr << "OpenCL error code" << ERR << "file: " << __FILE__  << "line: " << __LINE__ << ".\nExiting..." << endl; \
		exit(1); \
	}

// 获取设备数量信息
#define GET_DEVICE_NUM_INFO(DEV_ID, DEV_INFO, TYPE)							\
	{																		\
		cout << " +     |------------";													\
		TYPE value; \
		size_t length = 0;													\
		err = clGetDeviceInfo(DEV_ID, DEV_INFO, sizeof(value), &value, &length);		\
		CHECK_ERRORS(err);													\
		cout << "[" << call_nums++ << "]: " << #DEV_INFO  <<  ": " << value <<endl;						\
	}

// 获取设备文本信息
#define GET_DEVICE_TEXT_INFO(DEV_ID, DEV_INFO)					\
	{															\
		cout << " +     |------------";										\
		size_t length = 0;											\
		err = clGetDeviceInfo(DEV_ID, DEV_INFO, 0, 0, &length);		\
		CHECK_ERRORS(err);											\
		char* value = new char[length];								\
		err = clGetDeviceInfo(DEV_ID, DEV_INFO, length, value, 0);	\
		CHECK_ERRORS(err);											\
		cout << "[" << call_nums++ << "]: " #DEV_INFO  <<  ": " << value <<endl;				\
		delete[] value;												\
	}

int main(int argc, const char** argv)
{
	cl_int err = CL_SUCCESS;

	// 1. 获取当前设备所有支持OpenCL的平台的数量
	cl_uint num_of_platforms = 0;
	err = clGetPlatformIDs(0, 0, &num_of_platforms);
	CHECK_ERRORS(err);

	// 2. 获取当前设备所有支持OpenCL的平台的信息
	cl_platform_id* platforms = new cl_platform_id[num_of_platforms];
	err = clGetPlatformIDs(num_of_platforms, platforms, 0);
	CHECK_ERRORS(err);

	cl_char platform_names[10][50];
	// 3. 打印平台信息
	cout << "平台信息:\n";
	for (cl_uint i = 0; i < num_of_platforms; i++)
	{
		// 获取平台字符串的长度
		size_t platform_name_length = 0;
		err = clGetPlatformInfo(platforms[i], CL_PLATFORM_NAME, 0, 0, &platform_name_length);
		CHECK_ERRORS(err);

		// 获取平台字符串
		char* platform_name = new char[platform_name_length];
		err = clGetPlatformInfo(platforms[i], CL_PLATFORM_NAME, platform_name_length, platform_name, 0);
		CHECK_ERRORS(err);

		cout << "    [" << i << "] " << platform_name << endl;

		// 备份platform name
		if (i < 10) {
			memset(platform_names[i], 0, 50);
			memcpy(platform_names[i], platform_name, platform_name_length);
		}
		delete[] platform_name;
	}

	// 4. 查询各平台设备数量
	struct {
		cl_device_type type;
		const  char* name;
		cl_uint count;
	}devices[] = {
		{CL_DEVICE_TYPE_GPU, "CL_DEVICE_TYPE_GPU", 0},					// GPU
		{CL_DEVICE_TYPE_CPU, "CL_DEVICE_TYPE_CPU", 0},					// CPU
		{CL_DEVICE_TYPE_ACCELERATOR, "CL_DEVICE_TYPE_ACCELERATOR", 0}	// 加速器
	};

	// 5. 遍历查询各个平台下拥有的设备数量
	for (cl_int j = 0; j < num_of_platforms; j++) {
		cl_platform_id platform = platforms[j];
		cout << "\n " << j << ": platform:" << platform_names[j] << endl;

		// 6. 遍历查询GPU、CPU、ACCELERATOR设备的数量
		for (cl_int i = 0; i < (sizeof(devices) / sizeof(devices[0])); i++)
		{
			err = clGetDeviceIDs(platform, devices[i].type, 0, 0, &devices[i].count);
			if (err == CL_DEVICE_NOT_FOUND) {
				devices[i].count = 0;
				err = CL_SUCCESS;
			}
			CHECK_ERRORS(err);

			cout << " +----(" << i << "): devices:" << devices[i].name
				<< "\tcount:" << devices[i].count << endl;

			if (devices[i].count != 0) {
				// 7. 遍历查询GPU、CPU、ACCELERATOR 所有设备的信息
				cl_device_id* device = new cl_device_id[devices[i].count];
				err = clGetDeviceIDs(platform, devices[i].type, devices[i].count, device, 0);

				for (cl_int k = 0; k < devices[i].count; k++)
				{
					// 8. 获取和打印各个设备的name
					size_t length = 0;
					cl_device_id each_device = device[k];
					call_nums = 0;

					GET_DEVICE_TEXT_INFO(each_device, CL_DEVICE_NAME);
					GET_DEVICE_TEXT_INFO(each_device, CL_DEVICE_VENDOR);
					GET_DEVICE_TEXT_INFO(each_device, CL_DRIVER_VERSION);
					GET_DEVICE_TEXT_INFO(each_device, CL_DEVICE_VERSION);

					GET_DEVICE_NUM_INFO(each_device, CL_DEVICE_MAX_COMPUTE_UNITS, cl_uint);
					GET_DEVICE_NUM_INFO(each_device, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, cl_uint);
					GET_DEVICE_NUM_INFO(each_device, CL_DEVICE_MAX_CLOCK_FREQUENCY, cl_uint);
					GET_DEVICE_NUM_INFO(each_device, CL_DEVICE_IMAGE_SUPPORT, cl_uint);
					GET_DEVICE_NUM_INFO(each_device, CL_DEVICE_AVAILABLE, cl_uint);
				}

				call_nums = 0;
				delete[] device;
			}
			cout << " +" << endl;
		}
	}

	delete[] platforms;
	return 0;
}

运行结果如下:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

"小夜猫&小懒虫&小财迷"的男人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值