Chart 5 性能优化概述

文章目录

  • 前言
  • 5.1 可移植性
  • 5.2 优化梗概
  • 5.3 OpenCL 移植的初始评估
  • 5.4 将CPU代码移植到OpenCL GPU
  • 5.5 并行化GPU和CPU工作负载
  • 5.6 瓶颈分析
    • 5.6.1 识别瓶颈
    • 5.6.2 解决瓶颈
  • 5.7 API层面性能优化
    • 5.7.1 API函数调用的正确安排
    • 5.7.2 使用基于事件驱动的pipeline
    • 5.7.3 内核编译和构建
    • 5.7.4 二进制内核的向后兼容性
    • 5.7.5 使用有序命令队列
  • 总结


前言

这一章节提供了对 OpenCL 应用程序优化的高层次概述。更多的细节将在接下来的几章中讨论。
对 OpenCL 应用程序进行优化可能是一项具有挑战性的任务。通常,它需要比初始开发更多的工作。


5.1 可移植性

正如第2.4.2节所讨论的,OpenCL的性能严重依赖于硬件平台的底层体系结构,通常在不同体系结构间不具备可移植性。在其他平台上优化的OpenCL应用,特别是在离散GPU上优化的应用,可能在移动GPU上表现不佳。因此,其他OpenCL供应商的最佳实践可能不适用于Adreno GPU。对Adreno GPU的优化工作至关重要,需要仔细阅读整个文档。另外,针对Adreno GPU优化的OpenCL应用可能需要进一步调整和优化,以在其他Adreno GPU上实现最佳性能。

性能、生产力和可移植性通常是开发者需要平衡的三个因素。同时实现这三个目标是困难的,因为它们取决于时间、预算和目标。例如,更好的可移植性需要更通用的代码,因为某些特定的优化技巧可能仅适用于某些GPU。同样,实现更好的生产力,即能够快速开发、优化和部署应用程序,通常需要在性能或可移植性上做出妥协。开发者必须根据他们的优先级和目标做出谨慎的决策。
在这里插入图片描述

5.2 优化梗概

对于 OpenCL 应用程序的优化可以从高到低大致分为以下三个层次:

  • 应用程序/算法。
  • API 函数。
  • 内核优化。

一个OpenCL的优化问题本质上是如何最优地利用内存带宽和计算能力的问题,包括:

  • 如何最优地使用全局内存、局部内存、寄存器、缓存等。
  • 如何最优地利用计算资源,例如ALU(算术逻辑单元)和纹理操作。
  • 应用程序级别的优化策略在本章的其余部分讨论,而其他层次的内容将在接下来的章节中详细介绍。

5.3 OpenCL 移植的初始评估

在盲目移植之前,开发者必须评估一个应用程序是否适合使用OpenCL。以下是适合在GPU上使用OpenCL加速的应用程序的典型特征:

  • 大规模的输入数据集。
    • 对于小规模输入数据集,CPU与GPU之间的通信开销可能会掩盖OpenCL的性能优势。
  • 计算密集型。
    • GPU具有许多计算单元(ALUs),它们的峰值计算能力通常远高于CPU。为充分利用GPU,应用程序应具有相当高的计算复杂性。
  • 并行计算友好。
    • 工作负载可以被分割成小的独立单元,每个单元的处理不会影响其他单元。
    • GPU需要并行化任务以隐藏延迟。
  • 控制流分支有限。
    • 通常情况下,GPU不能像CPU一样高效地处理分歧控制流。如果使用情景需要大量条件检查和分支操作,可能更适合使用CPU。

5.4 将CPU代码移植到OpenCL GPU

通常,开发者可能已经有了一个基于CPU的用于OpenCL移植的参考程序。假设该程序由许多小的功能模块组成。虽然将每个模块逐个转换为OpenCL内核似乎很方便,但性能可能不会达到最佳。考虑以下因素是至关重要的:

  • 在某些情况下,将多个CPU功能模块合并为一个OpenCL内核可能会导致更好的性能,尤其是在减少GPU与内存之间的数据流量时。
  • 在某些情况下,将复杂的CPU功能模块拆分为多个简单的OpenCL内核可能会产生更好的(内核)并行化和更好的整体性能。
  • 开发者可能需要修改数据结构以调整数据流,减少整体流量。

5.5 并行化GPU和CPU工作负载

