Metal入门学习:GPU并行计算大数组相加
一、编程指南PDF下载链接(中英文档)
-
1、Metal编程指南PDF链接
https://github.com/dennie-lee/ios_tech_record/raw/main/Metal学习PDF/Metal 编程指南.pdf -
2、Metal着色语言(Metal Shader Language:简称MSL)编程指南PDF链接
https://github.com/dennie-lee/ios_tech_record/raw/main/Metal学习PDF/Metal 着色语言指南.pdf -
3、补充:官网API文档链接
https://developer.apple.com/documentation/metal/performing_calculations_on_a_gpu
二、内容前述
本文章通过元素个数相同的两个数组对应位置相加来切入Metal(GPU)的并行计算着色函数(本篇文章未涉及渲染函数:顶点着色函数和片元着色函数,会另起一篇文章介绍)。在此示例中,可以了解所有 Metal 应用程序中使用的基本任务。 您将看到如何将用 C 编写的简单函数转换为Metal着色语言 (Metal Shader Language :MSL),以便它可以在 GPU 上运行。通过创建管道,准备MSL函数在其上运行,并创建GPU可访问的数据对象。要针对您的数据执行管道,创建命令缓冲区,将命令写入其中,然后将缓冲区提交到命令队列,Metal将命令发送到GPU执行。
(下图是官网并行计算着色函数流程原理图:)

三、C语言和MSL语言对两个数组相加的函数对比
- 1、C语言函数:两个数组相加
void add_arrays(const float* inA,const float* inB,float* result,int length){for (int index = 0; index < length ; index++){result[index] = inA[index] + inB[index];}
}
- 2、MSL语言函数:两个数组相加
kernel void add_arrays(device const float* inA,device const float* inB,device float* result,uint index [[thread_position_in_grid]]){result[index] = inA[index] + inB[index];
}
关键词解释说明(在MSL编程指南PDF中可查看,点击上面的链接下载即可)

