对opencl简单理解和缓冲区以及相关操作的简单理解(完结)

来源:互联网 发布:阿里云设置伪静态 编辑:程序博客网 时间:2024/06/05 00:08

一.总体概括

计算机涉及的计算量越来越大,cpu明显已经不能再满足如此强大的计算需求.于是,另一些硬件出现了-GPU,DSP等.该怎么让这些硬件参与到日常的计算中来,这是个问题,为了解决这个问题,就有了OpenCL.

(百度百科有云:OpenCL是一个为异构平台编写程序的框架,此异构平台可由CPU,GPU或其他类型的处理器组成)

为了进一步理解这个异构系统编程框架,我们可以从以下四方面来分析理解

  • 异构系统抽象构成
  • 指令流
  • 数据流
  • 如何具体的编程实现

二.异构系统抽象构成 - opencl的平台的概念

这里写图片描述
一个主机+(一个或多个的)opencl设备
主机可以简单粗暴的理解为cpu,哼╭(╯^╰)╮;
opencl设备,就是需要整合的各种处理器(cpu,gpu,dsp或者其他).
在这里,你就简单粗暴理解为GPU就好咯.理解万岁!

三.指令流

这里写图片描述
opencl的指令流由两大部分构成:1.主机端2.opecncl设备端.
主机上的程序负责管理调度,opencl设备上的程序负责计算.(换做Kernel)
具体需要完成如下几步:

查询连接主机上的OpenCL设备;
在关联的设备上创建可执行程序;
从程序池中选择kernel程序;
从主机或设备上创建存储单元;
如果需要将主机的数据复制到OpenCL设备上的存储单元上;
执行kernel程序执行;
从OpenCL设备上复制结果到主机上。

四. 数据流

这里要说的是数据流,数据流主要指的是,实现数据在”内存-cpu-gpu”三者内的交互流.
主要分为:
- cpu与内存
- 内存与GPU
如上图所示,所谓的缓冲区buffer,子缓冲区subbuffer或者图像image,这些就是”内存-cpu-gpu”交互之间需要的一些抽象概念.

正常来说,会有三步(以buffer为例):

  1. 创建缓冲区;
  2. 将缓冲区和cpu进行链接,然后读写数据操作
  3. 将缓冲区和gpu进行链接,然后进行读写操作.

这样,数据构成一个完整回路.

1.opencl的创建缓冲区

代码如下:↓

cl_memclCreateBuffer  (     cl_context context,//该缓冲区所属的上下文    cl_mem_flags flags,    size_t size,//缓冲区的大小    void *host_ptr,    cl_int *errcode_ret//错误码)

其中红色标注出:contex,size与errcode部分很好理解
现在还剩下两部分, flags 与 host_ptr ,这两部分需要配合使用,详解如下:

1.1 flags 和 host_ptr

CL_MEM_USE_HOST_PTR 需要配合void *host_ptr一起服用!!!

主机内存上创建缓冲区的同时拷贝数据;
主机和设备端都可使用.但是可能需要数据同步处理.
流程图如下图所示:
主机分配的内存host_ptr(buffer created by malloc())在左下↙;
使用CL_MEM_USE_HOST_PTR标志调用clCreateBuffer()生成的buffer在右下↘;
这里写图片描述

CL_MEM_COPY_HOST_PTR 需要配合void *host_ptr一起服用!!!

与上面相似,不同点在于,CL_MEM_COPY_HOST_PTR是在设备上创建缓冲区.
设备上创建缓冲区的同时拷贝主机内存host_ptr上的数据;

CL_MEM_ALLOC_HOST_PTR void *host_ptr必须为Null!!!

主机内存上创建缓冲区;
主机和设备端都可使用.
这里写图片描述

1.2 其他flag

/ host device 读 CL_MEM_HOST_READ_ONLY CL_MEM_READ 写 CL_MEM_HOST_WRITE_ONLY CL_MEM_WRITE 读&写 / CL_MEM_READ_WRITE 不读&不写 CL_MEM_HOST_NO_ACCESS /

2. 主机(cpu)和buffer连接

操作 函数 读 clEnqueueReadBuffer 写 clEnqueueWriteBuffer 映射 clEnqueueMapBuffer

3. buffer和设备(GPU)链接

clSetKernelArg 之一和kernel参数一一对应,其他还是很简单的

0.如果让自己设计Opencl代码模式(这部分可以直接跳过,我来发牢骚的):

1.创建缓冲区需要做到以下三部分
- 指定该缓冲区所属的上下文
- 指定缓冲区的大小
- 错误码

cl_memclCreateBuffer  (     cl_context context,//该缓冲区所属的上下文    size_t size,//缓冲区的大小    cl_int *errcode_ret//错误码)

2.将缓冲区和gpu进行链接,设置各种模式:
剩下的内容,比如:该缓冲区和内核交互的限制会写到3这部分

3将缓冲区和gpu进行链接,然后进行读写操作.

3.将缓冲区和cpu进行链接,设置各种模式:
该缓冲区和cpu交互的限制会写到2这部分

2将缓冲区和cpu进行链接,然后读写数据操作

但是,opencl提供的创建缓冲区的函数,将2.3.的限制都糅合在了一起.Fuck!
从某种意义上以下两段代码实现功能是一样的:

cl_memclCreateBuffer(c,CL_MEM_USE_HOST_PTR,size,array,errcode);
buffer=cl_memclCreateBuffer(c,CL_MEM_USE_HOST_PTR,size,array,errcode);clEnqueueWriteBuffer(q,buffer,X,X,size,array,X,X,X);

但是你把两部分的功能糅合在一起不觉得太乱了吗
这里写图片描述
还有这个flag位,host,device乱七八糟的都放在一个位上,也是可以的….

/ host device 读 CL_MEM_HOST_READ_ONLY CL_MEM_READ 写 CL_MEM_HOST_WRITE_ONLY CL_MEM_WRITE 读&写 / CL_MEM_READ_WRITE 不读&不写 CL_MEM_HOST_NO_ACCESS /

其实还好,程序员嘛,啥样的都见过,也不差这一个……

啊,大概两年后我终于把牢骚发了出来.
浑身舒爽!
耶!
这里写图片描述

原创粉丝点击