OpenCL内存性能优化 (2)
OpenCL内存性能优化 (2)
- 7.1.4 全局内存
- 7.1.4.1 缓冲区
- 7.1.4.2 图片
- 7.1.4.3 使用图像对象与缓冲区对象
- 7.1.4.4 图像和缓冲区对象的使用
- 7.1.4.5 全局内存与本地内存
- 7.2 最佳内存加载/存储
- 7.2.1合并的内存加载/存储
- 7.2.2 矢量化加载/存储
- 7.2.3 最佳数据类型
- 7.2.4 16位浮点(半)与32位浮点
- 7.3 原子功能
7.1.4 全局内存
OpenCL应用程序可以使用两种类型的全局内存对象,即缓冲区和映像,并且都使用片外系统RAM。 与缓冲区对象(它是存储在系统RAM中的简单一维数据数组)相比,在开发人员无法假定内部数据存储方式的布局或格式的意义上,图像对象是不透明的存储对象。 创建图像对象后,该软件会以某些方式排列数据,以使GPU能够更高效地进行访问。 使用它们的最佳方法大不相同,以下各节将进行讨论。
7.1.4.1 缓冲区
缓冲区对象存储元素的一维集合,这些元素可以是标量数据类型(例如整数,浮点数),矢量数据类型或用户定义的结构。 使用以下API函数创建一个缓冲区对象:
cl_mem clCreateBuffer (cl_context context,
cl_mem_flags flags,
size_t size,
void *host_ptr,
cl_int *errcode_ret)
缓冲区对象存储在全局内存中,并通过Adreno GPU中的L2缓存进行访问。 在此函数中,最重要的参数是cl_mem_flags。 OpenCL为此功能提供了许多不同的标志,而如何选择和组合这些标志对于性能而言非常重要。 这里有几点:
- 某些标志可能会导致额外的内存副本。 尝试使用第7.4节中讨论的零复制标志。
- 某些标志适用于具有专用GPU内存的台式机/离散GPU。
- 使用最准确的标志。 一般的想法是,随着标志的限制越来越严格,OpenCL驱动程序可以为对象找到更好的配置并提高其性能。 例如,它可以强加最适合内存对象的缓存刷新策略(直写,回写等)。 第7.4.2节详细介绍了缓存策略及其对性能的影响。 这里有一些例子:
- 如果内存是主机只读的,则使用CL_MEM_HOST_READ_ONLY。
- 如果内存不能被主机访问,则使用CL_MEM_HOST_NO_ACCESS。
- 如果内存仅用于主机写入,请使用CL_MEM_HOST_WRITE_ONLY。
7.1.4.2 图片
图像对象用于存储一维,二维或三维纹理,帧缓冲区或图像数据,并且图像对象内部的数据布局是不透明的。 实际上,对象中的内容不必与实际图像数据相关联。 任何数据都可以存储为图像对象,以利用Adreno中的硬件纹理引擎及其L1缓存。
使用以下API创建图像对象:
cl_mem clCreateImage(cl_context context,
cl_mem_flags flags,
const cl_image_format *image_format,
const cl_image_desc *image_desc,
void *host_ptr,
cl_int *errcode_ret)
注意,图像的cl_mem_flags具有与上一节中讨论的缓冲区对象相似的经验法则。
Adreno GPU支持多种图像格式和数据类型。 从Adreno A3x GPU到Adreno A5x GPU,添加了新的图像格式和数据类型对。 用户可以使用功能clGetSupportedImageFormats来获取支持的图像格式/数据类型的完整列表。
为了充分利用内存带宽,建议使用长度为128位的对,例如CL_RGBA / CL_FlOAT,CL_RGBA / CL_SIGNED_INT32等。
7.1.4.3 使用图像对象与缓冲区对象
使用图像对象而不是缓冲区对象具有以下优点:
- 利用纹理引擎硬件。
- 利用L1缓存
- 内置图像边界处理。
- 支持第7.1.4节“图像”下列出的多种图像格式和数据类型组合,并支持自动格式转换。
OpenCL支持两个采样器过滤器,CLK_FILTER_NEAREST和CLK_FILTER_LINEAR。 对于CLK_FILTER_LINEAR,图像类型的正确组合允许GPU使用其内置的纹理引擎进行自动双线性插值。
例如,假定图像的类型为CLK_NORMALIZED_COORDS_TRUE和CL_UNORM_INT16,即图像日期为2字节无符号短。 函数调用read_imagef将执行以下操作:
- 从图像对象读取像素(然后将其缓存在L1缓存中)。
- 插值硬件中的相邻像素。
- 将其转换并归一化为[0,1]的范围
这对于双线性或三线性插值运算很方便。
有时,缓冲区对象可能是更好的选择:
- 更灵活的数据访问:
- 图像对象仅允许访问像素大小边界,例如,对于RGBA和128位/通道图像对象,访问权限为128位。
- 对于缓冲区对象,Adreno支持字节可寻址访问。 例如,如果没有超出缓冲区边界,则可以从缓冲区对象中的任何字节地址加载128位数据。
- 如果L1成为瓶颈。
- 例如,存在严重的L1缓存抖动,这使L1缓存访问效率低下。
可以在内核内部读写缓冲区对象。 尽管还可以从OpenCL 2.0读取和写入图像对象,但是由于同步要求,其性能通常较差。
7.1.4.4 图像和缓冲区对象的使用
代替仅使用纹理对象或仅使用缓冲区对象,更好的方法是充分利用UCHE<=>SP和UCHE<=>TPL1<=>SP路径。 由于TPL1具有L1高速缓存,因此最好将L1存储为最常用但相对较少的数据。
7.1.4.5 全局内存与本地内存
本地内存的一种使用情况是,首先将数据加载到本地内存中,进行同步以确保数据准备就绪,然后工作组中的工作项可以将其用于处理。 但是,由于以下原因,使用全局内存可能比LM更好。
- 可能具有更好的二级缓存命中率和更好的性能
- 代码比本地内存更简单,并且工作组更大
7.2 最佳内存加载/存储
在前面的部分中,我们讨论了有关如何使用不同类型的内存的一般指导。 在本节中,我们将介绍一些关键的和一般的要点,这些要点对于内存加载/存储的性能至关重要。
7.2.1合并的内存加载/存储
合并的加载/存储是指结合来自多个相邻工作项的加载/存储请求的功能,如第3.3.1节中所述,用于本地内存访问。 合并访问对于全局内存加载/存储也很重要。
合并存储以类似于读取的方式工作,除了负载是2向过程(请求和响应),而存储是1向过程。 因此,合并的负载通常比存储更重要。
自Adreno A4x GPU以来,在Adreno GPU中,逐渐启用了硬件合并访问,如表7-3所示。 专用内存不支持合并访问。
7.2.2 矢量化加载/存储
矢量化加载/存储是指对单个工作项以矢量化方式进行的多个数据加载/存储。 这与合并访问不同,合并访问是针对多个工作项的。 以下是使用向量化加载/存储的一些关键点:
- 对于每个工作项,建议以多个字节的块(例如64位/ 128位)加载数据,这样可以更好地利用带宽。
- 例如,可以将多个8位数据手动打包到一个元素(例如64位/ 128位)中,该元素使用vloadn加载,然后使用as_typeN函数(例如as_char16)解压缩。
- 请参见第9.2.3节中的向量化操作示例。
- 为了获得最佳的SP到L2带宽性能,加载/存储内存地址应为32位对齐。
- 有两种方法可以进行向量化的加载/存储:
- 使用内置函数(vload / vstoren),该函数在OpenCL中已定义好。
- 或者,可以使用指针强制转换进行向量化的加载/存储,如下所示:
char *p1; char4 vec;
vec = *(char4 *)(p1 + offset);
- 建议使用最多包含4个组件的矢量化加载/存储指令。 具有超过4个组成部分的数据类型的矢量化加载将被分为多个加载/存储指令,每个指令占用不超过4个组成部分。
- 避免在一个工作项中加载太多数据。
- 加载太多数据可能会导致寄存器占用量增加,从而导致工作组规模变小并影响性能。 在最坏的情况下,这可能会导致寄存器溢出,即编译器必须使用系统RAM来存储变量。
注意:
矢量化的ALU计算也可以提高性能,尽管通常不如矢量化的内存加载/存储计算那样。
7.2.3 最佳数据类型
数据类型很重要,因为它不仅影响内存流量,还影响ALU操作。 以下是有关数据类型的一些规则:
- 检查应用程序管道的每个阶段中的数据类型,并确保在整个管道中使用的数据类型是一致的。
- 如果可能,请使用较短的数据类型,以减少内存获取/带宽,并增加可用于执行的ALU数量。
7.2.4 16位浮点(半)与32位浮点
强烈建议使用一半数据类型而不是浮动数据类型,因为Adreno GPU具有专用的硬件来加速一半数据类型的计算。 半个ALU的触发器几乎是完整ALU的两倍。 以下是一些规则:
- 16位半数的精度支持有限。 它只能精确表示狭窄范围内的数据。
- 例如,它只能在整数值上准确表示[0,2048]。
- 如果一半数据计算导致不可接受的精度损失,则将一半转换为浮点数以进行计算。 但是将结果存储为一半数据类型。
7.3 原子功能
OpenCL中定义了一组局部和全局原子函数,而Adreno GPU本身在硬件中支持所有这些原子函数。 以下是使用原子函数时的一些规则:
- 避免由单个或多个工作组中的工作项频繁更新单个全局原子内存地址,因为原子操作是序列化操作,并且其性能通常不如并行操作好。
- 尝试首先使用本地原子,并自动对全局内存进行单个更新。
OpenCL内存性能优化 (2)相关推荐
- 经典|图解Linux内存性能优化核心思想
hi,大家好,今天分享一篇内存性能优化的文章,文章用了大量精美的图深入浅出地分析了Linux内核slab性能优化的核心思想,slab是Linux内核小对象内存分配最重要的算法,文章分析了内存分配的各种 ...
- 转:AIX 5L 内存性能优化
引言 内存子系统中最重要的优化部分并不涉及到实际的优化工作.在对您的系统进行优化之前,必须弄清楚主机系统的实际运行情况.要做到这一点,AIX® 管理员必须知道应该使用何种工具,以及如何对他或她将要捕获 ...
- 【chrome devtools】前端性能分析之chrome devtools的使用 前端项目内存性能优化的建议 前端浏览器崩溃卡死 前端性能分析实战
最近有个项目,静置一段时间,chrome内存一直上涨.就像是这样: 内存会慢慢悄悄的往上涨,最终可以到达2000多M,直至浏览器崩溃卡死.很明显,这应该是内存泄漏了. 但是只知道内存泄漏,并不知道究竟 ...
- android app性能优化大汇总(内存性能优化)
内存简介: RAM(random access memory)随机存取存储器.说白了就是内存. 一般Java在内存分配时会涉及到以下区域: 寄存器(Registers):速度最快的存储场所,因为寄存器 ...
- 性能优化系列(三)内存性能优化
文章首发「Android波斯湾」公众号,更新地址:https://github.com/jeanboydev/Android-ReadTheFuckingSourceCode Android 为每个应 ...
- 傲腾内存不支持linux吗,英特尔一面优化傲腾可持续内存性能 一面不忘科普
原标题:英特尔一面优化傲腾可持续内存性能 一面不忘科普 对于英特尔傲腾技术,科技圈内人士应该不会陌生,最近英特尔不仅忙着通过补丁优化其可持续内存性能,还不忘向广大科技爱好者科普傲腾增强型SSD的优势. ...
- 「性能优化系列」APP内存优化理论与实践
当一个应用同时运行越来越多的任务以及复杂的业务,Android系统的内存管理机制已经无法满足内存的释放与回收,为了应用的稳定性与性能,去控制内存的创建和回收就成为了一个重要的命题. 本篇文章主要涉及内 ...
- android 应用性能优化1
1 背景 其实有点不想写这篇文章的,但是又想写,有些矛盾.不想写的原因是随便上网一搜一堆关于性能的建议,感觉大家你一总结.我一总结的都说到了很多优化注意事项,但是看过这些文章后大多数存在一个问题就是只 ...
- 如何做好 VMware vSphere 性能优化?
如何做好 VMware vSphere 性能优化? https://mp.weixin.qq.com/s?__biz=MjM5NTk0MTM1Mw==&mid=2650633755&i ...
最新文章
- 【Linux】在VirtualBox-6.0中安装Manjaro18.0
- poj2739(尺取法+质数筛)
- eclipse if代码折叠_仅需一页Java代码就能实现网页源码爬取
- 阿里云(一)云存储OSS的命令行osscmd的安装和使用
- BugKuCTF WEB web5
- 硒4 Alpha –期望什么?
- 2021吉林高考26日几点可以查询成绩,2021吉林高考成绩查分时间及入口
- P4172 [WC2006]水管局长 LCT维护最小生成树
- dante pam mysql_FreeBSD下安装dante(sockd)并使用pam-pwdfile进行认证
- DNS使用的是TCP协议还是UDP协议
- R语言将数据框中的字符类型数字转换为数值
- 内码输入法手机版下载_win7 64位内码输入法下载
- JPA+QueryDSL
- Vue在线预览word
- Linux命令之远程拷贝文件scp
- Linux 快速搭建免费邮件服务器
- 常见的USB VID
- 【python】之字符串格式化
- Attempt to invoke virtual method ‘void cn.jiguang.share.android.api.AbsPlatform.notifyError
- NSGA-2学习笔记