《OpenCL实战》阅读笔记(1)

项目需要接触到opencl语言,日前购买了参考书《OpenCL实战》(Matthew Scarpino著 陈睿译),之后会详细阅读该书并对关键知识做出整理。

OpenCL编程基础

OpenCL简介

目前,GPU运算蓬勃发展,工程师和科研人员都得出了统一的结论,CPU/GPU系统昭示着未来超级计算发展的方向。
语言之间的对比

  • 传统C或C++编译目标为CPU
  • CUDA只能针对Nvidia的GPU,而非CPU
  • OpenCL不仅可以在AMD、Nvidia、Intel的CPU或GPU上运行,甚至可以在Sony的PS3上运行
  • OpenCL支持quartus的高层次综合,可以被编译器转化为硬件描述语言(Verilog,VHDL),这也是我阅读此书的目的

本书的目标为展示如何编写跨平台架构的应用程序,以及最大可能利用硬件资源。
OpenCL并不是一门独立的语言,而是建立在C和C++基础上的一套标准,扩展定义了一些数据类型,数据结构以及函数。开发人员已经针对Java和Python设计了一系列的接口库,但标准中只支持C和C++编写的API。
OpenCL的三个特点

  • 可移植性——可以在多种设备上运行,切换设备只需要重新编译
  • 标准化的向量处理——可处理向量运算
  • 并行编程——多个处理单元同时执行任务
    在这里插入图片描述
    在OpenCL中,不同的运算任务被称为内核(kernel),主机可以选择将内核程序发送到不同的设备中执行。主机应用程序通过上下文来管理所连接的设备,主机从一个名为程序(program)的内核容器中选择函数,才能创建出内核程序。

主机编程:基本的数据结构

OpenCL的数据类型同C/C++类似。
在这里插入图片描述

获取平台信息(Platform)

OpenCL开发者并不需要深入了解底层设备信息,只需通过函数cl_platform_id即可应对

cl_int clGetPlatformIDs(cl_unit num_entries, cl_platform_id *platforms, cl_unit *num_platforms)

函数的实际作用为将cl_platform_id放入platforms指向的内存空间中,将可用平台数作为num_platforms保存。函数返回一个整数值,当返回0时表示平台检测成功。

上述函数并不能获取平台信息,但clGetPlatformInfo可以。

cl_int clGetPlatformInfo(cl_platform_id platform, 
	cl_platform_info param_name, size_t param_value_size,
	void *param_value, size_t *param_value_size_ret)

变量param_name为枚举类型,其中包含了我们需要的各种信息。
在这里插入图片描述

访问安装设备(device)

在向设备发送内核之前,我们需要创建一个cl_device_id结构来表示某个设备。clGetDeviceIDs会将OpenCL设备所对应的结构保存在cl_device_id中。

cl_int clGetDeviceIDs(cl_platform_id platform,
	cl_device_type device_type, cl_unit num_entries,
	cl_device_id *devices, cl_unit *num_devices)

第一个参数为感兴趣的平台,第二个参数表示的是设备类型,取值如下所示。
在这里插入图片描述
同样的,可以使用clGetDeviceInfo来获取设备信息。

cl_int clGetDeviceInfo(cl_device_id device, 
	cl_device_info param_name, size_t param_value_size,
	void *param_value, size_t *param_value_size_ret)

下图为cl_device_info返回的中多次参数中的七个。
在这里插入图片描述

通过上下文管理设备(context)

OpenCL中,上下文标记了一部分设备,而非平台上的所有设备,只有选中的设备可以一起工作。上下文是命令队列创建的基础,命令队列是主机和设备间通信的纽带。
在这里插入图片描述
可以通过下述两个函数创建上下文。

cl_context clCreateContext(const cl_context_properties *properties,
	cl_unit num_devices, const cl_device_id *devices,
	(void CL_CALLBACK *notify_func)(...),
	void *user_data, cl_int *error)

cl_context clCreateContextFromType(
	const cl_context_properties *properties,
	cl_device_type device_type,
	(void CL_CALLBACK *notify_func)(...),
	void *user_data, cl_int *error)	
)

两个函数的区别为,前者直接确定设备,后者只给定了设备类型,使用后者的好处为创建上下文的过程中并不需要访问平台或设备。
获取上下文信息与之前函数十分类似。

cl_int clGetContextInfo(cl_context context, 
	cl_context_info param_name, size_t param_value_size,
	void *param_value, size_t *param_value_size_ret)

param_name必须设定为cl_context_info枚举类型中的一个。下表为其可选取值:
在这里插入图片描述

将设备代码保存在程序中(program)

内核和程序都保存可执行代码,但内核表示的只是设备上执行的某个函数,而程序则是由一对内核所构成的。在OpenCL中,一般程序由cl_program构成。可以通过函数clCreateProgramWithSource和函数clCreateProgramWithBinary创建程序。创建程序前,需要将内核代码以文本格式保存在缓存数组中。
在这里插入图片描述
程序编译函数为:

clBuildProgram(cl_program program, cl_uint num_devices,
	const cl_device_id *devices, const char *options,
	(void CL_CALLBACK *notify_func)(...), void *user_data)

第四个选项为编译器的编译选项,程序编译选项如下图所示:
在这里插入图片描述
可以通过调用函数clGetProgramInfo和函数clGetProgramBuildInfo来访问相关信息。第一个函数提供了和程序相关的数据结构的信息,例如程序的上下文和目标设备。第二个函数提供的是程序的编译信息。

clGetProgramInfo(cl_program program, cl_program_info param_name,
	size_t param_value_size, void *param_value,
	size_t *param_value_size_ret)

在这里插入图片描述
另外,函数clGetProgramBuildInfo十分重要,他是了解程序构建过程的唯一方法。

clGetProgramBuildInfo(cl_program program, cl_device_id device,
	cl_program_build_info param_name,
	size_t param_value_size, void *param_value,
	size_t *param_value_size_ret)

cl_program_build_info也是一个枚举类型,其中包含了程序构建的信息。

将函数打包为内核(kernel)

在程序编译和链接结束之后,需要将函数打包为名为内核的数据结构,内核是可以部署的,并能发送到命令队列中,再发送到设备上,内核结构用cl_kernel来表示。
OpenCL可以用cl_program结构来创建cl_kernel结构。函数签名如下

clCreateKernelsInProgram(cl_program program, cl_unit num_kernels, 
	cl_kernel *kernels, cl_unit *num_kernels_ret)

获取内核信息函数如下:

clGetKernelInfo(cl_kernel kernel, cl_kernel_info param_name,
	size_t param_value_size, void *param_value,
	size_t *param_value_size_ret)

用命令队列保存内核(queue)

主机和设备间通过命令队列来通信,命令队列为内核执行的顺序。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值