OpenCL-3-同步机制

因为OpenCL在异构系统上进行计算,须要管理并调度多个设备,就须要在设备之间内部或外部进行数据交互以及同步。
<!-- more -->程序员

1.同步类型

  根据同步的类型,同步分为两部分:宿主机端同步和设备端同步。安全

2.设备端同步

  设备端同步主要指同一个内核内不一样线程以前的同步,主要用于保证数据的一致性。根据工做组的划分,能够细分为组内同步和全局同步。网络

2.1组内同步

  OpenCL采用宽松的同步模型和内存一致性模型。一般来讲,采用硬件实现可以最好的实现同步,可是做为一个跨平台的API,并不能彻底实现这些特性。因此OpenCL的解决方案是让程序员明确的知道当前系统的状态,添加同步点,从而能够依据这些信息获取预期行为。异步

  在x86(CPU)平台上,咱们使用同步机制若是条件还未知足,咱们可使系统进入休眠等待条件知足。可是GPU上的线程与系统层级的线程不是一个概念,GPU的线程所占用的资源是固定的,不能释放的,这也就致使了若是不一样的不一样work group不能为同一个资源作同步,由于没有释放的概念,因此必然存在死锁的状态。因此只能组内同步。函数

  组内同步的机制是barrier,即屏障,在组内全部的item没有到达这个barrier以前,全部的item是不想下执行的。ui

item1
    |       item2
    |         |       item3
    |         |         |
    | 5s      |4s       | 3s
    |         |         |
------------------------------ 全部达到 barrier以后,同时出发
    |         |         |
    |         |         |

2.2全局同步

  目前OpenCL不支持与组内同步相似的全局同步方式(缘由上方已经介绍)。能够经过global fence以及原子操做来达到目的。spa

3.宿主机端同步

  OpenCL是基于任务并行,主机控制的模型,其中每一项任务都是数据并行的,具体经过使用和设备关联的线程安全的命令队列来实现。固然,内核、数据以及其余操做并非简单调用来进行的,而是经过异步加入指定的队列中。线程

  从宿主机角度来看,保证宿主机同步的要点有一下三条:code

  • 调用clFinish函数,该函数将阻塞直至命令队列中的全部命令都执行完毕。
  • 等待一个特定事件的完成
  • 执行一个阻塞操做

固然,根据所须要同步的计算设备的个数,能够分为单设备同步多设备同步队列

3.1单设备同步

3.1.1设置barrier

clFinish能够阻塞程序的执行直到命令队列中的全部命令都执行完成。可是这只是至关于在末尾加上了一个barrier。在中间加入barrier须要调用以下函数:

cl_int clEnqueueBarrier(
  cl_command_queue command_queue
  )

3.1.2等待事件

  等待事件,即将一个等待事件加入命令队列,只有这个等待事件知足之后,才能执行以后加入的命令,使用的命令以下:

cl_int clEnqueueWaitForEvents(
  cl_command_queue command_queue,
  cl_uint num_events,
  const cl_event* event_list
  )

从变量定义上很好理解,再也不赘述。

3.1.3阻塞访问

  咱们在进行网络访问或者进行IO读取的时候是如何进行阻塞与非阻塞的区分的呢,没错,每每是传入一个标志。对于OpenCL也是同样的,如:

clEnqueReadBuffer(que, CL_TRUEm....)

上面这个示例的第二个参数就是指定这个函数是不是同步操做,若是为TRUE,那么就会阻塞直至拷贝完成,若是为FALSE,在设置完后不等拷贝完成,就会返回。

3.2多设备同步

  在以前咱们已经了解到,使用事件只能在同一个上下文中实现同步。那么在不一样的设备不一样的上下文中如何实现同步呢,只剩下了一种方法,cFinish,等待另外一个命令队列执行完成,以后的命令才能继续执行。如一个CPU一个GPU,二者须要互相访问彼此的数据,那么如何实现同步呢,若是CPU要访问CPU的数据,必须等待CPU当前的命令队列执行完成,再也不占用内存,GPU才能进行访问。
这里写图片描述

版权声明:本文为博主原创文章,转载需声明为转载内容并添加原文地址。

原文地址:http://coderdock.com

相关文章
相关标签/搜索