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/503924.html

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

相关文章

Redis 数据库源码分析

Redis 数据库源码分析 我们都知道Redis是一个 <key,value> 的键值数据库&#xff0c;其实也就是一个 Map。如果让我来实现这样一个 Map&#xff0c;我肯定是用数组&#xff0c;当一个 key 来的时候&#xff0c;首先进行 hash 运算&#xff0c;接着对数据的 length 取余&…

基于YOLO11的无人机视角下羊群检测系统

基于YOLO11的无人机视角下羊群检测系统 (价格90) 包含 [sheep] 【羊】 1个类 通过PYQT构建UI界面&#xff0c;包含图片检测&#xff0c;视频检测&#xff0c;摄像头实时检测。 &#xff08;该系统可以根据数据训练出的yolo11的权重文件&#xff0c;运用在其他检测系统上…

WebRTC 在视频联网平台中的应用:开启实时通信新篇章

在当今这个以数字化为显著特征的时代浪潮之下&#xff0c;实时通信已然稳稳扎根于人们生活与工作的方方面面&#xff0c;成为了其中不可或缺的关键一环。回首日常生活&#xff0c;远程办公场景中的视频会议让分散各地的团队成员能够跨越地理距离的鸿沟&#xff0c;齐聚一堂共商…

【Go学习】-02-1-标准库:fmt、os、time

【Go学习】-02-1-标准库&#xff1a;fmt、os、time 1 fmt标准库1.1 输出1.1.1 fmt.Print1.1.2 格式化占位符1.1.2.1 通用占位符1.1.2.2 布尔型1.1.2.3 整型1.1.2.4 浮点数与复数1.1.2.5 字符串和[]byte1.1.2.6 指针1.1.2.7 宽度标识符1.1.2.8 其他flag 1.1.3 Fprint1.1.4 Sprin…

快速入门Spring Cloud Alibaba,轻松玩转微服务

​ 1 快速入门Spring Cloud Alibaba&#xff0c;轻松玩转微服务 1.1 架构 架构图&#xff1a; 1.2 项目结构 1.2.1 系统框架版本 版本适配查看&#xff1a;https://sca.aliyun.com/docs/2023/overview/version-explain/ Spring Boot Version &#xff1a;3.2.4 Spring Clo…

腾讯云AI代码助手-每日清单助手

作品简介 每日清单助手是一款可以记录生活的小程序&#xff0c;在人们需要记录时使用&#xff0c;所以根据这个需求来创建的这款应用工具&#xff0c;使用的是腾讯云AI代码助手来生成的所有代码&#xff0c;使用方便&#xff0c;快捷&#xff0c;高效。 技术架构 python语言…

Pytorch学习12_最大池化的使用

输入图像 import torch from torch import nninputtorch.tensor([[1,2,0,3,1],[0,1,2,3,1],[1,2,1,0,0],[5,2,3,1,1],[2,1,0,1,1]]) inputtorch.reshape(input,(-1,1,5,5))#二维张量转换为一个四维张量。(batch_size, channels, height, width)print(input.shape)ceil_modeTrue…

009:传统计算机视觉之边缘检测

本文为合集收录&#xff0c;欢迎查看合集/专栏链接进行全部合集的系统学习。 合集完整版请参考这里。 本节来看一个利用传统计算机视觉方法来实现图片边缘检测的方法。 什么是边缘检测&#xff1f; 边缘检测是通过一些算法来识别图像中物体之间或者物体与背景之间的边界&…

HarmonyOS Next系列之华为账号一键登录功能实现(十四)

系列文章目录 HarmonyOS Next 系列之省市区弹窗选择器实现&#xff08;一&#xff09; HarmonyOS Next 系列之验证码输入组件实现&#xff08;二&#xff09; HarmonyOS Next 系列之底部标签栏TabBar实现&#xff08;三&#xff09; HarmonyOS Next 系列之HTTP请求封装和Token…

大数据架构设计:数据分层治理的全景指南

大数据架构设计&#xff1a;数据分层治理的全景指南 在大数据架构中&#xff0c;数据分层治理是一种被广泛采用的设计模式&#xff0c;其核心目的是为数据赋予结构化管理的能力&#xff0c;降低复杂度&#xff0c;并为数据的多样化使用场景提供保障。在这篇文章中&#xff0c;…

