OpenCL 存储器次序规则

从根本上来说,一个关于存储器模型的问题就是理解对存储器中对象修改的时序。修改对象或通过函数调用来修改对象称为一个副作用,即改变了执行环境中的状态。通常对一个表达式的计算包括了值的计算以及副作用的引入。对于一个左值表达式的计算包括确定被赋值对象的同一性。本节的描述会比较学术化,如果读者对OpenCL标准本身不太感兴趣完全可以跳过,直接进入5.6.2节的内容。
我们假定OpenCL C内核编程语言以及主机端编程语言在由单个执行单元执行的某两个计算之间具有前后次序关系。该前后次序关系在那两个计算之间是一个非对称的、传递的(即离散数学中关于关系的对称性与传递性概念)、成对的关系,而且它们之间又是部分次序的。给定两个计算A和B,如果A的次序在B之前,那么对A的执行将先于对B的执行。当A的次序可能在B之前,也可能在B之后,那么A和B的计算在次序上是不确定的,而这在OpenCL标准中也未指定到底用哪种次序。
注意,前置次序(sequenced-before)是在单个执行单元(如一个主机端线程或一个工作项)中所执行的两个操作的部分次序。前置次序通常对应于那些操作的源程序次序,而之所以是部分次序,是因为OpenCL内核C语言中未定义实参计算次序。例如,在OpenCL C内核语言中调用foo(a+1,b+2,c+3);函数,参数计算次序是先执行a+1还是先执行c+3是未定义的,各家OpenCL平台实现厂商可以根据自己的需要来指定。
在OpenCL C内核编程语言中,在某一特定点,某个工作项W观察一个它可见的对象,那么W所看到的值可作为该对象的初始值,也可作为W在此对象中存储的值,或者作为另一个工作项或主机端线程在此对象中存储的值。这些根据以下规则来定。某些主机端编程语言的实现也会存在这种情况,对一个主机端线程可见的对象,它的值也可能是由另一个工作项或主机端线程对其所存储的值。
有两个表达式,如果其中一个修改了某个存储器位置的内容,而另一个同时对那个存储器位置进行读或写,那么这两个表达式就会存在冲突。
对某一特定的原子对象M的所有修改是以某个特定总和次序(见前面对memory_order_seq_cst的描述)发生的,称为对M的修改次序。如果A和B是对一个原子对象M的修改,并且A发生在B之前,那么A在对M的修改次序中将排在B之前。注意,对原子对象M的修改次序与M是在本地存储器还是在全局存储器无关。
一个释放次序产生于作用在原子对象M上的释放操作A。它作为在M的修改次序中所产生副作用的最大连续子序列。在这个子序列中,第一个操作是A,而后面每个操作要么由同一个工作项执行(或由执行释放操作的主机端线程执行),要么后面每个操作是原子的读-修改-写操作。
OpenCL的本地存储器与全局存储器是分离的。OpenCL内核程序对这两种存储器类型都可以访问,而主机端线程只能访问全局存储器。此外,OpenCL的work_group_barrier函数的flags参数指定了该函数将对哪些存储器可见。flags参数可设置为对本地存储器或全局存储器可见,也可设置为对二者都可见。由于可以设置存储器操作为本地存储器可见或全局存储器可见等,因此我们相应定义了本地同步和全局同步。在全局存储器上的某些操作可以全局同步于另一个工作项,或主机端线程所执行的其它操作。例如,在某一工作项上的“释放操作”,全局同步于另一个工作项上的“获得原子操作”。类似地,在内核程序中,某些本地存储器对象的原子操作可以本地同步于这些对象的其他原子操作。
我们定义了两个独立的前置次序的关系:全局前置次序以及局部前置次序。
一个全局存储器操作A全局发生在一个全局存储器操作B之前,如果:
1)A的次序在B之前;

2)A全局同步于B;

