mirror of
https://github.com/saymrwulf/onnxruntime.git
synced 2026-07-28 20:11:22 +00:00
### Description Merge main to WindowsAI ### Motivation and Context <!-- - Why is this change required? What problem does it solve? - If it fixes an open issue, please link to the issue here. --> --------- Signed-off-by: Nash <george.nash@intel.com> Signed-off-by: Yiming Hu <yiming.hu@amd.com> Signed-off-by: Liqun Fu <liqfu@microsoft.com> Co-authored-by: Kaz Nishimura <kazssym@linuxfront.com> Co-authored-by: Tianlei Wu <tlwu@microsoft.com> Co-authored-by: Nat Kershaw (MSFT) <nakersha@microsoft.com> Co-authored-by: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Co-authored-by: Changming Sun <chasun@microsoft.com> Co-authored-by: zesongw <zesong.wang@intel.com> Co-authored-by: Yi Zhang <zhanyi@microsoft.com> Co-authored-by: Dmitri Smirnov <yuslepukhin@users.noreply.github.com> Co-authored-by: Yifan Li <109183385+yf711@users.noreply.github.com> Co-authored-by: simonjub <78098752+simonjub@users.noreply.github.com> Co-authored-by: PeixuanZuo <94887879+PeixuanZuo@users.noreply.github.com> Co-authored-by: Adrian Lizarraga <adlizarraga@microsoft.com> Co-authored-by: Edward Chen <18449977+edgchen1@users.noreply.github.com> Co-authored-by: Arthur Islamov <arthur@islamov.ai> Co-authored-by: Jambay Kinley <jambaykinley@microsoft.com> Co-authored-by: Justin Chu <justinchuby@users.noreply.github.com> Co-authored-by: Wei-Sheng Chin <wschin@outlook.com> Co-authored-by: Bowen Bao <bowbao@microsoft.com> Co-authored-by: Hariharan Seshadri <shariharan91@gmail.com> Co-authored-by: Numfor Tiapo <numsmt2@gmail.com> Co-authored-by: Vincent Wang <wangwchpku@outlook.com> Co-authored-by: Pranav Sharma <prs@microsoft.com> Co-authored-by: George Nash <george.nash@intel.com> Co-authored-by: Abhishek Jindal <abjindal@microsoft.com> Co-authored-by: pengwa <pengwa@microsoft.com> Co-authored-by: Yiming Hu <woinck@users.noreply.github.com> Co-authored-by: Jiajia Qin <jiajia.qin@intel.com> Co-authored-by: Lukas Berbuer <36054362+lukasberbuer@users.noreply.github.com> Co-authored-by: Wanming Lin <wanming.lin@intel.com> Co-authored-by: Xavier Dupré <xadupre@users.noreply.github.com> Co-authored-by: aimilefth <60664743+aimilefth@users.noreply.github.com> Co-authored-by: Baiju Meswani <bmeswani@microsoft.com> Co-authored-by: Adam Pocock <adam.pocock@oracle.com> Co-authored-by: Chi Lo <54722500+chilo-ms@users.noreply.github.com> Co-authored-by: RandySheriffH <48490400+RandySheriffH@users.noreply.github.com> Co-authored-by: Randy Shuai <rashuai@microsoft.com> Co-authored-by: Vadym Stupakov <vadim.stupakov@gmail.com> Co-authored-by: Jian Chen <cjian@microsoft.com> Co-authored-by: Brian Lambert <98757707+brian-pieces@users.noreply.github.com> Co-authored-by: Nicolò Lucchesi <nicolo.lucchesi@gmail.com> Co-authored-by: liqun Fu <liqfu@microsoft.com> Co-authored-by: trajep <trajepl@gmail.com> Co-authored-by: Scott McKay <skottmckay@gmail.com> Co-authored-by: Mustafa Ateş Uzun <mustafauzun0@gmail.com> Co-authored-by: MistEO <mistereo@hotmail.com> Co-authored-by: satyajandhyala <satya.k.jandhyala@gmail.com> Co-authored-by: shaahji <96227573+shaahji@users.noreply.github.com> Co-authored-by: Rachel Guo <35738743+YUNQIUGUO@users.noreply.github.com> Co-authored-by: rachguo <rachguo@rachguos-Mini.attlocal.net> Co-authored-by: Caroline Zhu <wolfivyaura@gmail.com> Co-authored-by: Caroline Zhu <carolinezhu@microsoft.com> Co-authored-by: Guenther Schmuelling <guschmue@microsoft.com> Co-authored-by: xhcao <xinghua.cao@intel.com> Co-authored-by: Ella Charlaix <80481427+echarlaix@users.noreply.github.com> Co-authored-by: Xu Xing <xing.xu@intel.com> Co-authored-by: Hector Li <hecli@microsoft.com> Co-authored-by: Ye Wang <52801275+wangyems@users.noreply.github.com> Co-authored-by: Your Name <you@example.com> Co-authored-by: Benedikt Hilmes <benedikt.hilmes@rwth-aachen.de> Co-authored-by: rachguo <rachguo@rachguos-Mac-mini.local> Co-authored-by: George Wu <jywu@microsoft.com> Co-authored-by: JiCheng <wejoncy@163.com> Co-authored-by: Sheil Kumar <smk2007@gmail.com> Co-authored-by: Sheil Kumar <sheilk@microsoft.com> Co-authored-by: cloudhan <guangyunhan@microsoft.com> Co-authored-by: kyoshisuki <143475866+kyoshisuki@users.noreply.github.com> Co-authored-by: aciddelgado <139922440+aciddelgado@users.noreply.github.com> Co-authored-by: tlwu@microsoft.com <tlwu@a100.crj0ad2y1kku1j4yxl4sj10o4e.gx.internal.cloudapp.net> Co-authored-by: Maximilian Müller <44298237+gedoensmax@users.noreply.github.com> Co-authored-by: Tang, Cheng <souptc@gmail.com> Co-authored-by: Cheng Tang <chenta@microsoft.com@orttrainingdev9.d32nl1ml4oruzj4qz3bqlggovf.px.internal.cloudapp.net> Co-authored-by: Cheng Tang <chenta@microsoft.com> Co-authored-by: Jeff Daily <jeff.daily@amd.com> Co-authored-by: cloudhan <cloudhan@outlook.com> Co-authored-by: Yufeng Li <liyufeng1987@gmail.com> Co-authored-by: Zhang Lei <zhang.huanning@hotmail.com> Co-authored-by: Dwayne Robinson <fdwr@hotmail.com> Co-authored-by: Zhipeng Han <zhipeng.han@outlook.com> Co-authored-by: Thiago Crepaldi <thiago.crepaldi@microsoft.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Patrice Vignola <vignola.patrice@gmail.com> Co-authored-by: kunal-vaishnavi <115581922+kunal-vaishnavi@users.noreply.github.com> Co-authored-by: snadampal <87143774+snadampal@users.noreply.github.com> Co-authored-by: Sumit Agarwal <sumitagarwal330@gmail.com> Co-authored-by: Ashwini Khade <askhade@microsoft.com> Co-authored-by: Yang Gu <yang.gu@intel.com> Co-authored-by: Cheng Tang <chenta@a100.crj0ad2y1kku1j4yxl4sj10o4e.gx.internal.cloudapp.net> Co-authored-by: mindest <30493312+mindest@users.noreply.github.com> Co-authored-by: Scott McKay <Scott.McKay@microsoft.com> Co-authored-by: Xavier Dupre <xadupre@microsoft.com@orttrainingdev9.d32nl1ml4oruzj4qz3bqlggovf.px.internal.cloudapp.net> Co-authored-by: guyang3532 <62738430+guyang3532@users.noreply.github.com> Co-authored-by: Carson M <carson@pyke.io> Co-authored-by: sophies927 <107952697+sophies927@users.noreply.github.com>
345 lines
No EOL
14 KiB
C#
345 lines
No EOL
14 KiB
C#
using Microsoft.ML.OnnxRuntime.Tensors;
|
|
using System;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using Xunit;
|
|
|
|
namespace Microsoft.ML.OnnxRuntime.Tests
|
|
{
|
|
[Collection("OrtValueTests")]
|
|
public class OrtValueTests
|
|
{
|
|
public OrtValueTests()
|
|
{
|
|
}
|
|
|
|
[Fact(DisplayName = "PopulateAndReadStringTensor")]
|
|
public void PopulateAndReadStringTensor()
|
|
{
|
|
OrtEnv.Instance();
|
|
|
|
string[] strsRom = { "HelloR", "OrtR", "WorldR" };
|
|
string[] strs = { "Hello", "Ort", "World" };
|
|
long[] shape = { 1, 1, 3 };
|
|
var elementsNum = ShapeUtils.GetSizeForShape(shape);
|
|
Assert.Equal(elementsNum, strs.Length);
|
|
Assert.Equal(elementsNum, strsRom.Length);
|
|
|
|
using (var strTensor = OrtValue.CreateTensorWithEmptyStrings(OrtAllocator.DefaultInstance, shape))
|
|
{
|
|
Assert.True(strTensor.IsTensor);
|
|
Assert.False(strTensor.IsSparseTensor);
|
|
Assert.Equal(OnnxValueType.ONNX_TYPE_TENSOR, strTensor.OnnxType);
|
|
var typeShape = strTensor.GetTensorTypeAndShape();
|
|
{
|
|
Assert.True(typeShape.IsString);
|
|
Assert.Equal(shape.Length, typeShape.DimensionsCount);
|
|
var fetchedShape = typeShape.Shape;
|
|
Assert.Equal(shape.Length, fetchedShape.Length);
|
|
Assert.Equal(shape, fetchedShape);
|
|
Assert.Equal(elementsNum, typeShape.ElementCount);
|
|
}
|
|
|
|
using (var memInfo = strTensor.GetTensorMemoryInfo())
|
|
{
|
|
Assert.Equal("Cpu", memInfo.Name);
|
|
Assert.Equal(OrtMemType.Default, memInfo.GetMemoryType());
|
|
Assert.Equal(OrtAllocatorType.DeviceAllocator, memInfo.GetAllocatorType());
|
|
}
|
|
|
|
// Verify that everything is empty now.
|
|
for (int i = 0; i < elementsNum; ++i)
|
|
{
|
|
var str = strTensor.GetStringElement(i);
|
|
Assert.Empty(str);
|
|
|
|
var rom = strTensor.GetStringElementAsMemory(i);
|
|
Assert.Equal(0, rom.Length);
|
|
|
|
var bytes = strTensor.GetStringElementAsSpan(i);
|
|
Assert.Equal(0, bytes.Length);
|
|
}
|
|
|
|
// Let's populate the tensor with strings.
|
|
for (int i = 0; i < elementsNum; ++i)
|
|
{
|
|
// First populate via ROM
|
|
strTensor.StringTensorSetElementAt(strsRom[i].AsMemory(), i);
|
|
Assert.Equal(strsRom[i], strTensor.GetStringElement(i));
|
|
Assert.Equal(strsRom[i], strTensor.GetStringElementAsMemory(i).ToString());
|
|
Assert.Equal(Encoding.UTF8.GetBytes(strsRom[i]), strTensor.GetStringElementAsSpan(i).ToArray());
|
|
|
|
// Fill via Span
|
|
strTensor.StringTensorSetElementAt(strs[i].AsSpan(), i);
|
|
Assert.Equal(strs[i], strTensor.GetStringElement(i));
|
|
Assert.Equal(strs[i], strTensor.GetStringElementAsMemory(i).ToString());
|
|
Assert.Equal(Encoding.UTF8.GetBytes(strs[i]), strTensor.GetStringElementAsSpan(i).ToArray());
|
|
}
|
|
}
|
|
}
|
|
|
|
[Fact(DisplayName = "PopulateAndReadStringTensorViaTensor")]
|
|
public void PopulateAndReadStringTensorViaTensor()
|
|
{
|
|
OrtEnv.Instance();
|
|
|
|
string[] strs = { "Hello", "Ort", "World" };
|
|
int[] shape = { 1, 1, 3 };
|
|
|
|
var tensor = new DenseTensor<string>(strs, shape);
|
|
|
|
using (var strTensor = OrtValue.CreateFromStringTensor(tensor))
|
|
{
|
|
Assert.True(strTensor.IsTensor);
|
|
Assert.False(strTensor.IsSparseTensor);
|
|
Assert.Equal(OnnxValueType.ONNX_TYPE_TENSOR, strTensor.OnnxType);
|
|
var typeShape = strTensor.GetTensorTypeAndShape();
|
|
{
|
|
Assert.True(typeShape.IsString);
|
|
Assert.Equal(shape.Length, typeShape.DimensionsCount);
|
|
var fetchedShape = typeShape.Shape;
|
|
Assert.Equal(shape.Length, fetchedShape.Length);
|
|
Assert.Equal(strs.Length, typeShape.ElementCount);
|
|
}
|
|
|
|
using (var memInfo = strTensor.GetTensorMemoryInfo())
|
|
{
|
|
Assert.Equal("Cpu", memInfo.Name);
|
|
Assert.Equal(OrtMemType.Default, memInfo.GetMemoryType());
|
|
Assert.Equal(OrtAllocatorType.DeviceAllocator, memInfo.GetAllocatorType());
|
|
}
|
|
|
|
for (int i = 0; i < strs.Length; ++i)
|
|
{
|
|
// Fill via Span
|
|
Assert.Equal(strs[i], strTensor.GetStringElement(i));
|
|
Assert.Equal(strs[i], strTensor.GetStringElementAsMemory(i).ToString());
|
|
Assert.Equal(Encoding.UTF8.GetBytes(strs[i]), strTensor.GetStringElementAsSpan(i).ToArray());
|
|
}
|
|
}
|
|
}
|
|
static void VerifyTensorCreateWithData<T>(OrtValue tensor, TensorElementType dataType, long[] shape,
|
|
ReadOnlySpan<T> originalData) where T : unmanaged
|
|
{
|
|
// Verify invocation
|
|
var dataTypeInfo = TensorBase.GetTypeInfo(typeof(T));
|
|
Assert.NotNull(dataTypeInfo);
|
|
Assert.Equal(dataType, dataTypeInfo.ElementType);
|
|
|
|
var elementsNum = ShapeUtils.GetSizeForShape(shape);
|
|
|
|
Assert.True(tensor.IsTensor);
|
|
Assert.False(tensor.IsSparseTensor);
|
|
Assert.Equal(OnnxValueType.ONNX_TYPE_TENSOR, tensor.OnnxType);
|
|
|
|
var typeInfo = tensor.GetTypeInfo();
|
|
{
|
|
Assert.Equal(OnnxValueType.ONNX_TYPE_TENSOR, typeInfo.OnnxType);
|
|
var typeShape = typeInfo.TensorTypeAndShapeInfo;
|
|
Assert.Equal(shape.Length, typeShape.DimensionsCount);
|
|
|
|
var fetchedShape = typeShape.Shape;
|
|
Assert.Equal(shape.Length, fetchedShape.Length);
|
|
Assert.Equal(shape, fetchedShape);
|
|
Assert.Equal(elementsNum, typeShape.ElementCount);
|
|
}
|
|
|
|
using (var memInfo = tensor.GetTensorMemoryInfo())
|
|
{
|
|
Assert.Equal("Cpu", memInfo.Name);
|
|
Assert.Equal(OrtMemType.CpuOutput, memInfo.GetMemoryType());
|
|
Assert.Equal(OrtAllocatorType.DeviceAllocator, memInfo.GetAllocatorType());
|
|
}
|
|
|
|
// Verify contained data
|
|
Assert.Equal(originalData.ToArray(), tensor.GetTensorDataAsSpan<T>().ToArray());
|
|
}
|
|
|
|
[Fact(DisplayName = "CreateTensorOverManagedBuffer")]
|
|
public void CreateTensorOverManagedBuffer()
|
|
{
|
|
int[] data = { 1, 2, 3 };
|
|
var mem = new Memory<int>(data);
|
|
long[] shape = { 1, 1, 3 };
|
|
var elementsNum = ShapeUtils.GetSizeForShape(shape);
|
|
Assert.Equal(elementsNum, data.Length);
|
|
|
|
|
|
var typeInfo = TensorBase.GetElementTypeInfo(TensorElementType.Int32);
|
|
Assert.NotNull(typeInfo);
|
|
|
|
// The tensor will be created on top of the managed memory. No copy is made.
|
|
// The memory should stay pinned until the OrtValue instance is disposed. This means
|
|
// stayed pinned until the end of Run() method when you are actually running inference.
|
|
using (var tensor = OrtValue.CreateTensorValueFromMemory(data, shape))
|
|
{
|
|
VerifyTensorCreateWithData<int>(tensor, TensorElementType.Int32, shape, data);
|
|
}
|
|
}
|
|
|
|
// One can do create an OrtValue over a device memory and used as input.
|
|
// Just make sure that OrtMemoryInfo is created for GPU.
|
|
[Fact(DisplayName = "CreateTensorOverUnManagedBuffer")]
|
|
public void CreateTensorOverUnmangedBuffer()
|
|
{
|
|
const int Elements = 3;
|
|
// One can use stackalloc as well
|
|
var bufferLen = Elements * sizeof(int);
|
|
var dataPtr = Marshal.AllocHGlobal(bufferLen);
|
|
try
|
|
{
|
|
// Use span to populate chunk of native memory
|
|
Span<int> data;
|
|
unsafe
|
|
{
|
|
data = new Span<int>(dataPtr.ToPointer(), Elements);
|
|
}
|
|
data[0] = 1;
|
|
data[1] = 2;
|
|
data[2] = 3;
|
|
|
|
long[] shape = { 1, 1, 3 };
|
|
var elementsNum = ShapeUtils.GetSizeForShape(shape);
|
|
Assert.Equal(elementsNum, Elements);
|
|
|
|
using (var tensor = OrtValue.CreateTensorValueWithData(OrtMemoryInfo.DefaultInstance, TensorElementType.Int32,
|
|
shape, dataPtr, bufferLen))
|
|
{
|
|
VerifyTensorCreateWithData<int>(tensor, TensorElementType.Int32, shape, data);
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
Marshal.FreeHGlobal(dataPtr);
|
|
}
|
|
}
|
|
|
|
private static void PopulateAndCheck<T>(T[] data) where T : unmanaged
|
|
{
|
|
var typeInfo = TensorBase.GetTypeInfo(typeof(T));
|
|
Assert.NotNull(typeInfo);
|
|
|
|
long[] shape = { data.LongLength };
|
|
|
|
using (var ortValue = OrtValue.CreateAllocatedTensorValue(OrtAllocator.DefaultInstance,
|
|
typeInfo.ElementType, shape))
|
|
{
|
|
var dst = ortValue.GetTensorMutableDataAsSpan<T>();
|
|
Assert.Equal(data.Length, dst.Length);
|
|
|
|
var src = new Span<T>(data);
|
|
src.CopyTo(dst);
|
|
Assert.Equal(data, ortValue.GetTensorDataAsSpan<T>().ToArray());
|
|
}
|
|
}
|
|
|
|
// Create Tensor with allocated memory so we can test copying of the data
|
|
[Fact(DisplayName = "CreateAllocatedTensor")]
|
|
public void CreateAllocatedTensor()
|
|
{
|
|
float[] float_data = { 1, 2, 3, 4, 5, 6, 7, 8 };
|
|
int[] int_data = { 1, 2, 3, 4, 5, 6, 7, 8 };
|
|
ushort[] ushort_data = { 1, 2, 3, 4, 5, 6, 7, 8 };
|
|
double[] dbl_data = { 1, 2, 3, 4, 5, 6, 7, 8 };
|
|
var fp16_data = Array.ConvertAll(ushort_data, sh => new Float16(sh));
|
|
|
|
PopulateAndCheck(float_data);
|
|
PopulateAndCheck(int_data);
|
|
PopulateAndCheck(ushort_data);
|
|
PopulateAndCheck(dbl_data);
|
|
PopulateAndCheck(fp16_data);
|
|
}
|
|
|
|
private static readonly long[] ml_data_1 = { 1, 2 };
|
|
private static readonly long[] ml_data_2 = { 3, 4 };
|
|
|
|
// Use this utility method to create two tensors for Map and Sequence tests
|
|
private static void CreateTwoTensors(out OrtValue val1, out OrtValue val2)
|
|
{
|
|
const int ml_data_dim = 2;
|
|
// For map tensors they must be single dimensional
|
|
long[] shape = { ml_data_dim };
|
|
|
|
val1 = OrtValue.CreateTensorValueFromMemory(ml_data_1, shape);
|
|
val2 = OrtValue.CreateTensorValueFromMemory(ml_data_2, shape);
|
|
}
|
|
|
|
[Fact(DisplayName = "CreateMapFromValues")]
|
|
public void CreateMapFromValues()
|
|
{
|
|
CreateTwoTensors(out OrtValue keys, out OrtValue values);
|
|
using var map = OrtValue.CreateMap(ref keys, ref values);
|
|
Assert.Equal(OnnxValueType.ONNX_TYPE_MAP, map.OnnxType);
|
|
var typeInfo = map.GetTypeInfo();
|
|
var mapInfo = typeInfo.MapTypeInfo;
|
|
Assert.Equal(TensorElementType.Int64, mapInfo.KeyType);
|
|
Assert.Equal(OnnxValueType.ONNX_TYPE_TENSOR, mapInfo.ValueType.OnnxType);
|
|
|
|
// Must return always 2 for map since we have two ort values
|
|
Assert.Equal(2, map.GetValueCount());
|
|
|
|
map.ProcessMap((keys, values) => {
|
|
Assert.Equal(OnnxValueType.ONNX_TYPE_TENSOR, keys.OnnxType);
|
|
Assert.Equal(OnnxValueType.ONNX_TYPE_TENSOR, values.OnnxType);
|
|
Assert.Equal(ml_data_1, keys.GetTensorDataAsSpan<long>().ToArray());
|
|
Assert.Equal(ml_data_2, values.GetTensorDataAsSpan<long>().ToArray());
|
|
|
|
}, OrtAllocator.DefaultInstance);
|
|
}
|
|
|
|
[Fact(DisplayName = "CreateMapFromArraysUnmanaged")]
|
|
public void CreateMapFromArraysUnmanaged()
|
|
{
|
|
long[] keys = { 1, 2, 3 };
|
|
float[] vals = { 1, 2, 3 };
|
|
using var map = OrtValue.CreateMap(keys, vals);
|
|
}
|
|
|
|
[Fact(DisplayName = "CreateMapWithStringKeys")]
|
|
public void CreateMapWithStringKeys()
|
|
{
|
|
string[] keys = { "one", "two", "three" };
|
|
float[] vals = { 1, 2, 3 };
|
|
using var map = OrtValue.CreateMapWithStringKeys(keys, vals);
|
|
}
|
|
|
|
[Fact(DisplayName = "CreateMapWithStringValues")]
|
|
public void CreateMapWithStringValues()
|
|
{
|
|
long[] keys = { 1, 2, 3 };
|
|
string[] values = { "one", "two", "three" };
|
|
using var map = OrtValue.CreateMapWithStringValues(keys, values);
|
|
}
|
|
|
|
[Fact(DisplayName = "CreateSequence")]
|
|
public void CreateSequence()
|
|
{
|
|
CreateTwoTensors(out OrtValue val1, out OrtValue val2);
|
|
using var seqVals = new DisposableListTest<OrtValue> { val1, val2 };
|
|
using var seq = OrtValue.CreateSequence(seqVals);
|
|
|
|
Assert.Equal(OnnxValueType.ONNX_TYPE_SEQUENCE, seq.OnnxType);
|
|
var typeInfo = seq.GetTypeInfo();
|
|
var seqInfo = typeInfo.SequenceTypeInfo;
|
|
Assert.Equal(OnnxValueType.ONNX_TYPE_TENSOR, seqInfo.ElementType.OnnxType);
|
|
|
|
// Will return 2 because we put 2 values in the sequence
|
|
Assert.Equal(2, seq.GetValueCount());
|
|
|
|
// Visit each element in the sequence
|
|
seq.ProcessSequence((ortValue, index) =>
|
|
{
|
|
// We know both elements are tensors of long
|
|
Assert.Equal(OnnxValueType.ONNX_TYPE_TENSOR, ortValue.OnnxType);
|
|
if (index == 0)
|
|
{
|
|
Assert.Equal(ml_data_1, ortValue.GetTensorDataAsSpan<long>().ToArray());
|
|
}
|
|
else
|
|
{
|
|
Assert.Equal(ml_data_2, ortValue.GetTensorDataAsSpan<long>().ToArray());
|
|
}
|
|
}, OrtAllocator.DefaultInstance);
|
|
}
|
|
}
|
|
} |