为了充分利用SOC的计算能力,应用程序可能会在GPU执行内核的同时将一些任务委派给CPU。在设计这种拓扑结构和分配工作负载时,需要考虑以下几点:

  • 让CPU执行最适合CPU的部分,比如分歧控制流和顺序操作。
  • 避免GPU处于空闲状态等待CPU完成,反之亦然。
  • CPU和GPU之间的数据共享可能会很昂贵,特别是如果它们需要大量的同步或数据传输。相反,尝试将轻量级的CPU任务转移到GPU,即使它可能不适合GPU,以消除开销。

5.6 瓶颈分析

瓶颈是开发者应该花费最多时间优化的最慢的阶段。无论其他阶段效率多高,应用程序的性能都受到其瓶颈的限制。识别和分析瓶颈是至关重要的,而且并不总是直截了当的。本节简要讨论了如何识别和解决瓶颈。

5.6.1 识别瓶颈

通常,一个内核要么是受内存限制的,要么是受计算限制的(也称为ALU受限)。一个简单的技巧是操纵内核代码并在设备上运行内核,方法如下:

  • 如果增加更多的计算不改变性能,那可能不是计算受限的。
  • 如果过多的数据加载不改变性能,那可能不是内存受限的。

正如第4.3节所讨论的,Snapdragon性能分析工具可用于识别瓶颈。

5.6.2 解决瓶颈

一旦瓶颈被识别出来,可以采用不同的策略来解决它。

  • 如果这是一个受ALU限制的问题,找到降低计算复杂性和计算量的方法。
    • 使用 fast relaxed math 或 native math(类似于fast-math的编译选项)。
    • 使用16位浮点格式而不是32位浮点格式。
  • 如果这是一个受内存限制的问题,尝试改进内存访问,比如矢量化加载/存储,利用局部内存或纹理缓存(例如,使用只读图像对象替代缓冲区对象)。在GPU和全局内存之间使用较短的数据类型加载/存储数据可能有助于节省内存流量。

具体细节将在接下来的章节中详细描述。

注意:随着优化的进行,瓶颈可能会发生变化。在解决了内存瓶颈后,一个原本是受内存限制的问题可能会变成受ALU限制的问题,反之亦然。为了获得最佳性能,可能需要多次迭代。此外,不同的GPU可能存在不同的瓶颈。

5.7 API层面性能优化

负责管理资源和控制应用程序执行的OpenCL API函数大部分在CPU主机上运行。尽管这些函数的要求不如内核执行那么高,但不正确使用API函数可能会导致严重的性能惩罚。以下是一些建议,可以帮助开发者避免一些常见的陷阱。

5.7.1 API函数调用的正确安排

API函数应该被正确地放置,以防止它们阻塞或影响将工作负载启动到GPU。一些OpenCL API函数执行时间较长,应该在执行循环之外调用。例如,以下函数可能需要较长时间来执行:

clCreateProgramWithSource()
clBuildProgram()
clLinkProgram()
clUnloadPlatformCompiler()
  • 为了减少应用程序启动期间的执行时间,请使用clCreateProgramWithBinary而不是clCreateProgramWithSource。详细信息请参见第5.7.3节。

当clCreateProgramWithBinary失败时,不要忘记回退到从源代码构建。然而,这可能发生在OpenCL软件有不兼容的更新时。

  • 在内核调用之间避免创建或释放内存对象。clCreate{Image|Buffer}的执行时间与请求的内存量相关(如果使用host_ptr)。

  • 如果可能的话,使用Android ION内存分配器。clCreate{Buffer|Image2D}可以创建具有ION指针的内存对象,而不是分配额外的内存并进行复制。第7.4节讨论了如何使用ION内存。

  • 尽量重用OpenCL中的内存和上下文对象,避免创建新对象。主机在GPU内核启动期间应该进行轻量级的工作,以避免阻塞GPU的执行。

5.7.2 使用基于事件驱动的pipeline

OpenCL的enqueue API函数可以接受一个事件列表,该列表指定在当前API函数开始执行之前必须完成的所有事件。同时,enqueue API函数也可以生成一个事件ID来标识自己。主机只需将API函数和内核提交到GPU进行执行,而无需担心它们的依赖关系和完成情况,只要在事件列表参数中正确指定了依赖关系。使用这种方法显著减少了启动API函数调用的开销。软件可以最佳地安排这些函数,主机不必干涉API函数调用。因此,通过使用基于事件的管道来简化API函数是非常可取的。此外,开发者应注意以下几点:

  • 避免阻塞式API调用。阻塞调用需要主机CPU等待GPU完成,然后在下一次clEnqueueNDRangeKernel调用之前阻塞GPU。阻塞API调用主要用于调试。
  • 使用回调函数。从OpenCL 1.2开始,许多API函数被增强或修改以接受用户定义的回调函数来处理事件。这种异步调用机制使得主机在处理事件方面更加灵活,从而实现更有效的管道执行。

