5.1 检索你的应用程序
检索你的应用程序,寻找计算最密集的部,这些是值得移植到OpenCL上的部分。
你可以使用DS-5来检索你的应用程序,从Mali开发者网站下载DS-5:http://www.malideveloper.arm.com
5.2 为并行化分析你的代码
该部分描述如何为并行化分析计算密集型代码,包含以下部分:
>为并行化分析代码
>查找数据并行操作
>查找具有较少依赖的操作
>分析循环语句
5.2.1 为并行化分析代码
当你确定应用程序中计算最密集的部分后,分析代码,看看能否并行运行。并行化的代码可以如下:
容易的 需要很少或不需要修改
直接的 需要较小修改
见
使用全局ID代替循环计数器
困难的 需要复杂的修改
见
在循环中使用公式计算值以代替使用计数器
困难的并且包含依赖 需要复杂的修改,并且使用特殊的技术避免依赖
见 以一帧为阶段计算值
执行带依赖的计算,以multple-passes的方式
预先计算值,以移除依赖
明显不可能 如果明显不可能并行化代码,研究代码所使用算法和数据结构的替代方案。它们可能是可以并行化的
见 对非并行化代码使用并行处理
不可能的 这只是意味着,实现无法被并行化。别认为代码是最终的解决方案。代码只是方案的一种可能实现。可能会有多个不同的方案,某些可能可以并行化。
见 对非并行化代码使用并行处理
5.2.2 查找数据并行运算
寻找做大量运算的任务:
>完全没有共享数据
>相互之间不依赖结果
这种类型的操作是数据并行的,对于OpenCL非常理想。
5.2.3 查找具有较少依赖的运算
如果代码具有较少的依赖,考虑:
> 有没有方法移除依赖?
> 可以把依赖的执行挪到后面?
5.2.4 分析循环
循环是并行化的好目标,因为它们重复计算很多次,经常是独立地。
处理较少数据元素的循环
可能不适合数据并行处理,可能适合一个或多个CPU上的任务并行处理。
最佳循环
> 处理几千个项
> 对以前的迭代没有依赖
> 每次迭代独立地访问数据
简单循环并行化
如果循环包含一个变量,它基于前一次迭代的值来加,这是一种迭代间的依赖,阻止了并行化。看能否使用公式,使得你能够根据主循环的计数器计算变量的值。
需要前一次迭代数据的循环
看能否重构循环以移除依赖,如果不行,就不可能并行化循环。有很多技术可以分开依赖。见并行处理技术。
非并行化循环
如果循环包含你无法移除的依赖,研究执行计算的替代方法。这些替代方法可能是可以并行化的。
5.3 并行处理技术
这一部分讲述你能在OpenCL中使用的并行处理技术,它包含以下几个部分:
> 使用全局ID替代循环计数器
> 在循环中使用计算公式代替计数器
> 以一帧为阶段计算值
> 执行带依赖的计算,以multple-passes的方式
> 预先计算值,以移除依赖
> 使用软件流水线
> 使用任务并行化
5.3.1 使用全局ID替代循环计数器
5.3.2 在循环中使用计算公式代替计数器
替代递增和递减的变量,设计基于全局ID的计算变量值的公式。
5.3.3 以一帧为阶段计算值
如果你的应用需要数据元素的持续更新,它们之间具有依赖,尝试将计算分为离散的单元,每个图像帧一次迭代。
5.3.4 执行带依赖的计算,以multple-passes的方式
如果你的应用需要数据元素的持续更新,它们之间具有依赖,尝试将计算分为离散的单元,多个阶段执行计算。这一技术扩展了5.3.3中所描述的技术,通过通过分开更多的计算。划分数据元素为奇数域和偶数域。这分割了依赖,从而使完整的计算阶段化地执行。处理过程交替奇数域与偶数域的计算。
例如,这一技术可用于神经网络仿真。单个神经元被安排在一个三维网格中。计算一个神经元的状态涉及读取周围神经元。这意味着每个神经元对周围神经元的状态有依赖。
为执行仿真,三维网格被分层,以下面的方式执行:
a. 偶数结点值读取
b. 奇数层计算,存储结果
c. 奇数结点值读取
d. 偶数层计算,存储结果
5.3.5 预先计算值,以移除依赖
5.3.6 使用软件流水线
软件流水线是一种并行处理技术,使能多数据单元被同时处理,通过将计算分成一系列的顺序阶段。在一个流水线中,完整的过程被分成一些列阶段。一个数据在一个阶段中被处理,然后将结果传递到下一阶段。
5.3.7 使用任务并行化
5.4 对不可并行代码使用平行处理
如果你无法并行化你的代码,任然有可能使用并行处理。大多数运行在应用处理器上的代码,顺序运行。代码使用串行算法和非并发数据结构。并行化这种类型的代码会是很困难的或者是不可能。不能并行化代码的事实只是意味着这种特定实现无法并行化,这并不意味着问题不能以并行的方式得到解决。
研究下列方法:
使用你数据结构和算法的并行化版本
很多常用的数据结构和算法,使用时是非并发的。这阻止了你并行化代码。很多常用的数据结构和算法具有并行化版本。你可能使用这些以代替原始的代码,以并行化代码。见使用并发数据结构
用一种不同的方式解决问题
退一步想想代码所解决的问题。看看这个问题,研究解决它的替代方式。可能有替代方案,使用了可并行化的算法和数据结构。
从代码和数据结构的目的方面来考虑。
典型地,代码的目的是处理或传输数据。它获取一个特定的输入,产生一个特定的输出。
> 你要处理的数据可以被打破分成晓得数据元素吗?
> 这些数据元素可以被放进并发数据结构吗?
> 你能独立地处理数据元素吗?
如果答案是yes,你可能可以用OpenCL解决你的问题。
5.5 为OpenCL划分数据
这一部分讲述为OpenCL处理划分数据。它包含以下部分:
> 关于为OpenCL划分数据
> 使用并发数据结构
> 数据划分样例
5.5.1 关于为OpenCL划分数据
数据被划分,从而可以用OpenCL并行地计算。数据被分成下列层次等级:
> 最高层次,数据被划分成一个NDRange。NDRange中元素的总数目被称为全局工作大小
> NDRange被划分成工作组
> 每一个工作组被划分成工作项
5.5.2 使用并发数据结构
OpenCL执行成百上千个独立的内核实例,因此,处理和数据结构必须并行化到那个程度。这意味着你必须使用的数据结构,允许多个数据元素被同时独立地读和写。这被称为并发数据结构。很多常见的数据结构是非并发的,例如链表,哈希表,B树,图。很多常用的数据结构具有并行化版本。
5.5.3 数据划分样例
下面是你可以用OpenCL处理的不同维度数据的样例。
注意:这些样例使用相同数量的维度将问题映射到NDRange。OpenCL并不要求你这么做。你可以映射一个一维问题到一个二维或三维NDRange。
一维数据
一个一维数据的例子是音频。音频代表一系列的采样。音频音量的修改是个并行化任务,因为操作在每个采样独立地执行。在这个例子中,NDRange是音频中采样的总数。每个工作项可以是一个采样,一个工作组是一个采样的集合。音频也可以用向量处理。如果你的音频采样是16位的,你可以使一个工作项代表8个采样,用向量指令一次处理8个。
二维数据
图像天然适合OpenCL,因为它是一个二维像素数组。你可以处理一个1600x1200像素的图像,通过将它映射到一个1600x1200的NDRange。工作项的总数是图像中像素的总数,也就是,1920000。
NDRange被划分成工作组,每个工作组也是个二维数组。工作组的数目必须为NDRange恰好划分。如果每个工作项处理一个单一的像素,一个工作组的大小为8x16,大小为128。工作组大小正好适合划分NDRange,同时包括x和y坐标。为了处理图像,你需要15000个工作组,每个工作组由128个工作项。
你可以向量化这个例子,通过在一个单一的向量中处理所有的颜色通道。如果通道是8比特值,你可以在一个单一的向量中处理多个像素。如果每个向量处理4个像素,这意味着每个工作项处理四个像素,你需要少四倍的工作项来处理整个图像。这意味着NDRange可以被减少到400x1200,你只需要3750个工作组来处理图像。
三维数据
你可以使用三维数据来为真实世界中的物质行为建模。例如,你可以为建筑建模具体的行为,通过仿真三维数据集的压力。你可以使用产生的数据确定你需要的尺寸和设计,以保持特定的负载。你可以在游戏中使用这一技术为物理对象建模。当一个对象被打破,物理仿真使得打破的过程更加真实。
《Mali-T600系列GPU OpenCL开发者指南》第五章<转换现有代码到OpenCL>笔记,布布扣,bubuko.com
《Mali-T600系列GPU OpenCL开发者指南》第五章<转换现有代码到OpenCL>笔记
原文:http://blog.csdn.net/cloud_desktop/article/details/21075701