本系列文章汇总:
本章只是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;
}
运行结果如下: