OpenCL 学习(4)---- OpenCL 上下文和程序对象

目录

创建上下文

OpenCL 上下文创建:

查询支持的设备和平台信息,然后根据这些信息创建相应的 OpenCL 上下文对象

之后所有的 OpenCL 操作都是以该上下文对象(context)作为标识,相当于后续的并行计算也是在该设备上执行,

在实际的硬件产品中,PC 上的设备通常是一些显卡(Nvdia 独立显卡,或者 Intel 独立显卡),手机上是使用移动的 GPU (比如 ARMMALI)

c 复制代码
cl_context clCreateContext(
    const cl_context_properties *properties,  // 上下文创建属性
    cl_uint num_devices,                      // 运行的设备数量
    const cl_device_id *devices,              // 运行的 deviceId列表
    // 如果创建成功使用的回调函数
    void (CL_CALLBACK *pfn_notify)(const char *errinfo, const void *private_info, size_t cb,void *user_data), 
    void *user_data,                          // 回调函数使用的用户数据
    cl_int *errcode_ret);                     // 输出错误码
)

参数 properties 指定上下属性的属性名称及属性相应的值的列表,规定最后一个值为 0

如下表,当实现自定义选择平台时,参数 properties 可以设置为 NULL

cl_context_properties 属性值 描述
CL_CONTEXT_PLATFORM cl_platform_id 指定使用的平台
CL_CONTEXT_INETROP_USER_SYNC cl_bool 指定用户是否负责 OpenCL 和其他 API 之间的同步,如果没有指定,默认值为 CL_FALSE

参数 pfn_notifyuser_data 共同定义一个回调函数,这个回调函数报告上下文生命周期中出现的错误的有关信息,

要把 user_data 作为最后一个参数传递至回调函数,这两个参数都可以设置为 NULL
errcode_ret 是函数的返回状态值,成功为 CL_SUCCESS,否则值为对应的错误代码

创建程序对象

程序对象主要是用来加载、编译和处理 CL 代码的函数,这个处理流程跟 OpenGL 中处理 shader 语言代码几乎一样,

都是先将脚本语言加载、编译、链接,不同的是:
OpenCL 中的代码 GPU 的编程通常只在顶点着色器(VertexShader) 和片段着色器(FragementShader)中,

执行的时机依赖于渲染管线流程的顺序,不能直接通过 CPU 的代码控制Shader 的执行

OpenCL 的脚本代码在 GPU 中执行,可以通过命令队列来控制,并且可以使用事件进行同步,这一点是 OpenGL 所没有的

c 复制代码
cl_program clCreateProgramWithSource(
    cl_context context,                 // 输入OpenCL上下文对象
    cl_uint count,                      // 输入CL代码的数量,一般设置为 1
    const char **strings,               // 输入CL代码字符串数组 
    const size_t *lengths,              // 输入CL代码字符串数量  
    cl_int *errcode_ret)                // 输出错误码,如果成功返回0
c 复制代码
clCreateProgramWithBinary(
    cl_context                     /* context */,
    cl_uint                        /* num_devices */,
    const cl_device_id *           /* device_list */,
    const size_t *                 /* lengths */,
    const unsigned char **         /* binaries */,
    cl_int *                       /* binary_status */,
    cl_int *                       /* errcode_ret */)

这里的 CL 代码就是 GPU 中执行的内置的开发语言,一般将这部分代码作为一个完整的字符串,提供给 clCreateProgramWithSource 进行编译
CL 代码通常都是实现的一个个独立的函数,称为内核函数,经过编译、加载运行后,最终在 GPU 中执行

利用编译好程序二进制来创建程序对象,第五个参数传入 binaries 的内容,第四个参数为二进制内容大小

先使用对应的 OpenCL 编译工具(不同的平台会有不同的实现)将 CL 脚本代码编译成二进制数据,之后使用 clCreateProgramWithBinary来加载

c 复制代码
cl_program clCreateProgramWithBinary( cl_context         context,
                                    cl_uint            num_devices,
                                    const cl_device_id *device_list,
                                    const size_t       *lengths,
                                    cosnt unsigned char **binaries,
                                    cl_int             *binary_status,
                                    cl_int             *errcode_ret )
编译程序对象

clBuildProgram 为指定的所有设备构建程序对象,实际上等价于在一个C程序上调用编译器和链接器,

第四个参数就是设置编译器选项

c 复制代码
cl_int clBuildProgram(
        cl_program program,                  // 要编译的程序对象
        cl_uint num_devices,                 // 指定运行的设备Id数量
        const cl_device_id *device_list,     // 指定要运行的设备Id列表
        const char *options,                 // 编译参数字符串
        void (CL_CALLBACK *pfn_notify) (cl_program program,void *user_data), // 编译成功的回调函数,如果NULL表示同步等待
        void *user_data)                     // 回调函数用户数据

编译器的选项可以分为下面几种类型

  • 预处理选项
  • 数学选项
  • 优化选项
  • 其他选项

这几个选项的详细情况,如下表所示:

需要关注的主要就是 option 编译参数字串,通常这个参数设置跟 GCC 的编译选项非常类似,当然也有些 CL 语言本身的一些编译参数

比如 CL 程序中如果是下面的代码:

c 复制代码
#ifdef __USE_FLOAT__
    #define ELM_TYPE    float
#else
    #define ELM_TYPE    int
#endif

ELM_TYPE    data[10];

那么使用 clBuildProgram 编译 .cl 代码的时候,如果带上 options = "-D __USE_FLOAT__" 参数的时候,
.cl 代码会编译成 float data[10]否则就会编译成 int data[10]

clGetProgramBuildInfo 用于获取编译信息,通常用于获取编译传递的错误信息

c 复制代码
cl_int clGetProgramBuildInfo(
    cl_program program,                    // 程序对象
    cl_device_id device,                   // 编译的设备Id
    cl_program_build_info param_name,      // 通常用 CL_PROGRAM_BUILD_LOG,表示输出编译日志
    size_t param_value_size,               // 输出缓冲区大小
    void *param_value,                     // 输出缓冲区
    size_t *param_value_size_ret)          // 返回错误代码,成功返回0
查询和管理程序对象

TBD

相关推荐
xian_wwq2 小时前
【学习笔记】OAuth 2.0 安全攻防:从 Portswigger 六大实验看认证漏洞挖掘
笔记·学习·安全
babe小鑫2 小时前
大数据运维与管理专业学习数据分析的必要性
大数据·运维·学习
2501_901147832 小时前
粉刷房子问题:从DP基础到空间极致优化学习笔记
笔记·学习·动态规划
im_AMBER2 小时前
Leetcode 122 二叉树的最近公共祖先 | 二叉搜索树迭代器
学习·算法·leetcode·二叉树
CappuccinoRose2 小时前
CSS 语法学习文档(十一)
前端·css·学习·表单控件
随意起个昵称3 小时前
Dijstra算法学习笔记
笔记·学习·算法
星火开发设计4 小时前
C++ 异常处理:try-catch-throw 的基本用法
java·开发语言·jvm·c++·学习·知识·对象
知识分享小能手4 小时前
SQL Server 2019入门学习教程,从入门到精通,SQL Server 2019 事务和锁 — 语法知识点及使用方法详解(13)
数据库·学习·sqlserver
悠哉悠哉愿意5 小时前
【强化学习学习笔记】马尔科夫决策过程
笔记·学习·交互·强化学习