3)对于某个全局存储器操作C,A全局发生在C之前,并且C全局发生在B之前。这就是上面所提到的次序关系的传递性。
一个OpenCL实现应该确保不管在“本地前置次序”还是在“全局前置次序”关系中没有任何程序执行,哪怕是一个周期。
[插图]注意全局以及本地前置发生关系(order-befor)对于定义什么值被读以及数据竞争什么时候发生来说是很关键的。例如,全局前置次序关系定义了哪个全局存储器操作完全在其他全局存储器操作之前发生。如果一个操作A全局发生在操作B之前,那么A必须在B之前发生;特别是,A所写的任何内容将对B可见。本地前置发生关系对于本地存储器具有类似的特性。程序员可以使用本地存储器与全局存储器前置发生关系来思考设计程序行为的相关次序。
对全局对象M的一个可见副作用A,以及对M的一个值计算B(这里,M的值计算B对副作用A可见),同时满足以下条件:
1)A全局发生在B之前。
2)不存在其他对M的副作用X,使得A全局发生在X之前且X全局发生在B之前。也就是说,在副作用A与值计算操作B之间不存在其他对M的副作用。
我们类似地定义对本地对象M的对外可见的副作用。一个非原子的、要由计算B所确定的标量对象M的值,应该是由可见的副作用A所存储的值。
程序的执行包含了据竞争,如果它在两个不同的执行单元中包含了两个具有竞争性的行为A和B,并且满足:
1)A或B至少有一个不是原子的,或A和B不具有包含性的存储器作用域(例如,A操作的存储区域只对全局存储器可见,B操作的存储区域只对本地存储器可见;或者A操作和B操作的存储区域都是本地存储器,但是所操作的原子对象是在全局存储器中)。
2)A操作和B操作对于全局前后发生次序关系而言是无序的全局行为,或A和B操作对于本地前后发生次序关系而言是无序的本地行为。
任一这样的数据竞争都将导致未定义的行为。
我们也定义了本地原子对象与全局原子对象上副作用的可见次序。接下来将定义一个全局原子对象M的次序。本地原子对象上的副作用可见次序与使用本地前置发生关系所定义的类似。
作用在全局原子对象M上的副作用的可见序列,是在M的修改次序中所产生副作用的最大连续子序列。在此子序列中有对M的一次值计算B,而第一个副作用对B可见,并且每个副作用都全局发生在值计算B之前。B计算出来的M的值,应该是M可见序列中某个操作对M所存储的值。
如果对原子对象M进行修改的操作A,全局发生在对M修改的操作B之前,那么在M的修改次序中,A应该发生在B之前。这个要求称为写-写一致性。
如果对原子对象M的值计算A全局发生在对M的值计算B之前,并且A从对M的一个副作用X处取其值,那么由B计算出的值应该要么等于由X所存储的值,要么是对M的一个副作用Y所存储的值。这里,Y在对M的修改,在次序上发生在X之后。这个要求被称为读-读一致性。
如果对原子对象M的值计算A全局发生在对M的操作B之前,那么A将从对M的一个副作用X处取其值。这里X对M的修改在次序上应该在B之前。这个要求称为读-写一致性。
如果对原子对象M的一个副作用X全局发生在对M的值计算B之前,那么值计算B将从X处取其值,或从对M的修改次序中,在X之后的一个副作用Y处取其值。这个要求被称为写-读一致性。