5.7.3 内核编译和构建

在运行时编译和构建内核源代码可能会很昂贵。一些应用程序可能会动态生成源代码,因为一些参数可能在一开始就不可用。如果创建和编译源代码不影响GPU执行,这可能是可以接受的。但总的来说,不建议使用动态源代码生成。

与即时构建源代码相比,更好的方法是离线创建源代码并仅使用二进制内核。在加载应用程序时,二进制内核代码也会被加载。这样做会显著减少从磁盘加载代码的开销。

5.7.4 二进制内核的向后兼容性

如果应用程序面向不同层次的Adreno设备,则需要不同版本的二进制代码。

  • 二进制代码只能用于它编译的特定GPU。例如,为Adreno A730 GPU编译的二进制代码不能用于Adreno A740 GPU。
  • 不能保证对于同一设备,从OpenCL软件的一个版本构建的二进制代码能够直接在新版本的OpenCL软件中重复使用。
  • 如果二进制内核不兼容,可以使用clCreateProgramWithSource作为备用解决方案。

5.7.5 使用有序命令队列

Adreno OpenCL平台支持无序命令队列。然而,实现无序命令队列所需的依赖管理,存在显著的开销。Adreno软件可以高效地为有序队列流水线处理命令。因此,使用有序命令队列而不是无序命令队列是一个良好的做法。


总结

本文废话有点多,需要快速开发的同学,可以不用那么细看本章

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/204726.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2023-12-04 AIGC-Stable Diffusion和SadTalker-搭建及使用

摘要: 2023-12-04 AIGC-SadTalker-搭建及使用 代码仓库: https://github.com/Stability-AI/stablediffusion https://github.com/camenduru/stable-diffusion-webui-colab https://github.com/OpenTalker/SadTalker https://github.com/adofsauron/SadTalker-Video-Lip-Sync 文…

0基础学习云计算难吗?

很多人经常会问云计算是什么?云计算能干什么?学习云计算能做什么工作?其实我们有很多人并不知道云计算是什么,小知今天来给大家讲讲学习云计算能做什么。 中国的云计算行业目前正处于快速发展阶段,随着互联网和数字化…

人脸识别安卓主板_MTK方案智能闸机门禁工业安卓主板定制开发

人脸识别主板广泛应用于各个领域,包括人脸支付系统、人脸识别监控系统、写字楼办公楼门禁闸机、校园、地铁、住宅门禁、考勤机、智能门锁、广告机、售卖机等。 主板基于联发科MTK方案,并由行业PCBA和MTK的核心板组成。根据产品需求,可以选择…

7、类型转换构造、析构、深拷贝、类的静态成员

1、类型转换构造 |自定义转换 利用一个已定义的对象,来定义另一个不同类型的对象 实现从源类型到目标类型的隐式类型转换的目的 总结下已知构造,包括类型转换构造 如下,如果Person给Human赋值时,Person有私有变量,则需要在Pers…

浅聊JAVA开发下环境部署与使用工具的安装与部署

Java开发环境的部署涉及到安装Java Development Kit(JDK)、配置系统环境变量、选择一个集成开发环境(IDE)等步骤。以下是一般情况下的Java开发环境部署步骤: 安装Java Development Kit (JDK): 访问 Oracle JDK下载页面…

qt creator配置opencv库 (MSVC版本)

目录 1. MSVC版本 1.1 使用cmake编译opencv 1.2 再使用visual studio 2019生成opencv的lib,dll 1.3 配置opencv的系统环境变量 1.4 新建qt项目 1. MSVC版本 1.1 使用cmake编译opencv 1.2 再使用visual studio 2019生成opencv的lib,dll 1.3 配置opencv的系统环境变量 D:…

Educational Codeforces Round 159 (Div. 2) A~E

