• 笔记第1篇-OpenCL基础


    注:本笔记基于互联网上各个博文整合,如有侵权请及时告知。文末有参考博文的链接。

    CPU,GPU的架构简介

    CPU:多指令单数据流(流水线模式),MISD,擅长逻辑控制。

    GPU:单指令多数据流(向量算法),SIMD,擅长并行计算。

    所以1个CPU+几个GPGPU(通用并行处理的GPU)的架构即异构编程。

    使用通用的OpenCL接口(API)开发的应用可以在不同的SDK中通用,OPenCL只是一个标准,Intel,AMD,NVIDIA等各大厂商采用不同的SDK进行自定制的开发;

    OpenCL硬件层的抽象

    它是一个Host(控制处置单元,常通由一个CPU担负)和一堆Compute Device(计算设备,由一些GPU、CPU其他支撑的芯片担负),其中Compute Device切分为很多Processing Element(这是独立介入单数据计算的最小单元,这个不同硬件实现都不一样,如GPU可能就是其中一个Processor,而CPU多是一个Core,我猜的。。因为这个实现对开发者是隐藏的),其中很多个Processing Element可以构成组为一个Compute Unit,一个Unit内的element之间可以便利的同享memory,也只有一个Unit内的element可以实现同步等操作。

    可以理解为:

    Host是公司的总经理:负责对公司的整体任务分配与调度。

    Compute Device是公司总经理管理的若干个实施部门:各个这样的部门负责把总经理分配的任务并行地完成。但是,各部门执行同样的运算任务。

    Compute Unit是各部门下面的各个项目组,负责把任务在技术层面上实现。各个项目组的技术细节不对外公开(项目组内共享Local Memory)。

    Processing element是员工,负责项目组内任务的实施,是最底层的工作节点。员工有自己私有的技术(Private Memory)。整个公司内,每个Processing Element有自己的索引号(Global ID),工号。在每个项目组(Workgroup)内,有自己项目组内的编号,就是LocalID。下图从Compute Device进行划分。

    如上图,有全局内存(变量),全局常量,本地内存以及局部变量。

    OpenCL的软件层架构:

    Setup相关知识(系统的初始化):

    -Device:对应一个计算设备;注意,多核的CPU是一个整个的Device。即Device是单个CPU或GPU或FPGA。

    -Context:上下文;一个Context包括几个Device,Context是这些Device的联系纽带,只有在同一个Context里的Device才能彼此交流任务。你的单板上可以有很多Context。Context可以由CPU或CPU+GPU创建。

    -Command queue:给每个Device提交的指令序列。

    内存相关知识:

           -Buffer:内存

           -Images:原生的用于GPU运算的图像处理的“类型”,表示各种维度的图像。

           -数据交互的方式:A 将地址拷贝到工作组空间,计算完成再拷贝出去(传形参);B 将计算数据组的地址传输进去(传指针)。

    GPU代码执行相关知识:

           -Program:包括Kernel和其他库等。OpenCL是动态编译的语言,源代码编译后生成一个相同的中间文件,该中间文件连接不同的linker时生成不同的程序。然后将程序读入Compute Device。

           -kernel:在processing element(PE,员工)处跑的内核程序,是最基本的处理事情。各个PE的内核(算法)相同而处理的数据不同,这就是所谓的单指令多数据体系(SIMD)。

           -Work item:processing element在代码里的表示,一个Work Item代表一个processing element(PE,员工)。

           -程序对象:内核程序的源代码文件(.cl文件)和可执行文件。内存对象:计算设备执行OpenCL内核程序所需的变量。

    并行与同步相关的知识:

           -任务并行与数据并行:任务并行是指流水线的工作模式。数据并行是指多组数据同时进行相同计算的方式(所有的矩阵操作基本都可以用!)

           -Command queue命令队列:每个计算设备Compute Device都有一个或多个命令队列。但一个命令队列只管理一个计算设备。通过命令队列,可以实现宿主机和计算设备的异步控制。分为启动命令(开始执行kernel程序);内存命令(在host和内存设备之间移动数据,或进行内存映射);同步命令(约束命令在计算设备的执行情况)。

           -Events(事件):命令队列中每条命令都有着命令的状态,当命令的状态发生变化,就产生了事件Event。在分布式计算的环境中,Events用于不同计算单元之间的同步。

    -按事件发生位置来分:内核端事件:主要负责异步执行命令的同步操作(多个处理单元的阶段同步)和全局内核和本地内存的同步。主机端事件:完成命令队列之间的同步操作(统筹各个计算设备的操作)。

    -按事件发生原因来分:

    命令事件

    CL_QUEUED:命令已经加入命令队列。

    CL_SUBMITTED:命令已经有宿主机提交给与所在命令队列相关联的设备。

    CL_RUNNING:该命令正在执行。

    CL_COMPLETE:命令已经完成

    ERROR_CORE:负数,指代不同的错误情况。

    用户自定义事件

    需要进行同一上下文内的各ConputeDevice之间同步时,用用户自定义事件。

    cl_event clCreateUserEvent(

    cl_context context, //指定上下文

    cl_uint* errcode_ret //该函数所关联的错误值

    )

    如果创建成功,errcode_ret会被赋值为CL_SUCCESS或者错误时,赋值为以下的值:

    CL_INVALID_EVENT:上下文不合法

    CL_OUT_OF_RESOURCE: 资源未就绪或分配资源失败

    CL_OUT_OF_HOST_MEMORY:宿主机资源未就绪或分配资源失败

    之后我们就可以在各个处理函数中设置返回的事件的值:

    cl_intclSetUserEventStatus(

    cl_eventevent, //具体事件值

    cl_intexecution_status //指向状态

    )

    -同步:

    OpenCL是基于任务并行,主机控制的模型,其中每一项任务都是数据并行的,具体通过使用和设备关联的线程安全的命令队列来实现。

    -单设备同步:通过以下设置:

    A设置barrier(即屏障,在组内所有的item没有到达这个barrier之前,所有的item是不向下执行的)。

    cl_int clEnqueueBarrier(

    cl_command_queuecommand_queue

    )

    B等待事件(等待事件,即将一个等待事件加入命令队列,只有这个等待事件满足以后,才能执行之后加入的命令)。

    C阻塞访问:在内存IO读取时设置一个标志,当标志有效时,会阻塞直到拷贝完成。

    -多设备同步:cFinish,等待另一个命令队列执行完成,之后的命令才能继续执行。如一个CPU一个GPU,两者需要互相访问彼此的数据,那么如何实现同步呢,如果CPU要访问CPU的数据,必须等待CPU当前的命令队列执行完成,不再占用内存,GPU才能进行访问。clFinish可以阻塞程序的执行直到命令队列中的所有命令都执行完成。但是这只是相当于在末尾加上了一个barrier。



  • 相关阅读:
    Azure PowerShell (2) 修改Azure订阅名称
    Windows Azure Platform Introduction (11) 了解Org ID、Windows Azure订阅、账户
    Azure PowerShell (3) 上传证书
    Azure PowerShell (1) PowerShell入门
    Windows Azure Service Bus (2) 队列(Queue)入门
    Windows Azure Service Bus (1) 基础
    Windows Azure Cloud Service (10) Role的生命周期
    Windows Azure Cloud Service (36) 在Azure Cloud Service配置SSL证书
    Android studio 使用心得(一)—android studio快速掌握快捷键
    android 签名、混淆打包
  • 原文地址:https://www.cnblogs.com/charleechan/p/12500563.html
Copyright © 2020-2023  润新知