[[thread_position_in_grid]]文档中也有,更加详细的解析说明可查看这篇文章:https://juejin.cn/post/7085633906501746724,文章中还有延伸说明解释[[threadgroup_position_in_grid]]和[[threads_per_threadgroup]]
四、关键代码段解析
- 1、初始化、加载扩展名为.metal的文件、创建管道状态对象加载并行计算着色函数
//_mDevice = MTLCreateSystemDefaultDevice();
// Load the shader files with a .metal file extension in the project
id<MTLLibrary> newDefaultLibrary = [_mDevice newDefaultLibrary];
if (newDefaultLibrary == nil){NSLog(@"Failed to find the default library");return nil;
}id<MTLFunction> newFunction = [newDefaultLibrary newFunctionWithName:@"add_arrays"];
if (newFunction == nil){NSLog(@"Failed to find the adder function");return nil;
}NSError *error;
// Create a compute pipeline state object.
//根据扩展名为.metal文件中kernel定义的函数创建计算管道(项目Add文件)
_mAddFunctionPSO = [_mDevice newComputePipelineStateWithFunction:newFunction error:&error];
if (_mAddFunctionPSO == nil){// If the Metal API validation is enabled, you can find out more information about what// went wrong. (Metal API validation is enabled by default when a debug build is run// from Xcode)NSLog(@"Failed to create pipeline state object,error : %@)",error);return nil;
}// 指令队列
_mCommandQueue = [_mDevice newCommandQueue];
if (_mCommandQueue == nil){NSLog(@"Failed to find command queue");return nil;
}
- 2、初始化数组数据
//初始化数组数据
- (void)prepareData{_mBufferA = [_mDevice newBufferWithLength:bufferSize options:MTLResourceStorageModeShared];_mBufferB = [_mDevice newBufferWithLength:bufferSize options:MTLResourceStorageModeShared];_mBufferResult = [_mDevice newBufferWithLength:bufferSize options:MTLResourceStorageModeShared];[self generateRandomFloatData:_mBufferA];[self generateRandomFloatData:_mBufferB];
}- (void)generateRandomFloatData:(id<MTLBuffer>)buffer{float *dataPtr = buffer.contents;for (int index = 0; index < arrayLength; index++){dataPtr[index] = (float)rand() / (float)RAND_MAX;}
}
- 3、指令参数添加,提交GPU计算
- (void)sendComputeCommand{//create a command buffer to hold commands//创建指令缓存冲区id<MTLCommandBuffer> commandBuffer = [_mCommandQueue commandBuffer];assert(commandBuffer != nil);//开始进行指令添加参数id<MTLComputeCommandEncoder> computeEncoder = [commandBuffer computeCommandEncoder];assert(computeEncoder != nil);NSTimeInterval startTimeInterval = [[[NSDate alloc] init] timeIntervalSince1970];[self encodeAdderCommand:computeEncoder];//添加参数完毕,[computeEncoder endEncoding];//提交执行指令[commandBuffer commit];//等待计算完毕[commandBuffer waitUntilCompleted];NSTimeInterval endTimeInterval = [[[NSDate alloc] init] timeIntervalSince1970];NSLog(@"长度为:%u 的两个数组相加(Metal方式)花费的时间:%f",arrayLength,(endTimeInterval - startTimeInterval));//验证计算结果[self verifyResults];
}- (void)encodeAdderCommand:(id<MTLComputeCommandEncoder>)computeEncoder{//encode pipeline state object and its parameters[computeEncoder setComputePipelineState:_mAddFunctionPSO];//此处的atIndex为0,与MSL函数中参数对应顺序对应(也可以设置buffer(0),此处可先忽略buffer,详细信息可查看着色语言编程指南PDF)[computeEncoder setBuffer:_mBufferA offset:0 atIndex:0];//此处的atIndex为1,与MSL函数中参数对应顺序对应(也可以设置buffer(1),此处可先忽略buffer,详细信息可查看着色语言编程指南PDF)[computeEncoder setBuffer:_mBufferB offset:0 atIndex:1];//此处的atIndex为1,与MSL函数中参数对应顺序对应(也可以设置buffer(2),此处可先忽略buffer,详细信息可查看着色语言编程指南PDF)[computeEncoder setBuffer:_mBufferResult offset:0 atIndex:2];//全部线程数量,此处对应[[thread_position_in_grid]],理解此处请看第三.2对应关键词解释的文章MTLSize gridSize = MTLSizeMake(arrayLength, 1, 1);NSUInteger threadGroupSize = _mAddFunctionPSO.maxTotalThreadsPerThreadgroup;if (threadGroupSize > arrayLength){threadGroupSize = arrayLength;}//线程组大小MTLSize threadGroupsize = MTLSizeMake(threadGroupSize, 1, 1);[computeEncoder dispatchThreads:gridSize threadsPerThreadgroup:threadGroupsize];
}
五、完整代码
例子:github链接:https://github.com/dennie-lee/MetalArrayAddDemo
相关文章:
Metal入门学习:GPU并行计算大数组相加
一、编程指南PDF下载链接(中英文档) 1、Metal编程指南PDF链接 https://github.com/dennie-lee/ios_tech_record/raw/main/Metal学习PDF/Metal 编程指南.pdf 2、Metal着色语言(Metal Shader Language:简称MSL)编程指南PDF链接 https://github.com/dennie-lee/ios_te…...
关于在spyder,jupyter notebook下创建虚拟环境(pytorch,tensorflow)均有效
anaconda下载地址 https://www.anaconda.com/download/ 下载完成后打开anaconda目录下的 anaconda prompt 在命令行中输入下面的命令创建一个叫tf2.0的虚拟环境(“tf2.0”是建立的Conda虚拟环境的名字,可以自拟) conda create -n tf2.0 p…...
oracle 闪回恢复
oracle 闪回恢复 闪回恢复区主要通过3个初始化参数来设置和管理: db_recovery_file_dest:指定闪回恢复区的位置 db_recovery_file_dest_size:指定闪回恢复区的可用空间大小 db_flashback_retention_target:指定数据库可以回退的时…...
LeetCode 322 零钱兑换
题目: 给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1 。你可以认为每种硬币的数量…...
面试篇SpringMVC是什么以及工作原理
1,什么是SpringMVC呢? 它是Spring的一种设计模式,一款框架。 2,MVC分别代表什么? M代表模型即model的缩写,指业务逻辑层模型。V代表视图即View的缩写,指视图层。C则是controller的缩写ÿ…...
jQuery-层级选择器
<!DOCTYPE HTML> <html> <head> <meta http-equiv"Content-Type" content"text/html; charsetUTF-8"> <title>层级选择器</title> <style type"text/css"> …...
【Java数据结构】——第十节(下).选择排序与堆排序
作者简介:大家好,我是未央; 博客首页:未央.303 系列专栏:Java初阶数据结构 每日一句:人的一生,可以有所作为的时机只有一次,那就是现在!!! 文章目…...
45道SQL题目陆续更新
文章目录 学习视频配置环境第一天内连接 外连接第二天第三天 学习视频 学习视频 配置环境 四张表 配置四张表的sql语句 #创建发据库 create database frogdata charsetutf8;use frogdata;# 学生表 Student create table Student( SId varchar(10), Sname var…...
在线PS软件有哪些不错的推荐
许多新的UI设计合作伙伴非常关心在线ps工具的选择。现在市场上有各种各样的ps网页替代工具,数量众多,令人眼花缭乱。本文简要介绍了10个在线PS工具,我相信一定有一个适合你! 1.即时设计 即时设计是一款在线 UI 设计工具…...
Java实现天气预报功能
如果要实现类似百度天气、手机App这样的天气预报功能该如何实现?首先想到的是百度... 背景: 最近公司做了一个项目,天气预报的功能也做上去了,不仅有实时天气、未来7天预报的功能、还有气象预警的功能。 天气包括基本天气、白天夜…...
python循环语句
while循环 Python中,while循环只要在条件(表达式)为真的情况下,就会一直重复执行相应的循环代码块。 while语句的语法格式如下: while 条件表达式:代码块while语句执行的具体流程为:首先判断…...
多线程基础(一)线程基础信息、synchronized 锁概念
1. 基本概念: 程序: 程序是一些保存在磁盘上的指令的有序集合,是静态的。程序包括:内存资源、IO资源、信号处理等。(如:XX.exe) 进程: 进程是程序执行的过程,包括了动态…...
JAVA期末考内容知识点的梳理
作者的话 前言:这些都是很基本的,还有很多没有写出来,重点在于考试复习,包括后四章的内容 前面内容请参考JAVA阶段考内容知识点的梳理 一、集合、流 课堂总结1集合 集合概念: 保存和盛装数据的容器,将许多…...
为什么要使用Thrift与Protocol Buffers?
编码数据的格式 程序通常(至少)使用两种形式的数据: 在内存中,数据保存在对象、结构体、列表、数组、散列表、树等中。 这些数据结构针对 CPU 的高效访问和操作进行了优化(通常使用指针)。如果要将数据写…...
oa是什么意思?oa系统哪个好用?
一、oa是什么意思 oa(Office Automation办公自动化)是一种将智能化科技应用于企业管理中的应用系统。它可以通过电脑网络、互联网等技术手段,将企业的各种业务流程、各种业务数据进行集成和处理,将各种业务流程和各种业务数据统一…...
Linq和C# Lambda表达式
什么是Linq 简介 Linq (Language Integrated Query) 是一种语言集成的查询技术,可以在C#和其他.NET语言中使用。Linq允许我们使用一种类SQL的语言来查询数据,这使得代码更加简洁和易于阅读。Linq提供了一种通用的查询接口,可以用于查询各种…...
蓝桥:前端开发笔面必刷题——Day2 数组(三)
文章目录 📋前言🎯两数之和 II📚题目内容✅解答 🎯移除元素📚题目内容✅解答 🎯有序数组的平方📚题目内容✅解答 🎯三数之和📚题目内容✅解答 📝最后 &#x…...
人工智能专栏第四讲——人工智能的未来展望与机遇
目录 一、人工智能的未来展望 二、人工智能在各领域的应用 三、人工智能的机遇 四、总结...
Unity阴影(Shadow)、Shadowmap
Unity阴影(Shadow) 在Unity中,阴影(Shadow)是用于模拟场景中物体之间相互遮挡和光照效果的特性。阴影可以增加场景的真实感,并在视觉上提供深度和空间感。 Unity提供了几种阴影投射和接收的方法和技术&am…...
编程语言的四种错误处理方法,你知道几种?
错误处理是编程的一个基本要素。除非你写的是“hello world”,否则就必须处理代码中的错误。在本文中,我将讨论各种编程语言在处理错误时使用的最常见的四种方法,并分析它们的优缺点。 关注不同设计方案的语法、代码可读性、演变过程、运行效…...
如何快速使用Diff Checker:面向初学者的完整文本对比指南
如何快速使用Diff Checker:面向初学者的完整文本对比指南 【免费下载链接】diff-checker Desktop application to compare text differences between two files (Windows, Mac, Linux) 项目地址: https://gitcode.com/gh_mirrors/di/diff-checker 你是否经常…...
高通Camera开发实战:ION内存与DMA-BUF的跨进程共享机制详解
高通Camera开发实战:ION内存与DMA-BUF的跨进程共享机制详解 在移动影像系统的开发中,内存管理始终是性能优化的核心战场。当Camera HAL层需要处理4K60fps视频流或超高分辨率连拍时,传统的内存拷贝方式会带来难以忍受的性能损耗。ION内存分配器…...
【VS Code】settings.json配置实战:全局与工作区设置的灵活切换技巧
1. 理解VS Code的配置层级体系 第一次用VS Code时,我就被它的配置系统惊艳到了。不像其他编辑器把配置藏在注册表或系统深处,VS Code把所有设置都明明白白放在settings.json文件里。但更厉害的是它的双层配置设计——就像手机有系统级设置和APP单独设置…...
极域电子教室破解终极指南:如何用JiYuTrainer重获电脑控制权
极域电子教室破解终极指南:如何用JiYuTrainer重获电脑控制权 【免费下载链接】JiYuTrainer 极域电子教室防控制软件, StudenMain.exe 破解 项目地址: https://gitcode.com/gh_mirrors/ji/JiYuTrainer 还在为课堂上的全屏广播而苦恼吗?当老师开启极…...
从点外卖到银行转账:用生活案例理解数据流图(DFD)在系统架构设计中的应用
从点外卖到银行转账:用生活案例理解数据流图在系统设计中的应用 中午12点,你打开外卖APP选了一份黄焖鸡米饭,点击支付后,商家接单、骑手取餐、最终送达——这个看似简单的流程背后,隐藏着一个精密的数据流动网络。就像…...
终极指南:如何用 Ice 重新定义 macOS 菜单栏使用体验
终极指南:如何用 Ice 重新定义 macOS 菜单栏使用体验 【免费下载链接】Ice Powerful menu bar manager for macOS 项目地址: https://gitcode.com/GitHub_Trending/ice/Ice 你是否曾经因为 Mac 顶部菜单栏过于拥挤而感到烦躁?那些不断堆积的应用图…...
Graphormer部署案例:科研云平台中Graphormer作为标准化AI分子服务模块
Graphormer部署案例:科研云平台中Graphormer作为标准化AI分子服务模块 1. 项目概述 Graphormer是一种基于纯Transformer架构的图神经网络模型,专门为分子图(原子-键结构)的全局结构建模与属性预测而设计。该模型在OGB、PCQM4M等…...
【电机】深入解析无刷直流电机BLDC的工作原理与性能优势
1. 无刷直流电机BLDC的革新性设计 第一次拆解无刷电机时,我被它的精巧结构震撼到了——传统有刷电机里那些容易磨损的碳刷和换向器完全消失了,取而代之的是三个呈星形排列的线圈和一组永磁体。这种将"电刷物理接触"变为"电子换向"的…...
AWS CDN 配置:实现非 www 域名自动跳转到 www.xxx.com
1. 为什么需要将非 www 域名跳转到 www 域名? 很多网站在运营过程中都会遇到一个经典问题:用户可能通过带 www 的域名(如 www.example.com)访问,也可能直接输入不带 www 的域名(如 example.com)…...
Vue3 + TypeScript 实战:从 React 视角理解类型系统的10个关键差异
一、前言 在 2026 年的软件开发中,Vue3 已经成为每一位工程师必须掌握的技能。无论是构建高性能后端服务、开发响应式前端界面,还是维护生产级服务器集群,这项技术都在其中扮演着关键角色。 很多开发者在入门阶段会遇到一个普遍问题&#x…...