A.Binary lmbalance(思维) 题意: 给出一个01字符串,你可以对字符串进行无限次下列操作: 选择一个位置 i ( 1 ≤ i ≤ ∣ s ∣ − 1 , |s|为字符串s的长度 ) i(1 \le i \le |s| - 1,\text{|s|为字符串s的长度}) i(1≤…

深度学习实战66-基于计算机视觉的自动驾驶技术,利用YOLOP模型实现车辆区域检测框、可行驶区域和车道线分割图

大家好,我是微学AI,今天给大家介绍一下深度学习实战66-基于计算机视觉的自动驾驶技术,利用YOLOP模型实现车辆区域检测框、可行驶区域和车道线分割图。本文我将介绍自动驾驶技术及其应用场景,并重点阐述了基于计算机视觉技术下的自动驾驶。自动驾驶技术是一种利用人工智能和…

Linux报too many open files的解决方案及 lsof、sysctl 命令介绍

Too many open files in system 问题处理 服务器异常: 一串的etc下的shell文件报 /etc/profile.d/bash_completion.sh: Too many open files in system 查看当前操作系统允许打开的文件数 # 用户级查看: ulimit -n # 系统级查看: cat /pro…

Java实现屏幕截图程序(二)

本文是继Java实现屏幕截图程序(一)之后进行加工的,主要逻辑是依靠javafx界面进行屏幕范围选择和截图图片显示,在日常工作中较为适用,下面把代码分享给大家。 以下是JavaFX实现的简单选择界面截图程序代码: 屏幕拖动监听器,截图后的界面可拖动就靠它: import javafx.e…

LeetCode刷题--- 计算布尔二叉树的值

个人主页:元清加油_【C】,【C语言】,【数据结构与算法】-CSDN博客 个人专栏:http://t.csdnimg.cn/ZxuNL http://t.csdnimg.cn/c9twt 前言:这个专栏主要讲述递归递归、搜索与回溯算法,所以下面题目主要也是这些算法做的 我讲述…

cache教程1.LRU 缓存淘汰策略

这一节实现LRU算法,要理解明白其使用的数据结构。 FIFO/LFU/LRU 算法简介 Cache的缓存全部存储在内存中,内存是有限的,因此不可能无限制地添加数据。当占用内存超过了给定的内存大小时候,就需要从缓存中移除一条或多条数据了。我…

计算机网络(二)| 物理层上 | 数据通信基础知识 调制 频率范围 信噪比

文章目录 1 物理层基本概念2.数据通信基础知识2.1 数据通信基本概念2.2 信道基本概念2.2.1 基带调制(编码)方式2.2.2 带通调制方式 2.3 信道的极限速率影响因素2.3.1 **频率范围**2.3.2 **信噪比** 内容笔记来源于谢希任老师《计算机网络》 物理层重点 …

Xilinx FPGA平台DDR3设计详解(三):DDR3 介绍

本文介绍一下常用的存储芯片DDR3,包括DDR3的芯片型号识别、DDR3芯片命名、DDR3的基本结构等知识,为后续掌握FPGA DDR3的读写控制打下坚实基础。 一、DDR3芯片型​号 电路板上的镁光DDR3芯片上没有具体的型号名。 ​如果想知道具体的DDR3芯片型号&#…

rename--一些例子与问题

指令 A 和指令 B之间存在先写后读(RAW)的相关性 指令 B 的源寄存器 r0 来自于指令 A 产生的结果因此在进行寄存器重命名的时候,指令 B 的 r0 对应的物理寄存器应该直接来自于指令A所对应的P30,而不应该来自于从RAT读取的值。指令A,B,D之间存在先写后写(WAW)的相关性…

阿里云效部署前后端

静态站点到OSS 阿里云-云效,阿里云企业级一站式 DevOps,可以免费使用(会限制人数、流水线数量等,个人项目够用了)。相关文章 CI 持续集成 - 阿里云云效 OSS 是对象存储的意思,一般一个项目对应一个 Bucke…

20231202年江西省“振兴杯”网络信息行业(信息安全测试员)职业技能竞赛

C1-xor chall.py from flag import flagdef encrypt(x, y):keyzxbresultfor i in range(len(x)):resultchr(ord(x[i])^ord(y[i])^ord(key[i%3]))return result x flag y flag[1:] flag[0]enc open(flag.enc, wb) enc.write(encrypt(x, y)) enc.close()简单的异或&#xf…

一个小问题

用paddle的paddleOCR的时候,需要修改部分代码,但是直接Python xx.py不能运行,需要用paddle自己的命令行方式运行,感觉很麻烦啊。 另外工作上遇到像这样的小问题,应不应该去问同事呢,感觉这个问题比较简单但…

使用Jython将Python代码转换为Java可执行文件

步骤1:安装Jython 首先,我们需要安装Jython。可以使用pip命令来安装Jython: pip install jython 步骤2:编写Python代码 第二步是编写你的Python代码。在这个例子中,我们简单地打印出"Hello World!"。你可…

Java API接口强势对接:构建高效稳定的系统集成方案

文章目录 1. Java API接口简介2. Java API接口的优势2.1 高度可移植性2.2 强大的网络通信能力2.3 多样化的数据处理能力 3. 实战:Java API接口强势对接示例3.1 场景描述3.2 用户管理系统3.3 订单处理系统3.4 系统集成 4. 拓展:Java API接口在微服务架构中…