unity学习14:unity里的C#脚本的几个基本生命周期方法, 脚本次序order等

目录 1 初始的C# 脚本 1.1 初始的C# 脚本 1.2 创建时2个默认的方法 2 常用的几个生命周期方法 2.1 脚本的生命周期 2.1.1 其中FixedUpdate 方法 的时间间隔&#xff0c;是在这设置的 2.2 c#的基本语法别搞混 2.2.1 基本的语法 2.2.2 内置的方法名&#xff0c;要求更严…

Ubuntu中使用miniconda安装R和R包devtools

安装devtools环境包 sudo apt-get install gfortran -y sudo apt-get install build-essential -y sudo apt-get install libxt-dev -y sudo apt-get install libcurl4-openssl-dev -y sudo apt-get install libxml2.6-dev -y sudo apt-get install libssl-dev -y sudo apt-g…

如何在 Windows 10/11 上录制带有音频的屏幕 [3 种简单方法]

无论您是在上在线课程还是参加在线会议&#xff0c;您都可能需要在 Windows 10/11 上录制带有音频的屏幕。互联网上提供了多种可选方法。在这里&#xff0c;本博客收集了 3 种最简单的方法来指导您如何在 Windows 10/11 上使用音频进行屏幕录制。请继续阅读以探索&#xff01; …

Python 中几个库的安装与测试

一、jupyter 安装步骤 确保系统已经安装了Python&#xff08;建议 Python 3.6 及以上版本&#xff09;。点击WinR输入cdm进入命令提示符窗口&#xff0c;然后输入pip install jupyter&#xff0c;按下回车键。等待安装过程完成。安装过程中&#xff0c;你会看到命令行输出安装…

【阅读笔记】基于FPGA的红外图像二阶牛顿插值算法的实现

图像缩放技术在图像显示、传输、分析等多个领域中扮演着重要角色。随着数字图像处理技术的发展&#xff0c;对图像缩放质量的要求也越来越高。二阶牛顿插值因其在处理图像时能够较好地保持边缘特征和减少细节模糊&#xff0c;成为了图像缩放中的一个研究热点。 一、 二阶牛顿插…

5.1 数据库:INSERT 插入语句

工作中增删改查这四类sql语句里边用的最多的就是查询语句。因为绝大多数的软件系统都是读多写少的&#xff0c;而且查询的条件也是各种各样。本节课程我们来学习下一个DML语句&#xff0c;那就是向数据表里面写入记录的insert语句。Insert语句是可以向数据表里边写入&#xff0…

【 算法设计与分析-回顾算法知识点】福建师范大学数学与计算机科学学院 2006 — 2007学年第二学期考试 A 卷

一&#xff0e;填空题&#xff08;每空2分&#xff0c;共30分&#xff09; 1&#xff0e;算法的时间复杂性指算法中 元运算 的执行次数。 2&#xff0e;在忽略常数因子的情况下&#xff0c;O、和三个符号中&#xff0c; O 提供了算法运行时间的一个上界。 3&#xff0e;设Dn…

嵌入式技术之Linux(Ubuntu) 一

一、Linux入门 1.硬件和操作系统以及用户的关系 一个传感器&#xff0c;获得数据后&#xff0c;需要向服务器发送数据。传感器传数据给上位机。 上位机需要一个程序来接收数据&#xff0c;那么这个上位机是什么机器&#xff1f; 我们的笔记本电脑就可以当成上位机。 两个手…

Flink系统知识讲解之:如何识别反压的源头

Flink系统知识之&#xff1a;如何识别反压的源头 什么是反压 Ufuk Celebi 在一篇古老但仍然准确的文章中对此做了很好的解释。如果您不熟悉这个概念&#xff0c;强烈推荐您阅读这篇文章。如果想更深入、更低层次地了解该主题以及 Flink 网络协议栈的工作原理&#xff0c;这里有…

浙江安吉成新的分布式光伏发电项目应用

摘 要&#xff1a;分布式光伏发电站是指将光伏发电组件安装在用户的建筑物屋顶、空地或其他适合的场地上&#xff0c;利用太阳能进行发电的一种可再生能源利用方式&#xff0c;与传统的大型集中式光伏电站相比&#xff0c;分布式光伏发电具有更灵活的布局、更低的建设成本和更高…