移动端异构运算技术 - GPU OpenCL 编程(基础篇)

news2024/11/24 0:45:46

一、前言

随着移动端芯片性能的不断提升,在移动端上实时进行计算机图形学、深度学习模型推理等计算密集型任务不再是一个奢望。在移动端设备上,GPU 凭借其优秀的浮点运算性能,以及良好的 API 兼容性,成为移动端异构计算中非常重要的计算单元。现阶段,在 Android 设备市场,高通 Adreno 和华为 Mali 已经占据了手机 GPU 芯片的主要份额,二者均提供了强劲的 GPU 运算能力。OpenCL,作为 Android 的系统库,在两个芯片上均得到良好的支持。

目前,百度 APP 已经将 GPU 计算加速手段,应用在深度模型推理及一些计算密集型业务上,本文将介绍 OpenCL 基础概念与简单的 OpenCL 编程。
(注:Apple 对于 GPU 推荐的使用方式是 Metal,此处暂不做展开)

二、基础概念

2.1 异构计算

异构计算(Heterogeneous Computing),主要是指使用不同类型指令集和体系架构的计算单元组成系统的计算方式。常见的计算单元类别包括 CPU、GPU 等协处理器、DSP、ASIC、FPGA 等。

2.2 GPU

GPU(Graphics Processing Unit),图形处理器,又称显示核心、显卡、视觉处理器、显示芯片或绘图芯片,是一种专门在个人电脑、工作站、游戏机和一些移动设备(如平板电脑、智能手机等)上执行绘图运算工作的微处理器。传统方式中提升 CPU 时钟频率和内核数量而提高计算能力的方式已经遇到了散热以及能耗的瓶颈。虽然 GPU 单个计算单元的工作频率较低,却具备更多的内核数及并行计算能力。相比于 CPU,GPU 的总体性能 - 芯片面积比,性能 - 功耗比都更高。

三、OpenCL

OpenCL(Open Computing Language)是一个由非盈利性技术组织 Khronos Group 掌管的异构平台编程框架,支持的异构平台涵盖 CPU、GPU、DSP、FPGA 以及其他类型的处理器与硬件加速器。OpenCL 主要包含两部分,一部分是一种基于 C99 标准用于编写内核的语言,另一部分是定义并控制平台的 API。

OpenCL 类似于另外两个开放的工业标准 OpenGL 和 OpenAL ,二者分别用于三维图形和计算机音频方面。OpenCL 主要扩展了 GPU 图形生成之外的计算能力。

3.1 OpenCL 编程模型

使用 OpenCL 编程需要了解 OpenCL 编程的三个核心模型,OpenCL 平台、执行和内存模型。

平台模型(Platform Model)

Platform 代表 OpenCL 视角上的系统中各计算资源之间的拓扑联系。对于 Android 设备,Host 即是 CPU。每个 GPU 计算设备(Compute Device)均包含了多个计算单元(Compute Unit),每个计算单元包含多个处理元素(Processing Element)。对于 GPU 而言,计算单元和处理元素就是 GPU 内的流式多处理器。

执行模型 (Execution Model)

通过 OpenCL 的 clEnqueueNDRangeKernel 命令,可以启动预编译好的 OpenCL 内核,OpenCL 架构上可以支持 N 维的数据并行处理。以二维图片为例,如果将图片的宽高作为 NDRange,在 OpenCL 的内核中可以把图片的每个像素放在一个处理元素上执行,借此可以达到并行化执行的目地。

从上面平台模型部分可以知道,为了提高执行效率,处理器通常会将处理元素分配到执行单元中。我们可以在 clEnqueueNDRangeKernel 中指定工作组大小。同一个工作组中的工作项可以共享本地内存,可以使用屏障(Barriers)去进行同步,也可以通过特定的工作组函数(比如 async_work_group_copy)来进行协作。

内存模型 (Memory Model)

