当前位置: 首页 > news >正文

[Unity Sentis] Unity Sentis 详细步骤工作流程

文章目录

  • 1. 导入模型文件
    • 支持的模型
    • 创建运行时模型
    • 导入错误
  • 2. 为模型创建输入
    • 将数组转换为张量
    • 创建多个输入
    • 进行操作
  • 3. 创建一个引擎来运行模型
    • 创建一个Worker
    • 后端类型
  • 4. 运行模型
  • 5. 获取模型的输出
    • 获取张量输出
    • 多个输出
    • 打印输出

1. 导入模型文件

要导入 ONNX 模型文件,请将文件从计算机拖到“Project”窗口的“Assets”文件夹中。

如果您的模型有外部权重文件,请将它们放在与模型文件相同的目录中,以便 Sentis 自动导入它们。

支持的模型

您可以导入 opset 版本在 7 到 15 之间的大多数 ONNX 模型文件。低于 7 或高于 15 的版本可能仍会导入 Sentis,但您可能会得到意外结果。

Sentis 不支持以下内容:

  • 使用超过 8 个维度的张量的模型。
  • 稀疏输入张量或常数。
  • String张量。
  • 复数张量。

Sentis 还将一些张量数据类型(如布尔值)转换为浮点数或整数。这可能会增加模型使用的内存。

当您导入模型文件时,Sentis 会优化模型。有关详细信息,请参阅了解 Sentis 中的模型。

创建运行时模型

要使用导入的模型,必须使用 ModelLoader.Load 创建运行时模型对象。

using UnityEngine;
using Unity.Sentis;public class CreateRuntimeModel : MonoBehaviour
{public ModelAsset modelAsset;Model runtimeModel;void Start(){runtimeModel = ModelLoader.Load(modelAsset);}
}

然后,您可以创建一个引擎来运行模型。

导入错误

如果“模型资源导入设置”窗口显示警告,表明您的模型包含不受支持的运算符,您可以添加自定义层来实现缺少的运算符。有关示例,请参阅示例脚本中的添加自定义层示例。

2. 为模型创建输入

要检查模型所需输入的形状和大小,请打开 ONNX 模型导入设置并检查输入部分。

将数组转换为张量

要从一维数据数组创建张量,请按照下列步骤操作:

  1. 创建一个具有每个轴长度的 TensorShape 对象。
  2. 使用 TensorShape 对象和数据数组创建一个 Tensor 对象。

例如,以下代码为采用形状为 3 × 1 × 3 的输入张量的模型创建一个张量。

