课程链接: https://www.bilibili.com/video/BV1zC4y1s7Ax/?spm_id_from=333.337.search-card.all.click&vd_source=23174149881549c431809ba9bd3acade
OpenCL简介
OpenCL计算架构
多平台支持
环境配置
参考:
[1] https://blog.csdn.net/Ciellee/article/details/122379217
也可以使用vcpkg进行opencl环境安装,vcpkg是c++的包管理器,可以方便安装管理c++第三方库
vcpkg install opencv:x64-windows
输出本地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);
cout << "Platform info: \n";
// 3. 打印平台信息
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;
}
return 0;
}
这是我的PC输出的结果:
Platform info:
[0] NVIDIA CUDA
[1] Intel(R) OpenCL HD Graphics
第2章 主机编程:基本的数据结构
2.1 基本数据类型
- OpenCL是跨平台的工具包,因而需要一系列同意的基本数据类型作为支撑。
- 数据类型的声明在 CL/cl_platform.h 中,这些数据只是对c/c++数据类型的再定义而已。
2.2 获取平台信息
应用场景举例:
- 有多个可用的设备,需要指定计算的设备
- 发布程序时,根据用户的硬件平台,指定设备。
- 通过 cl_platform_id来对应上述两种情况
2.2.1 创建平台结构
每个 cl_platform_id 对应的是安装在主机上一种不同的OpenCL的具体实现(平台)。
编写平台程序分为两步:
- 为一个或多个 cl_platform_id 结构分配内存空间
- 调用 clGetPlatformID来初始化这些数据结构,其函数签名如下:
clGetPlatformIDs(
cl_uint num_entries,
cl_platform_id * platforms,
cl_uint * num_platforms);
关于这个函数需要注意三点:
- 这个函数并不会返回 cl_platform_id, 当成功时返回 0, 返回负数表示检测失败
- 函数的实际作用是将cl_platform_id 放到platforms指向的内存空间中
- 把可用的平台数用 num_platforms 保存起来, 反应了平台可用的上限数
- num_entries 表示想要检测平台的上限数
- platforms 对象内存地址
使用场景
// 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);
这里调用了两次 clGetPlatformIDs
- 第一次调用获取到了支持的平台数 num_of_platforms
- 第二次调用获取到了平台的内存地址,类似handle
2.2.2 获取平台信息
api:
clGetPlatformInfo(cl_platform_id platform,
cl_platform_info param_name,
size_t param_value_size,
void * param_value,
size_t * param_value_size_ret)
- platform 设备内存地址
- param_name 平台信息相关参数
2.3 访问安装设备
在访问完厂商的平台之后,便可以访问平台相连的各个设备。设备复杂接受来自主机分发的任务和数据。程序中的设备用 cl_device_id 结构来表示。这一节中着重考察两个OpenCL的设备函数。
- clGetDeviceIDS
- clGetDeviceInfo
2.3.1 创建设备结构
在向设备发送 kernel 之前,我们需要创建一个 cl_device_id 结构来表示某个设备。可以通过
clGetDeviceIDs 实现。它会将 OpenCL设备所对应的结构保存在 cl_device_id型数组中,其函数签名如下: