要导入 ONNX 模型文件,请将文件从计算机拖到“Project”窗口的“Assets”文件夹中。
如果您的模型有外部权重文件,请将它们放在与模型文件相同的目录中,以便 Sentis 自动导入它们。
您可以导入 opset 版本在 7 到 15 之间的大多数 ONNX 模型文件。低于 7 或高于 15 的版本可能仍会导入 Sentis,但您可能会得到意外结果。
Sentis 不支持以下内容:
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);
}
}
然后,您可以创建一个引擎来运行模型。
如果“模型资源导入设置”窗口显示警告,表明您的模型包含不受支持的运算符,您可以添加自定义层来实现缺少的运算符。有关示例,请参阅示例脚本中的添加自定义层示例。
要检查模型所需输入的形状和大小,请打开 ONNX 模型导入设置并检查输入部分。
要从一维数据数组创建张量,请按照下列步骤操作:
例如,以下代码为采用形状为 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。有关详细信息,请参阅对张量进行运算。
要运行模型,请创建一个Worker。 Worker 是将模型分解为可执行任务并安排任务在 GPU 或 CPU 上运行的引擎。
Worker 是 IWorker 对象的实例。
使用 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 多线程的支持程度,或者对计算着色器的支持程度。您可以分析模型以了解模型的性能。
创建工作线程后,使用 Execute 运行模型。
worker.Execute(inputTensor);
您可以在创建工作线程时启用详细模式。当您运行模型时,Sentis 将执行情况记录到控制台窗口。
worker = WorkerFactory.CreateWorker(BackendType.GPUCompute, runtimeModel, verbose: true);
当您第一次在 Unity 编辑器中运行模型时,速度可能会很慢,因为 Sentis 需要编译代码和着色器。后期跑得更快。
有关示例,请参阅示例脚本中的运行模型示例。
使用 PeekOutput 访问张量的输出。 PeekOutput 返回一个 Tensor 对象,因此通常需要将其转换为 TensorFloat 或 TensorInt。例如:
worker.Execute(inputTensor);
TensorFloat outputTensor = worker.PeekOutput() as TensorFloat;
PeekOutput 的结果是一个浅拷贝,它指向与原始输出相同的内存,这意味着以下内容:
要获得原始张量的所有权,请执行以下任一操作:
如果您使用任一方法,则必须在使用完张量后将其释放。
当您从 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 tensor
TensorFloat inputTensor = new TensorFloat(new TensorShape(4), new[] { 2.0f, 1.0f, 3.0f, 0.0f });
// Create runtime model
runtimeModel = ModelLoader.Load(modelAsset);
// Create engine and execute
worker = WorkerFactory.CreateWorker(BackendType.GPUCompute, runtimeModel);
worker.Execute(inputTensor);
// Iterate through the output layer names of the model and print the output from each
foreach (var outputName in runtimeModel.outputs)
{
TensorFloat outputTensor = worker.PeekOutput(outputName) as TensorFloat;
// Make the tensor readable by downloading it to the CPU
outputTensor.MakeReadable();
outputTensor.PrintDataPart(10);
}
}
}
您可以使用以下方法将张量数据记录到控制台窗口: