Unity Burst详解

【简介】

Burst是Unity的编译优化技术,优化了从C#代码编译成Native代码的过程,经过编译优化后代码有更高的运行效率。

在Unity中使用Burst很简单,在方法或类前加上[BurstCompile]特性即可。在构建时编译代码的步骤,Burst编译器会识别该特性对方法或类做编译优化。其适用于高性能计算的场景,逻辑复杂的场景不适用。

Burst编译的实现得益于已有的SIMD和LLVM技术。

【SIMD】

在现代 CPU 中,并行性操作大致分为三种类型:

  • 指令级并行,主要由 cpu 流水线技术,乱序执行技术等技术完成
  • 线程级并行,主要依靠多核多线程技术实现
  • 数据级并行,主要依靠 SIMD (单指令多数据) 来实现

SIMD是CPU硬件设计的一部分,是的CPU可以同时对多个数据执行相同的操作。

指令执行时(指令由操作码和操作数构成)CPU先访问缓存,缓存分为指令缓存和数据缓存,如果缓存中有指令就读取,没有指令从内存中读取;读取数据的过程也类似。

以加法为例,对于5+2这个加法计算,最少需要四条指令:

  1. 将数值 5 加载到寄存器中(LOAD操作码)
  2. 将数值 2 加载到寄存器中(LOAD操作码)
  3. 将两个寄存器中的数值相加(ADD操作码)
  4. 将相加后的结果存储到指定的寄存器或内存中(STORE操作码)

在SISD(单指令单数据)中,每个指令只会取一次数据,而在SIMD(单指令多数据)中,一次指令会取多个数据,节省了CPU获取数据的时间。

一次性取出来的数放在向量寄存器中,但向量寄存器大小有限,在AVX指令集中有256位。

在C#中,float类型占64位,一般要4个float类型一组。

现代编译器有三种方式来支持 SIMD:

  • 编译器能够在没有用户干预的情况下生成支持使用硬件SIMD的代码,称之为自动矢量化
  • 通过使用的Intrinsics 函数实现 SIMD
  • 使用矢量 C++ 类 (仅限ICC编译器) 来实现 SIMD

(Intrinsics函数是一种内建函数,它们用于实现高级别的底层操作。这些函数通常由编译器提供,并且可以直接映射到特定的硬件指令。使用Intrinsics函数可以实现对特定硬件功能的直接访问,从而提高代码的性能和效率。

内联函数通常用关键字inline声明,是由编译器处理的普通函数,编译器会根据需要将函数内容直接插入到调用处,减少了函数调用的开销。而Intrinsics函数一般不需要显式声明,编译器会自动识别并将其优化为特定的硬件指令 )

Unity.Mathematics提供了支持SIMD的数据类型,例如float4/int4等类型,在Job中需要使用这些数据类型。

在Job中要多用float4类型才有效,例如有一个float类型的数组,可以转为float4类型的数组,有利于在循环计算时自动矢量化。

【LLVM】

传统编译器架构为:

frontEnd(前端)检查源代码是否存在错误,将源代码分析成词法单元,然后进行语法分析生成抽象语法树,生成中间IR语言

Optimizer(优化) 对中间IR语言进行优化,消除冗余计算,内联、变量折叠等

BackEnd(后端) 最终将IR中间语言生成目标机器所能执行的代码

这种问题在于不同语言都要有各自的编译器和优化手段,LLVM期望提供一种IR标准,不同语言经过编译后先生成LLVM IR语言,只需要针对其做优化即可。

新增一个语言时,只需新实现一个前端,新增一种设备后,只需新实现一个后端

BurstCompiler会根据特性找到需要编译的方法,将方法对应的C# IR转为LVVM IR,随后针对LVVM IR做优化,编译。

【Burst使用】

支持的类型和语法

可以简单的将BurstCompile特性至于方法或类上,但不是所有的方法和类都支持。情况如下:

  • 支持基元类型:bool/byte/int/long/float/double,不支持char、string、decimal
  • 支持Unity.Mathematics中的向量类型,例如bool3\bool4\int3\int4\float3\float4等
  • 支持枚举类型、结构体、元组、System.IntPtr、Span<T>
  • 支持DllImport and internal calls 
  • 不支持Managed Array,例如int[] a;支持NativeArray
  • 方法中不能引用managed object
  • 不支持Try Catch语法

打Log

代码中Log是少不了的,Burst对Debug.Log有额外支持,例如:

Debug.Log("This a string literal");int value = 256;
Debug.Log($"This is an integer value {value}"); //string需要使用FixedString,例如:
FixedString128Bytes str = "fixedstring128";
Debug.Log(str);

 编译检查

为避免在构建时才发现Burst编译不过,提供了Burst Inspector可以在Editor下预编译,以便查看编译结果

通过Jobs > Burst > Open Inspector 打开可视化面板,面板会显示编译结果

面板左边显示了可以正常编译得Job,右边显示当前选中的Job的编译结果,依次是:

  • Assembly:最终优化生成的NativeCode
  • .NET IL:原始的C# Job代码生成的IL
  • LLVM IR (Unoptimized) :未优化的LLVM IR
  • LLVM IR (Optimized):优化后的LLVM IR
  • LLVM IR Optimization Diagnostics:提供优化诊断细节

舍弃编译

当在类或结构体添加BurstCompile特性后,默认对其内所有方法做编译,如果某个方法我们使用了Managed Object而不想编译,可以使用[BurstDiscard]特性。

注意,使用该特性时,方法不能有返回值,可以通过ref或者out传递返回值

同步编译

Editor上Job是默认异步编译的,首次执行到Job时才会异步编译。通过[BurstCompile(CompileSynchronously = true)]开启同步编译

精度设定

浮点数精度会影响计算性能,默认采用中等精度,可以通过[BurstCompile(FloatPrecision.Med, FloatMode.Fast)]指定精度

指定取值范围

对参数和返回值指定取值范围有利于编译器做特定的代码优化,例如

[return:AssumeRange(0u, 13u)]
static uint WithConstrainedRange([AssumeRange(0, 26)] int x)
{return (uint)x / 2u;
}

分支指定

 可以通过Unity.Burst.CompilerServices.Hint.Likely告诉编译器该分支大概率为true,需要重点优化,例如

if (Unity.Burst.CompilerServices.Hint.Likely(b))
{// Any code in here will be optimized by Burst with the assumption that we'll probably get here!
}
else
{// Whereas the code in here will be kept out of the way of the optimizer.
}

【参考】

深入浅出让你理解什么是LLVM - 简书

https://zhuanlan.zhihu.com/p/472813616

Quick Start | Burst | 1.7.4

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

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

相关文章

【经典神经网络架构解析篇】【1】LeNet网络详解:模型结构解析、优点、实现代码

《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发】2.【车牌识别与自动收费管理系统开发】3.【手势识别系统开发】4.【人脸面部活体检测系统开发】5.【图片风格快速迁移软件开发】6.【人脸表表情识别系统】7.【…

数据结构之双向链表

目录 双向链表的基本概念和结构 初始化 尾插 头插 尾删 头删 查找 在指定位置之后插入 删除指定位置节点 判空 销毁 完整代码 测试代码 双向链表的基本概念和结构 双向链表&#xff08;Doubly Linked List&#xff09;‌是一种链式存储结构&#xff0c;每个节点除…

[程序设计]—代理模式

[程序设计]—代理模式&#x1f473; 本文章记录学习于——52.面向切面&#xff1a;AOP-场景模拟_哔哩哔哩_bilibili 最近闲来无事&#xff0c;在学习Spring的源码&#xff1a; 后面慢慢更新源码系列blog&#xff0c;希望多多关注&#x1f64f;&#x1f64f; 目前已经总结的b…

网易云音乐登录两部手机:IP属地归属何方?

在数字化生活日益普及的今天&#xff0c;音乐平台成为了我们日常娱乐不可或缺的一部分。网易云音乐&#xff0c;作为众多音乐爱好者的首选&#xff0c;其丰富的音乐资源和个性化的推荐算法深受用户喜爱。然而&#xff0c;随着多设备登录成为常态&#xff0c;一个问题也随之浮现…

spark汇总

目录 描述运行模式1. Windows模式代码示例 2. Local模式3. Standalone模式 RDD描述特性RDD创建代码示例&#xff08;并行化创建&#xff09;代码示例&#xff08;读取外部数据&#xff09;代码示例&#xff08;读取目录下的所有文件&#xff09; 算子DAGSparkSQLSparkStreaming…

SQL多表联查、自定义函数(字符串分割split)、xml格式输出

记录一个报表的统计&#xff0c;大概内容如下&#xff1a; 多表联查涉及的报表有&#xff1a;房间表、买家表、合同表、交易表、费用表、修改记录表 注意&#xff1a;本项目数据库使用的是sqlserver&#xff08;mssql&#xff09;&#xff0c;非mysql。 难点1:业主信息&#…

实用操作系统学习笔记

第1章 操作系统概述 操作系统基本概念 【基础知识】 操作系统&#xff1a;控制和管理整个计算机系统的硬件和软件资源&#xff0c;合理地组织、调度计算机的工作与资源的分配&#xff0c;进而为用户和其他软件提供方便接口与环境的程序集合。操作系统是计算机系统中最基本的…

硬件设计-齐纳管

目录 摘要 详情 齐纳管的工作电流、 摘要 齐纳管&#xff08;Zener Diode&#xff09;是一种特殊的二极管&#xff0c;它能够在特定的反向电压下保持电流稳定。正常情况下&#xff0c;二极管只允许正向电流通过&#xff0c;而阻止反向电流流过。而齐纳管在一定的反向电压下可…

linux网络 | https前置知识 | 数据加密与解密、数据摘要

前言:本节内容讲述https的相关内容。 https博主会着重讲解https如何让一个请求和一个响应能够安全的进行交互。 https博主将用两篇文章进行讲解。本篇是两篇中第一篇。会把http的安全问题引出来&#xff0c; 然后说一下https的基本解决方法。 下面废话不多说&#xff0c; 开始我…

小目标检测难点分析和解决策略

目录 一、背景 二、检测难点 三、主流改进方法 3.1 基于改进数据增强的小目标检测算法 3.1.1 监督数据增强方法 3.1.2 无监督数据增强方法 3.2. 基于改进特征提取的小目标检测算法 3.2.1. 扩张卷积 3.2.2. 特征增强 3.2.3. 多尺度特征提取 3.2.4. 注意力机制 3.3 基…

Java 继承

目录 1. 继承概述 2. 继承好处 3. 继承格式 4. 继承规定 5. debug 调试 6. 方法重写 6.1 概述 6.2 规定 7. super 关键字 7.1 概述 7.2 使用 7.3 在构造器中使用 8. 子类对象实例化的全过程 9. 练习 1. 继承概述 举例&#xff1a;Person 类中有name&#xff0c…

CES Asia 2025科技盛宴,AI智能体成焦点

2025第七届亚洲消费电子技术展&#xff08;CES Asia赛逸展&#xff09;将在北京拉开帷幕&#xff0c;AI智能体有望成为展会的核心亮点。 深圳市人工智能行业协会发文表示全力支持CES Asia 2025&#xff08;赛逸展&#xff09;&#xff0c;称其为人工智能领域的创新发展提供了强…

HTMLHTML5革命:构建现代网页的终极指南 - 0. 课程目录设计

结构清晰&#xff0c;层层递进 课程从基础知识&#xff08;如HTML学前必知&#xff09;开始&#xff0c;逐步深入到高级应用&#xff08;如PWA配置和WebApp优化&#xff09;。每个模块都有明确的目标&#xff0c;适合零基础学员逐步掌握HTML。 覆盖范围广 这套课程涵盖了HTM…

大型语言模型(LLM)中的tokens是什么

大型语言模型(LLM)中的tokens是什么 在大型语言模型(LLM)中,tokens是文本处理的基本单位,它可以是一个单词、一个字符、一个标点符号,或者是一个特殊的标记。以下是关于tokens的详细介绍及举例: 一、tokens的定义和作用 定义:tokens是将文本分割成的一个个有意义的…

嵌入式C语言:二维数组

目录 一、二维数组的定义 二、内存布局 2.1. 内存布局特点 2.2. 内存布局示例 2.2.1. 数组元素地址 2.2.2. 内存布局图&#xff08;简化表示&#xff09; 2.3. 初始化对内存布局的影响 三、访问二维数组元素 3.1. 常规下标访问方式 3.2. 通过指针访问 3.2.1. 指向数…

Java进阶-在Ubuntu上部署SpringBoot应用

随着云计算和容器化技术的普及&#xff0c;Linux 服务器已成为部署 Web 应用程序的主流平台之一。Java 作为一种跨平台的编程语言&#xff0c;具有广泛的应用场景。本文将详细介绍如何在 Ubuntu 服务器上部署 Java 应用&#xff0c;包括环境准备、应用发布、配置反向代理&#…

node-sass@4.14.1报错的最终解决方案分享

输入npm i全安装文件所需的依赖的时候&#xff0c;博主是使用sass去书写的&#xff0c;使用的是node-sass4.14.1和sass-loader7.3.1的版本的&#xff0c;安装的时候老是出现错误&#xff0c; node-sass4.14.1版本不再被支持的原因 node-sass 是一个基于 LibSass 的 Node.js 绑…

Java设计模式 —— 【行为型模式】命令模式(Command Pattern) 详解

文章目录 模式介绍优缺点适用场景结构案例实现注意事项 模式介绍 有时候需要向某些对象发送请求&#xff0c;但是并不知道请求的接收者是谁&#xff0c;也不知道被请求的操作是什么。此时希望用一种松耦合的方式来设计程序&#xff0c;使得请求发送者和请求接收者能够消除彼此…

Vue3初学之组件通信

一起进行学习&#xff1a; 在 Vue 3 中&#xff0c;组件通信是一个非常重要的概念&#xff0c;它决定了如何在父子组件之间、兄弟组件之间以及跨层级组件之间传递数据和事件。以下是 Vue 3 中常见的组件通信方式&#xff1a; 父子组件通信 1.1 父组件向子组件传递数据&#x…

springBoot整合ELK Windowsb版本 (elasticsearch+logstash+kibana)

springBoot整合ELK Windowsb版本 【elasticsearchlogstashkibana】 下载软件启动服务1、elasticsearch2、kibana3、logstash 集成springboot1、添加依赖2、在logback.xml添加相关配置3、修改logstash 配置4、重启logstash 最后测试 下载软件 elasticsearch 官网 https://www.…