下图中描述了 OpenCL 的内存结构:

  • 宿主内存(Host Memory):宿主 CPU 可直接访问的内存。

  • 全局 / 常量内存 (Global/Constant Memory):可以用于计算设备中的所有计算单元。

  • 本地内存(Local Memory):对计算单元中的所有处理元素可用。

  • 私有内存(Private Memory):用于单个处理元素。

3.2 OpenCL 编程

OpenCL 的编程实际应用中需要一些工程化的封装,本文仅以两个数组相加作为举例,并提供一个简单的示例代码作为参考 ARRAY_ADD_SAMPLE (https://github.com/xiebaiyuan/opencl_cook/blob/master/array_add/array_add.cpp)。

本文将用此作为示例,来阐述 OpenCL 的工作流程。

OpenCL 整体流程主要分为以下几个步骤:

初始化 OpenCL 相关环境,如 cl_device、cl_context、cl_command_queue 等

 cl_int status;
// init device
    runtime.device = init_device();
// create context
    runtime.context = clCreateContext(nullptr, 1, &runtime.device, nullptr, nullptr, &status);
// create queue
    runtime.queue = clCreateCommandQueue(runtime.context, runtime.device, 0, &status);

初始化程序要执行的 program、kernel

 cl_int status;
    // init program
    runtime.program = build_program(runtime.context, runtime.device, PROGRAM_FILE);
    // create kernel
    runtime.kernel = clCreateKernel(runtime.program, KERNEL_FUNC, &status);

准备输入输出,设置到 CLKernel

 // init datas 
    float input_data[ARRAY_SIZE];
    float bias_data[ARRAY_SIZE];
    float output_data[ARRAY_SIZE];
    for (int i = 0; i < ARRAY_SIZE; i++) {
        input_data[i] = 1.f * (float) i;
        bias_data[i] = 10000.f;
    }
    // create buffers
    runtime.input_buffer = clCreateBuffer(runtime.context, CL_MEM_READ_ONLY |
        CL_MEM_COPY_HOST_PTR, ARRAY_SIZE * sizeof(float), input_data, &status);
    runtime.bias_buffer = clCreateBuffer(runtime.context, CL_MEM_READ_ONLY |
        CL_MEM_COPY_HOST_PTR, ARRAY_SIZE * sizeof(float), bias_data, &status);
    runtime.output_buffer = clCreateBuffer(runtime.context, CL_MEM_READ_ONLY |
        CL_MEM_COPY_HOST_PTR, ARRAY_SIZE * sizeof(float), output_data, &status);
    // config cl args
    status = clSetKernelArg(runtime.kernel, 0, sizeof(cl_mem), &runtime.input_buffer);
    status |= clSetKernelArg(runtime.kernel, 1, sizeof(cl_mem), &runtime.bias_buffer);
    status |= clSetKernelArg(runtime.kernel, 2, sizeof(cl_mem), &runtime.output_buffer);

执行获取结果

 // clEnqueueNDRangeKernel
    status = clEnqueueNDRangeKernel(runtime.queue, runtime.kernel, 1, nullptr, &ARRAY_SIZE,
                                    nullptr, 0, nullptr, nullptr);
    // read from output
    status = clEnqueueReadBuffer(runtime.queue, runtime.output_buffer, CL_TRUE, 0,
                                 sizeof(output_data), output_data, 0, nullptr, nullptr);
    // do with output_data
    ...

四、总结

随着 CPU 瓶颈的到来,GPU 或者其他专用计算设备的编程将是未来的一个重要的技术方向。

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

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

相关文章

小巧有劲的按摩好手,能装兜里的护理工具,小鸟斗士筋膜枪体验

现在很多朋友为了身体健康&#xff0c;平时都会去做些简单的健身&#xff0c;因为之前长期不运动&#xff0c;所以健身后很容易有肌肉酸痛等问题&#xff0c;对此&#xff0c;筋膜枪是个很好用的工具&#xff0c;可以有效促进血液循环&#xff0c;还能够缓解久坐所导致的腰背酸…

java面试强基(16)

说说 List, Set, Queue, Map 四者的区别&#xff1f; List(对付顺序的好帮手): 存储的元素是有序的、可重复的。Set(注重独一无二的性质): 存储的元素是无序的、不可重复的。Queue(实现排队功能的叫号机): 按特定的排队规则来确定先后顺序&#xff0c;存储的元素是有序的、可…

壳寡糖/肉桂醛修饰乳清蛋白,乳清浓缩蛋白-羟丙基甲基纤维素复合材料

产品名称&#xff1a;壳寡糖修饰乳清蛋白 英文名称&#xff1a;Chitosan-whey protein 用途&#xff1a;科研 状态&#xff1a;固体/粉末/溶液 产品规格&#xff1a;1g/5g/10g 保存&#xff1a;冷藏 储藏条件&#xff1a;-20℃ 储存时间&#xff1a;1年 壳寡糖&#xff0c;又叫…

【图文详解】入职必备——SVN使用教程

一、SVN基本操作 1、进入svnbucket官网&#xff0c;创建一个空项目&#xff0c;学习svn 2、创建好测试项目后&#xff0c;复制对应地址 3、右键点击“SVN 检出” 4、粘贴“版本库URL”&#xff0c;填写“检出至目录”&#xff0c;最后点击“确定” 5、完善“用户名”和“密码”…

3.9、以太网交换机自学习和转发帧的流程

3.9、以太网交换机自学习和转发帧的流程 1.以太网交换机工作在数据链路层&#xff08;也包括物理层&#xff09; 说明&#xff1a;目前市场上也有包含网络层部分功能的交换机&#xff0c;称为三层交换机 2.以太网交换机收到帧后&#xff0c;在帧交换表中查找的目的MAC地址所…

cilantro 点云均值漂移算法(MeanShift)

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 均值漂移算法是一种非常经典的层次聚类方式,已在二维图像中得到了广泛的应用。这里我们也已二维图像为例来阐述其整个计算过程: 算法基本思想:如下图所示,左侧为实际的图像特征的分布,右侧为基于图像特征分布计…

马斯克让猴子学会意念打字!还用人脑模型演示背后原理,电线入脑清晰可见...

杨净 Pine 发自 凹非寺量子位 | 公众号 QbitAI一鸽再鸽&#xff0c;马斯克Neuralink终于官宣新进展。果然不出所料&#xff0c;与此前大家预想的意念打字相关。不过get这项技能的不是人类&#xff0c;而是他们的老朋友——猴子。根据黄色提示“指哪打哪”&#xff1a;我可以吃点…

第 04 章_逻辑架构

第 04 章_逻辑架构1. 逻辑架构剖析1. 1 服务器处理客户端请求1.2 Connectors1.3 第 1 层&#xff1a;连接层1.4 第 2 层&#xff1a;服务层1. 5 第 3 层&#xff1a;引擎层1. 6 存储层1. 7 小结2. SQL执行流程2. 1 MySQL 中的 SQL执行流程3. 优化器 &#xff1a;4. 执行器 &…

Vue3 —— 怎样利用vite创建一个vue3项目

前言 本文主要讲解如何利用vitevue创建第一个项目以及vue3的基础知识点 一、创建一个vue3项目 这里我们主要介绍如何利用 vitevue3创建项目 1.有关vite Vite&#xff08;法语意为 "快速的"&#xff0c;发音 /vit/&#xff0c;发音同 "veet"&#xff09;是…

【目标检测】Faster R-CNN论文代码复现过程解读(含源代码)

目录&#xff1a;Faster R-CNN论文代码复现过程解读Faster R-CNN代码使用说明书&#xff08;分享在github上&#xff09;一、代码的地址二、我的配置环境三、参数值文件下载四、VOC数据集下载五、模型训练步骤&#xff08;1&#xff09;训练VOC0712数据集1.数据集的准备2.数据集…

做电商太难了。。

阅读本文大概需要 1.86 分钟。上周跟在杭州做电商的朋友交流了一下&#xff0c;发现他们太难了。前些天不还有说现在全国 65% 的快递网点都停摆了&#xff0c;这对电商影响非常大&#xff0c;最直接的就是物流快递的问题&#xff0c;一堆快递堆在那里发不出去。虽然直播间卖得算…

win11 右键关闭显示更多选项 修改右键菜单

建议直接使用方法三 win11右键显示更多选项怎么关闭&#xff1f; Win11右键显示更多选项怎么关闭&#xff1f;本文将为您介绍4个简单有效的解决方法&#xff0c;您可以根据自身实际情况来挑选一个更加适合自己的方案&#xff01; 方法一&#xff1a;更改文件资源管理器选项恢…

高质量项目管理-甘特图模板+教程(附下载包)/ PMP项目管理可用

做项目管理的少不了用到甘特图&#xff0c;但项目流程那么多&#xff0c;每个都一一去做一个甘特图又需要耗费非常大的时间。所以这里给大家收集了一些甘特图模板教程&#xff0c;供大家参考学习&#xff01; 科普一下&#xff1a;甘特图&#xff08;Gantt chart&#xff09;又…

皕杰报表之隐藏处理

第一步&#xff0c;新建报表&#xff0c;然后新建参数 参数type设置成中文描述为统计类型、数据类型为字符串。 参数year设置成中文描述为年、数据类型为日期、时间日期格式为yyyy。 参数month设置成中文描述为月、数据类型为日期、时间日期格式为MM。 参数day设置成中文描…

腾讯安全在2022:出租车、地铁和爆发的火山

“它就像是一个烧锅炉的过程&#xff0c;整个过程会很漫长。但前面蒸汽没出来是没效果的&#xff0c;不可能这个锅烧两下&#xff0c;这个锅烧两下&#xff0c;最后哪个都不开。一旦确定方向&#xff0c;我们就会坚定地朝这个方向走&#xff0c;从上至下坚定生态的持续投入&…

element-tiptap和vuedraggable的拖拽冲突

今天写项目的时候&#xff0c;遇到一个问题&#xff0c;分享给大家。 场景 我有一个A区域&#xff0c;还有一个B区域。A区域内的Vue组件可以通过Vuedraggable这个框架来拖拽到B区域中。B区域内的Vue组件在标题上使用了element-tiptap组件&#xff08;用来高级编辑&#xff09…

上海发布:应对产业封锁,出台硬核政策扶持集成电路,最高奖励3000万!

上海张江科学城&#xff0c;聚集了全上海超六成集成电路企业 前 言 11月23日&#xff0c;上海市经济信息化委、市财政局发布了关于印发 《上海市集成电路和软件企业核心团队专项奖励办法》的通知。 该文件提出&#xff0c;上海市将在未来5年&#xff0c;对符合要求的集成电路和…

idea打包springboot项目成 docker 镜像方法 (详细)

idea打包springboot项目 详细方法 么有比这个更详细的了 双击package 生成.jar文件 文件生成位置如下图 将041-springboot-thymeleaf-1.0.0.jar 上传到/root/myspringboot文件夹中 默认已经安装好docker linux 操作 cd /root/myspringboot vim Dockerfile bash From openjd…

【leetcode】2273. 移除字母异位词后的结果数组(js实现)

1. 题目 https://leetcode.cn/problems/find-resultant-array-after-removing-anagrams/description/?languageTagsjavascript 2. 思路 对于每个单词&#xff0c;用哈希表统计每个字符出现的次数&#xff0c;前后两个字母进行比较。如果比较以后发现是字母异位词&#xff…

详解设计模式:策略模式

策略模式&#xff08;Strategy Pattern&#xff09;也被称为政策模式&#xff08;Policy Pattern&#xff09;&#xff0c;是在 GoF 23 种设计模式中定义了的行为型模式。 策略模式 是针对一组算法&#xff0c;将每一个算法封装到具有共同接口的独立的类中&#xff0c;使得它们…