赞(0)
未经允许不得转载:极客笔记 » OpenCL 存储器次序规则

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
OpenCL 基本概念
OpenCL 是什么OpenCL 平台模型OpenCL 执行模型OpenCL 上下文简介OpenCL 命令队列简介OpenCL 在设备上执行内核OpenCL 存储器区域OpenCL 存储器对象OpenCL 共享虚拟存储器OpenCL 与OpenGL
OpenCL 基础教程
OpenCL 在Windows上搭建开发环境OpenCL 在Linux上搭建开发环境OpenCL 在OS X上搭建开发环境OpenCL 第一个程序OpenCL 平台OpenCL 设备OpenCL 创建上下文OpenCL 创建命令队列OpenCL 创建Program对象OpenCL 编译Program对象OpenCL 查询和管理Program对象OpenCL 创建内核对象OpenCL 设置内核参数OpenCL 查询和管理内核对象OpenCL 执行内核OpenCL 编写内核代码OpenCL 错误处理
OpenCL C特性
OpenCL 地址空间修饰符OpenCL 函数修饰符OpenCL 对象访问修饰符OpenCL 标量数据类型OpenCL 为什么要有矢量数据类型OpenCL 矢量初始化OpenCL 读取和修改矢量分量OpenCL 运算符OpenCL 维度和工作项OpenCL 工作组OpenCL 矢量数据拷贝OpenCL 异步拷贝和预取OpenCL 数学函数OpenCL 公共函数OpenCL 几何函数OpenCL 整数函数OpenCL 关系函数OpenCL 杂项矢量函数OpenCL 同步函数OpenCL 原子函数OpenCL 内建图像读函数OpenCL 内建无采样器图像读函数OpenCL 内建图像写函数OpenCL 内建图像查询函数OpenCL 工作组函数OpenCL 内建管道读/写函数OpenCL 内建工作组管道读/写函数OpenCL 内建管道查询函数OpenCL 设备队列OpenCL Blocks语法OpenCL 设备队列相关函数OpenCL 子内核存储器可见性OpenCL 设备队列的使用示例
OpenCL 存储器对象
OpenCL 存储器对象OpenCL 分配缓冲区对象OpenCL 创建子缓冲区对象OpenCL 图像对象和采样器对象OpenCL 图像对象OpenCL 图像格式描述符OpenCL 图像描述符OpenCL 图像对象查询OpenCL 采样器对象OpenCL 主机端采样器对象OpenCL 设备端采样器对象OpenCL 图像旋转示例OpenCL 管道OpenCL 创建管道对象OpenCL 管道对象查询OpenCL 主机与设备间数据传输OpenCL 图像对象主机与设备间数据拷贝OpenCL 缓冲区对象数据填充OpenCL 图像对象数据填充OpenCL 缓冲区对象间数据传输OpenCL 图像对象和缓冲区对象间数据拷贝OpenCL 缓冲区对象映射OpenCL 图像对象映射OpenCL 解映射OpenCL 共享虚拟存储器OpenCL SVM缓冲创建与释放OpenCL SVM缓冲映射与解映射OpenCL SVM缓冲填充与拷贝OpenCL SVM类型OpenCL SVM特性OpenCL 共享虚拟存储器示例OpenCL 存储器一致性模型OpenCL 存储器次序规则OpenCL 原子操作的存储器次序规则OpenCL 栅栏操作的存储器次序规则OpenCL 工作组函数的存储器次序规则OpenCL 主机端与设备端命令的存储器次序规则OpenCL 关于存储器次序在实际OpenCL计算设备中的实现
OpenCL 同步及事件机制
OpenCL 同步及事件机制OpenCL 主机端的OpenCL同步OpenCL OpenCL事件机制OpenCL 对OpenCL事件的标记和栅栏OpenCL 内核程序中的同步OpenCL 工作组内同步OpenCL 原子操作OpenCL 1.2中的原子操作OpenCL 2.0中的原子操作OpenCL 局部存储器与全局存储器间的异步拷贝OpenCL 工作组间同步
OpenCL 与OpenGL互操作
OpenCL 与OpenGL互操作OpenCL 从一个OpenGL上下文来创建OpenCL上下文OpenCL 使用OpenGL共享的缓存对象OpenCL 使用OpenGL纹理数据OpenCL 共享OpenGL渲染缓存OpenCL 从一个OpenCL存储器对象查询OpenGL对象信息OpenCL 访问共享对象的OpenCL与OpenGL之间的同步OpenCL AMD Cayman架构GPUOpenCL AMD GCN架构的GPUOpenCL NVIDIA CUDA兼容的GPUOpenCL NVIDIA GPU架构的执行模型OpenCL NVIDIA GPU的全局存储器OpenCL NVIDIA GPU的局部存储器OpenCL ARM Mali GPU硬件架构OpenCL ARM Mali GPU存储器层次OpenCL ARM Mali GPU OpenCL映射