using UnityEngine;
using Unity.Sentis;public class ConvertArrayToTensor : MonoBehaviour
{void Start(){// 创建一个包含 9 个值的数据数组float[] data = new float[] { 1f, 2f, 3f, 4f, 5f, 6f, 7f, 8f, 9f };// 创建大小为 3 × 1 × 3 的 3D 张量形状TensorShape shape = new TensorShape(3, 1, 3);// 从数组创建一个新的张量TensorFloat tensor = new TensorFloat(shape, data);}
}

创建多个输入

如果模型需要多个输入张量,您可以创建一个包含输入的字典。例如:

Dictionary<string, Tensor> inputTensors = new Dictionary<string, Tensor>()
{{ "x", xTensor },{ "y", yTensor },
};

进行操作

如果需要对张量进行操作,请使用 WorkerFactory.CreateOps。有关详细信息,请参阅对张量进行运算。

3. 创建一个引擎来运行模型

要运行模型,请创建一个Worker。 Worker 是将模型分解为可执行任务并安排任务在 GPU 或 CPU 上运行的引擎。

Worker 是 IWorker 对象的实例。

创建一个Worker

使用 WorkerFactory.CreateWorker 创建Worker。您必须指定后端类型(告诉 Sentis 在哪里运行工作程序)以及运行时模型。

例如,以下代码创建一个使用 Sentis 计算着色器在 GPU 上运行的工作线程。

using UnityEngine;
using Unity.Sentis;public class CreateWorker : MonoBehaviour
{ModelAsset modelAsset;Model runtimeModel;IWorker worker;void Start(){runtimeModel = ModelLoader.Load(modelAsset);worker = WorkerFactory.CreateWorker(BackendType.GPUCompute, runtimeModel);}
}

后端类型

Sentis 提供 CPU 和 GPU 后端类型。要了解 Sentis 如何使用不同后端执行操作,请参阅 Sentis 如何运行模型。

如果后端类型不支持模型中的 Sentis 层,则工作线程将回退到在该层的 CPU 上运行。有关更多信息,请参阅支持的 ONNX 运算符。

BackendType.GPUCompute、BackendType.GPUCommandBuffer 和 BackendType.CPU 是最快的后端类型,因此仅当平台不支持计算着色器时才使用 BackendType.GPUPixel。要检查您的运行时平台是否支持计算着色器,请使用 SystemInfo.supportsComputeShaders

如果将 BackendType.CPU 与 WebGL 一起使用,Burst 会编译为 WebAssembly 代码,这可能会很慢。有关详细信息,请参阅 WebGL 开发入门。

模型运行的速度取决于平台对 Burst 多线程的支持程度,或者对计算着色器的支持程度。您可以分析模型以了解模型的性能。

4. 运行模型

创建工作线程后,使用 Execute 运行模型。

worker.Execute(inputTensor);

您可以在创建工作线程时启用详细模式。当您运行模型时,Sentis 将执行情况记录到控制台窗口。

worker = WorkerFactory.CreateWorker(BackendType.GPUCompute, runtimeModel, verbose: true);

当您第一次在 Unity 编辑器中运行模型时,速度可能会很慢,因为 Sentis 需要编译代码和着色器。后期跑得更快。

有关示例,请参阅示例脚本中的运行模型示例。

5. 获取模型的输出

获取张量输出

使用 PeekOutput 访问张量的输出。 PeekOutput 返回一个 Tensor 对象,因此通常需要将其转换为 TensorFloat 或 TensorInt。例如:

worker.Execute(inputTensor);
TensorFloat outputTensor = worker.PeekOutput() as TensorFloat;

PeekOutput 的结果是一个浅拷贝,它指向与原始输出相同的内存,这意味着以下内容:

  • 您不需要在输出上使用 Dispose。
  • 如果更改输出或重新运行工作程序,工作程序输出和 PeekOutput 副本都会更改。
  • 如果您在工作线程上使用 Dispose,则 PeekOutput 副本也将被释放。

要获得原始张量的所有权,请执行以下任一操作:

  • 使用 PeekOutput 后​​,对张量使用 TakeOwnership。
  • 使用 FinishExecutionAndDownloadOutput 而不是 PeekOutput。 Sentis 从本机内存下载张量。

如果您使用任一方法,则必须在使用完张量后将其释放。

当您从 PeekOutput 返回的张量中读取数据时,可能会产生性能成本,因为 Sentis 会等待模型完成运行,然后将数据从 GPU 或 Burst 下载到 CPU。您可以异步读取模型的输出以避免这种成本。您还可以分析模型以了解有关模型性能的更多信息。

要从模型输出以外的层获取中间张量,请参阅从任意层获取输出。

多个输出

如果模型有多个输出,您可以使用每个输出名称作为 PeekOutput 中的参数。

例如,以下代码示例打印模型每一层的输出。

using UnityEngine;
using Unity.Sentis;public class GetMultipleOutputs : MonoBehaviour
{ModelAsset modelAsset;Model runtimeModel;IWorker worker;void Start(){// Create an input tensorTensorFloat inputTensor = new TensorFloat(new TensorShape(4), new[] { 2.0f, 1.0f, 3.0f, 0.0f });// Create runtime modelruntimeModel = ModelLoader.Load(modelAsset);// Create engine and executeworker = WorkerFactory.CreateWorker(BackendType.GPUCompute, runtimeModel);worker.Execute(inputTensor);// Iterate through the output layer names of the model and print the output from eachforeach (var outputName in runtimeModel.outputs){TensorFloat outputTensor = worker.PeekOutput(outputName) as TensorFloat;// Make the tensor readable by downloading it to the CPUoutputTensor.MakeReadable();outputTensor.PrintDataPart(10);}}
}

打印输出

您可以使用以下方法将张量数据记录到控制台窗口:

  • Print
  • PrintDataPart,打印张量数据的第一个元素。

相关文章:

  • 2024.2.6日总结(小程序开发3)
  • 【前端web入门第五天】01 结构伪类选择器与伪元素选择器
  • python介绍,安装Cpython解释器,IDE工具pycharm的使用
  • Vue中间件的讲解案例分析
  • Unity类银河恶魔城学习记录3-4 EnemyBattleState P50
  • 服务器托管有哪些好处?
  • 大华 DSS 数字监控系统 attachment_getAttList.action SQL 注入漏洞复现
  • Stable Diffusion 模型下载:Schematics(原理图)
  • 父类之王“Object”类和内部类
  • JVM Java虚拟机入门指南
  • Android Studio从零基础到APP上线(3)
  • MySQL 数据库表格创建、数据插入及获取插入的 ID:Python 教程
  • 分享springboot框架的一个开源的本地开发部署教程(若依开源项目开发部署过程分享持续更新二开宝藏项目MySQL数据库版)
  • 树莓派智能自行车灯:亲,小心后方大卡车~
  • 假期2.6
  • 2018天猫双11|这就是阿里云!不止有新技术,更有温暖的社会力量
  • Android Volley源码解析
  • Android框架之Volley
  • GitUp, 你不可错过的秀外慧中的git工具
  • Hibernate【inverse和cascade属性】知识要点
  • javascript面向对象之创建对象
  • Java编程基础24——递归练习
  • js学习笔记
  • sessionStorage和localStorage
  • SpiderData 2019年2月23日 DApp数据排行榜
  • vue从创建到完整的饿了么(11)组件的使用(svg图标及watch的简单使用)
  • 产品三维模型在线预览
  • 让你成为前端,后端或全栈开发程序员的进阶指南,一门学到老的技术
  • 三分钟教你同步 Visual Studio Code 设置
  • 赢得Docker挑战最佳实践
  • 在Docker Swarm上部署Apache Storm:第1部分
  • Mac 上flink的安装与启动
  • 浅谈sql中的in与not in,exists与not exists的区别
  • #13 yum、编译安装与sed命令的使用
  • #传输# #传输数据判断#
  • (12)Hive调优——count distinct去重优化
  • (3)(3.2) MAVLink2数据包签名(安全)
  • (30)数组元素和与数字和的绝对差
  • (39)STM32——FLASH闪存
  • (C语言)fread与fwrite详解
  • (八)Flask之app.route装饰器函数的参数
  • (附源码)springboot 智能停车场系统 毕业设计065415
  • (附源码)ssm高校社团管理系统 毕业设计 234162
  • (附源码)ssm高校实验室 毕业设计 800008
  • (收藏)Git和Repo扫盲——如何取得Android源代码
  • (算法)Game
  • (五)大数据实战——使用模板虚拟机实现hadoop集群虚拟机克隆及网络相关配置
  • (学习日记)2024.04.04:UCOSIII第三十二节:计数信号量实验
  • (译) 函数式 JS #1:简介
  • .NET/C# 中设置当发生某个特定异常时进入断点(不借助 Visual Studio 的纯代码实现)
  • .net下简单快捷的数值高低位切换
  • @select 怎么写存储过程_你知道select语句和update语句分别是怎么执行的吗?
  • @staticmethod和@classmethod的作用与区别
  • []使用 Tortoise SVN 创建 Externals 外部引用目录
  • [android] 请求码和结果码的作用