Make the return namedonnxvalue objects disposable in C# API (#392)

* added the disposablenamedonnxvalue as result container

* C-API related fixes and tensorproto fix

* addressed some of the review comments
This commit is contained in:
shahasad 2019-01-28 21:40:19 -08:00 committed by jignparm
parent 571e1e9a6c
commit 5ef4c90f1d
6 changed files with 516 additions and 277 deletions

View file

@ -39,15 +39,15 @@ namespace CSharpUsage
}
// Run the inference
var results = session.Run(container); // results is an IReadOnlyList<NamedOnnxValue> container
// dump the results
foreach (var r in results)
using (var results = session.Run(container)) // results is an IDisposableReadOnlyCollection<DisposableNamedOnnxValue> container
{
Console.WriteLine("Output for {0}", r.Name);
Console.WriteLine(r.AsTensor<float>().GetArrayString());
// dump the results
foreach (var r in results)
{
Console.WriteLine("Output for {0}", r.Name);
Console.WriteLine(r.AsTensor<float>().GetArrayString());
}
}
}
}

View file

@ -0,0 +1,177 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using System.Numerics.Tensors;
namespace Microsoft.ML.OnnxRuntime
{
public interface IDisposableReadOnlyCollection<T>: IReadOnlyCollection<T>, IDisposable
{
}
internal class DisposableList<T> : List<T>, IDisposableReadOnlyCollection<T>
where T: IDisposable
{
#region IDisposable Support
private bool disposedValue = false; // To detect redundant calls
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
// TODO: dispose managed state (managed objects).
for (int i = 0; i < this.Count; i++)
{
this[i].Dispose();
}
this.Clear();
}
// TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
// TODO: set large fields to null.
disposedValue = true;
}
}
~DisposableList()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose(false);
}
// This code added to correctly implement the disposable pattern.
public void Dispose()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
public class DisposableNamedOnnxValue: NamedOnnxValue, IDisposable
{
protected IDisposable _nativeMemoryManager;
protected DisposableNamedOnnxValue(string name, Object value, IDisposable nativeMemoryManager)
:base(name, value)
{
_nativeMemoryManager = nativeMemoryManager;
}
internal static DisposableNamedOnnxValue CreateFromOnnxValue(string name, IntPtr nativeOnnxValue)
{
DisposableNamedOnnxValue result = null;
/* Get Tensor element type */ //TODO: Assumed value is Tensor, need to support non-tensor types in future
IntPtr typeAndShape = IntPtr.Zero;
TensorElementType elemType = TensorElementType.DataTypeMax;
try
{
NativeApiStatus.VerifySuccess(NativeMethods.OrtGetTensorShapeAndType(nativeOnnxValue, out typeAndShape));
elemType = NativeMethods.OrtGetTensorElementType(typeAndShape);
}
finally
{
if (typeAndShape != IntPtr.Zero)
{
NativeMethods.OrtReleaseTensorTypeAndShapeInfo(typeAndShape);
}
}
switch (elemType)
{
case TensorElementType.Float:
result = NameOnnxValueFromNativeTensor<float>(name, nativeOnnxValue);
break;
case TensorElementType.Double:
result = NameOnnxValueFromNativeTensor<double>(name, nativeOnnxValue);
break;
case TensorElementType.Int16:
result = NameOnnxValueFromNativeTensor<short>(name, nativeOnnxValue);
break;
case TensorElementType.UInt16:
result = NameOnnxValueFromNativeTensor<ushort>(name, nativeOnnxValue);
break;
case TensorElementType.Int32:
result = NameOnnxValueFromNativeTensor<int>(name, nativeOnnxValue);
break;
case TensorElementType.UInt32:
result = NameOnnxValueFromNativeTensor<uint>(name, nativeOnnxValue);
break;
case TensorElementType.Int64:
result = NameOnnxValueFromNativeTensor<long>(name, nativeOnnxValue);
break;
case TensorElementType.UInt64:
result = NameOnnxValueFromNativeTensor<ulong>(name, nativeOnnxValue);
break;
case TensorElementType.UInt8:
result = NameOnnxValueFromNativeTensor<byte>(name, nativeOnnxValue);
break;
default:
throw new NotSupportedException("Tensor of element type: " + elemType + " is not supported");
}
return result;
}
private static DisposableNamedOnnxValue NameOnnxValueFromNativeTensor<T>(string name, IntPtr nativeOnnxValue)
{
NativeOnnxTensorMemory<T> nativeTensorWrapper = new NativeOnnxTensorMemory<T>(nativeOnnxValue);
DenseTensor<T> dt = new DenseTensor<T>(nativeTensorWrapper.Memory, nativeTensorWrapper.Dimensions);
return new DisposableNamedOnnxValue(name, dt, nativeTensorWrapper);
}
#region IDisposable Support
private bool disposedValue = false; // To detect redundant calls
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
// dispose managed state (managed objects).
if (_nativeMemoryManager != null)
{
_nativeMemoryManager.Dispose();
_nativeMemoryManager = null;
}
}
// free unmanaged resources (unmanaged objects) and override a finalizer below.
// set large fields to null.
disposedValue = true;
}
}
~DisposableNamedOnnxValue()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose(false);
}
// This code added to correctly implement the disposable pattern.
public void Dispose()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
}

View file

@ -105,7 +105,7 @@ namespace Microsoft.ML.OnnxRuntime
/// </summary>
/// <param name="inputs"></param>
/// <returns>Output Tensors in a Collection of NamedOnnxValue</returns>
public IReadOnlyCollection<NamedOnnxValue> Run(IReadOnlyCollection<NamedOnnxValue> inputs)
public IDisposableReadOnlyCollection<DisposableNamedOnnxValue> Run(IReadOnlyCollection<NamedOnnxValue> inputs)
{
string[] outputNames = new string[_outputMetadata.Count];
_outputMetadata.Keys.CopyTo(outputNames, 0);
@ -118,7 +118,7 @@ namespace Microsoft.ML.OnnxRuntime
/// <param name="inputs"></param>
/// <param name="outputNames"></param>
/// <returns>Output Tensors in a Collection of NamedOnnxValue</returns>
public IReadOnlyCollection<NamedOnnxValue> Run(IReadOnlyCollection<NamedOnnxValue> inputs, IReadOnlyCollection<string> outputNames)
public IDisposableReadOnlyCollection<DisposableNamedOnnxValue> Run(IReadOnlyCollection<NamedOnnxValue> inputs, IReadOnlyCollection<string> outputNames)
{
return Run(inputs, outputNames, RunOptions.Default);
}
@ -129,9 +129,9 @@ namespace Microsoft.ML.OnnxRuntime
/// <param name="inputs"></param>
/// <param name="outputNames"></param>
/// <param name="options"></param>
/// <returns>Output Tensors in a Dictionary</returns>
/// <returns>Output Tensors in a Collection of NamedOnnxValue</returns>
//TODO: kept internal until RunOptions is made public
internal IReadOnlyCollection<NamedOnnxValue> Run(IReadOnlyCollection<NamedOnnxValue> inputs, IReadOnlyCollection<string> outputNames, RunOptions options)
internal IDisposableReadOnlyCollection<DisposableNamedOnnxValue> Run(IReadOnlyCollection<NamedOnnxValue> inputs, IReadOnlyCollection<string> outputNames, RunOptions options)
{
var inputNames = new string[inputs.Count];
var inputTensors = new IntPtr[inputs.Count];
@ -166,10 +166,10 @@ namespace Microsoft.ML.OnnxRuntime
try
{
NativeApiStatus.VerifySuccess(status);
var result = new List<NamedOnnxValue>();
var result = new DisposableList<DisposableNamedOnnxValue>();
for (uint i = 0; i < outputValueArray.Length; i++)
{
result.Add(NamedOnnxValue.CreateFromOnnxValue(outputNamesArray[i], outputValueArray[i]));
result.Add(DisposableNamedOnnxValue.CreateFromOnnxValue(outputNamesArray[i], outputValueArray[i]));
}
return result;

View file

@ -182,72 +182,6 @@ namespace Microsoft.ML.OnnxRuntime
}
internal static NamedOnnxValue CreateFromOnnxValue(string name, IntPtr nativeOnnxValue)
{
NamedOnnxValue result = null;
/* Get Tensor element type */ //TODO: Assumed value is Tensor, need to support non-tensor types in future
IntPtr typeAndShape = IntPtr.Zero;
TensorElementType elemType = TensorElementType.DataTypeMax;
try
{
NativeApiStatus.VerifySuccess(NativeMethods.OrtGetTensorShapeAndType(nativeOnnxValue, out typeAndShape));
elemType = NativeMethods.OrtGetTensorElementType(typeAndShape);
}
finally
{
if (typeAndShape != IntPtr.Zero)
{
NativeMethods.OrtReleaseTensorTypeAndShapeInfo(typeAndShape);
}
}
switch (elemType)
{
case TensorElementType.Float:
result = NameOnnxValueFromNativeTensor<float>(name, nativeOnnxValue);
break;
case TensorElementType.Double:
result = NameOnnxValueFromNativeTensor<double>(name, nativeOnnxValue);
break;
case TensorElementType.Int16:
result = NameOnnxValueFromNativeTensor<short>(name, nativeOnnxValue);
break;
case TensorElementType.UInt16:
result = NameOnnxValueFromNativeTensor<ushort>(name, nativeOnnxValue);
break;
case TensorElementType.Int32:
result = NameOnnxValueFromNativeTensor<int>(name, nativeOnnxValue);
break;
case TensorElementType.UInt32:
result = NameOnnxValueFromNativeTensor<uint>(name, nativeOnnxValue);
break;
case TensorElementType.Int64:
result = NameOnnxValueFromNativeTensor<long>(name, nativeOnnxValue);
break;
case TensorElementType.UInt64:
result = NameOnnxValueFromNativeTensor<ulong>(name, nativeOnnxValue);
break;
case TensorElementType.UInt8:
result = NameOnnxValueFromNativeTensor<byte>(name, nativeOnnxValue);
break;
default:
throw new NotSupportedException("Tensor of element type: "+elemType+" is not supported");
}
return result;
}
private static NamedOnnxValue NameOnnxValueFromNativeTensor<T>(string name, IntPtr nativeOnnxValue)
{
NativeOnnxTensorMemory<T> nativeTensorWrapper = new NativeOnnxTensorMemory<T>(nativeOnnxValue);
DenseTensor<T> dt = new DenseTensor<T>(nativeTensorWrapper.Memory, nativeTensorWrapper.Dimensions);
return NamedOnnxValue.CreateFromTensor<T>(name, dt);
}
private bool TryPinAsTensor<T>(
out MemoryHandle pinnedMemoryHandle,
out IntPtr dataBufferPointer,

View file

@ -70,29 +70,30 @@ namespace Microsoft.ML.OnnxRuntime.Tests
}
// Run the inference
var results = session.Run(container); // results is an IReadOnlyList<NamedOnnxValue> container
Assert.Equal(1, results.Count);
float[] expectedOutput = LoadTensorFromFile(@"bench.expected_out");
// validate the results
foreach (var r in results)
using (var results = session.Run(container)) // results is an IReadOnlyList<NamedOnnxValue> container
{
Assert.Equal("softmaxout_1", r.Name);
Assert.Equal(1, results.Count);
var resultTensor = r.AsTensor<float>();
int[] expectedDimensions = { 1, 1000, 1, 1 }; // hardcoded for now for the test data
Assert.Equal(expectedDimensions.Length, resultTensor.Rank);
var resultDimensions = resultTensor.Dimensions;
for (int i = 0; i < expectedDimensions.Length; i++)
float[] expectedOutput = LoadTensorFromFile(@"bench.expected_out");
// validate the results
foreach (var r in results)
{
Assert.Equal(expectedDimensions[i], resultDimensions[i]);
}
Assert.Equal("softmaxout_1", r.Name);
var resultArray = r.AsTensor<float>().ToArray();
Assert.Equal(expectedOutput.Length, resultArray.Length);
Assert.Equal(expectedOutput, resultArray, new floatComparer());
var resultTensor = r.AsTensor<float>();
int[] expectedDimensions = { 1, 1000, 1, 1 }; // hardcoded for now for the test data
Assert.Equal(expectedDimensions.Length, resultTensor.Rank);
var resultDimensions = resultTensor.Dimensions;
for (int i = 0; i < expectedDimensions.Length; i++)
{
Assert.Equal(expectedDimensions[i], resultDimensions[i]);
}
var resultArray = r.AsTensor<float>().ToArray();
Assert.Equal(expectedOutput.Length, resultArray.Length);
Assert.Equal(expectedOutput, resultArray, new floatComparer());
}
}
}
}
@ -247,28 +248,31 @@ namespace Microsoft.ML.OnnxRuntime.Tests
}
onnxModelFileName = Path.Combine(cwd, opset, modelDir.Name, onnxModelNames[0].Name);
var session = new InferenceSession(onnxModelFileName);
var inMeta = session.InputMetadata;
var innodepair = inMeta.First();
var innodename = innodepair.Key;
var innodedims = innodepair.Value.Dimensions;
for (int i = 0; i < innodedims.Length; i++)
using (var session = new InferenceSession(onnxModelFileName))
{
if (innodedims[i] < 0)
innodedims[i] = -1 * innodedims[i];
}
var inMeta = session.InputMetadata;
var innodepair = inMeta.First();
var innodename = innodepair.Key;
var innodedims = innodepair.Value.Dimensions;
for (int i = 0; i < innodedims.Length; i++)
{
if (innodedims[i] < 0)
innodedims[i] = -1 * innodedims[i];
}
var testRoot = new DirectoryInfo(Path.Combine(cwd, opset, modelDir.Name));
var testData = testRoot.EnumerateDirectories("test_data*").First();
var dataIn = LoadTensorFromFilePb(Path.Combine(cwd, opset, modelDir.Name, testData.ToString(), "input_0.pb"));
var dataOut = LoadTensorFromFilePb(Path.Combine(cwd, opset, modelDir.Name, testData.ToString(), "output_0.pb"));
var tensorIn = new DenseTensor<float>(dataIn, innodedims);
var nov = new List<NamedOnnxValue>();
nov.Add(NamedOnnxValue.CreateFromTensor<float>(innodename, tensorIn));
var resnov = session.Run(nov);
var res = resnov.ToArray()[0].AsTensor<float>().ToArray<float>();
Assert.Equal(res, dataOut, new floatComparer());
session.Dispose();
var testRoot = new DirectoryInfo(Path.Combine(cwd, opset, modelDir.Name));
var testData = testRoot.EnumerateDirectories("test_data*").First();
var dataIn = LoadTensorFromFilePb(Path.Combine(cwd, opset, modelDir.Name, testData.ToString(), "input_0.pb"));
var dataOut = LoadTensorFromFilePb(Path.Combine(cwd, opset, modelDir.Name, testData.ToString(), "output_0.pb"));
var tensorIn = new DenseTensor<float>(dataIn, innodedims);
var nov = new List<NamedOnnxValue>();
nov.Add(NamedOnnxValue.CreateFromTensor<float>(innodename, tensorIn));
using (var resnov = session.Run(nov))
{
var res = resnov.ToArray()[0].AsTensor<float>().ToArray<float>();
Assert.Equal(res, dataOut, new floatComparer());
}
}
}
catch (Exception ex)
{
@ -284,15 +288,19 @@ namespace Microsoft.ML.OnnxRuntime.Tests
{
// model takes 1x5 input of fixed type, echoes back
string modelPath = Path.Combine(Directory.GetCurrentDirectory(), "test_types_FLOAT.pb");
var session = new InferenceSession(modelPath);
var container = new List<NamedOnnxValue>();
var tensorIn = new DenseTensor<float>(new float[] { 1.0f, 2.0f, -3.0f, float.MinValue, float.MaxValue }, new int[] { 1, 5 });
var nov = NamedOnnxValue.CreateFromTensor("input", tensorIn);
container.Add(nov);
var res = session.Run(container);
var tensorOut = res.First().AsTensor<float>();
Assert.True(tensorOut.SequenceEqual(tensorIn));
session.Dispose();
using (var session = new InferenceSession(modelPath))
{
var container = new List<NamedOnnxValue>();
var tensorIn = new DenseTensor<float>(new float[] { 1.0f, 2.0f, -3.0f, float.MinValue, float.MaxValue }, new int[] { 1, 5 });
var nov = NamedOnnxValue.CreateFromTensor("input", tensorIn);
container.Add(nov);
using (var res = session.Run(container))
{
var tensorOut = res.First().AsTensor<float>();
Assert.True(tensorOut.SequenceEqual(tensorIn));
}
}
}
[Fact(Skip = "Boolean tensor not supported yet")]
@ -300,15 +308,18 @@ namespace Microsoft.ML.OnnxRuntime.Tests
{
// model takes 1x5 input of fixed type, echoes back
string modelPath = Path.Combine(Directory.GetCurrentDirectory(), "test_types_BOOL.pb");
var session = new InferenceSession(modelPath);
var container = new List<NamedOnnxValue>();
var tensorIn = new DenseTensor<bool>(new bool[] { true, false, true, false, true }, new int[] { 1, 5 });
var nov = NamedOnnxValue.CreateFromTensor("input", tensorIn);
container.Add(nov);
var res = session.Run(container);
var tensorOut = res.First().AsTensor<bool>();
Assert.True(tensorOut.SequenceEqual(tensorIn));
session.Dispose();
using (var session = new InferenceSession(modelPath))
{
var container = new List<NamedOnnxValue>();
var tensorIn = new DenseTensor<bool>(new bool[] { true, false, true, false, true }, new int[] { 1, 5 });
var nov = NamedOnnxValue.CreateFromTensor("input", tensorIn);
container.Add(nov);
using (var res = session.Run(container))
{
var tensorOut = res.First().AsTensor<bool>();
Assert.True(tensorOut.SequenceEqual(tensorIn));
}
}
}
[Fact]
@ -316,15 +327,18 @@ namespace Microsoft.ML.OnnxRuntime.Tests
{
// model takes 1x5 input of fixed type, echoes back
string modelPath = Path.Combine(Directory.GetCurrentDirectory(), "test_types_INT32.pb");
var session = new InferenceSession(modelPath);
var container = new List<NamedOnnxValue>();
var tensorIn = new DenseTensor<int>(new int[] { 1, -2, -3, int.MinValue, int.MaxValue }, new int[] { 1, 5 });
var nov = NamedOnnxValue.CreateFromTensor("input", tensorIn);
container.Add(nov);
var res = session.Run(container);
var tensorOut = res.First().AsTensor<int>();
Assert.True(tensorOut.SequenceEqual(tensorIn));
session.Dispose();
using (var session = new InferenceSession(modelPath))
{
var container = new List<NamedOnnxValue>();
var tensorIn = new DenseTensor<int>(new int[] { 1, -2, -3, int.MinValue, int.MaxValue }, new int[] { 1, 5 });
var nov = NamedOnnxValue.CreateFromTensor("input", tensorIn);
container.Add(nov);
using (var res = session.Run(container))
{
var tensorOut = res.First().AsTensor<int>();
Assert.True(tensorOut.SequenceEqual(tensorIn));
}
}
}
[Fact]
@ -332,15 +346,19 @@ namespace Microsoft.ML.OnnxRuntime.Tests
{
// model takes 1x5 input of fixed type, echoes back
string modelPath = Path.Combine(Directory.GetCurrentDirectory(), "test_types_DOUBLE.pb");
var session = new InferenceSession(modelPath);
var container = new List<NamedOnnxValue>();
var tensorIn = new DenseTensor<double>(new double[] { 1.0, 2.0, -3.0, 5, 5 }, new int[] { 1, 5 });
var nov = NamedOnnxValue.CreateFromTensor("input", tensorIn);
container.Add(nov);
var res = session.Run(container);
var tensorOut = res.First().AsTensor<double>();
Assert.True(tensorOut.SequenceEqual(tensorIn));
session.Dispose();
using (var session = new InferenceSession(modelPath))
{
var container = new List<NamedOnnxValue>();
var tensorIn = new DenseTensor<double>(new double[] { 1.0, 2.0, -3.0, 5, 5 }, new int[] { 1, 5 });
var nov = NamedOnnxValue.CreateFromTensor("input", tensorIn);
container.Add(nov);
using (var res = session.Run(container))
{
var tensorOut = res.First().AsTensor<double>();
Assert.True(tensorOut.SequenceEqual(tensorIn));
}
}
}
[Fact(Skip = "String tensor not supported yet")]
@ -348,15 +366,18 @@ namespace Microsoft.ML.OnnxRuntime.Tests
{
// model takes 1x5 input of fixed type, echoes back
string modelPath = Path.Combine(Directory.GetCurrentDirectory(), "test_types_STRING.onnx");
var session = new InferenceSession(modelPath);
var container = new List<NamedOnnxValue>();
var tensorIn = new DenseTensor<string>(new string[] { "a", "c", "d", "z", "f" }, new int[] { 1, 5 });
var nov = NamedOnnxValue.CreateFromTensor("input", tensorIn);
container.Add(nov);
var res = session.Run(container);
var tensorOut = res.First().AsTensor<string>();
Assert.True(tensorOut.SequenceEqual(tensorIn));
session.Dispose();
using (var session = new InferenceSession(modelPath))
{
var container = new List<NamedOnnxValue>();
var tensorIn = new DenseTensor<string>(new string[] { "a", "c", "d", "z", "f" }, new int[] { 1, 5 });
var nov = NamedOnnxValue.CreateFromTensor("input", tensorIn);
container.Add(nov);
using (var res = session.Run(container))
{
var tensorOut = res.First().AsTensor<string>();
Assert.True(tensorOut.SequenceEqual(tensorIn));
}
}
}
[Fact(Skip = "Int8 not supported yet")]
@ -364,15 +385,18 @@ namespace Microsoft.ML.OnnxRuntime.Tests
{
// model takes 1x5 input of fixed type, echoes back
string modelPath = Path.Combine(Directory.GetCurrentDirectory(), "test_types_INT8.pb");
var session = new InferenceSession(modelPath);
var container = new List<NamedOnnxValue>();
var tensorIn = new DenseTensor<sbyte>(new sbyte[] { 1, 2, -3, sbyte.MinValue, sbyte.MaxValue }, new int[] { 1, 5 });
var nov = NamedOnnxValue.CreateFromTensor("input", tensorIn);
container.Add(nov);
var res = session.Run(container);
var tensorOut = res.First().AsTensor<sbyte>();
Assert.True(tensorOut.SequenceEqual(tensorIn));
session.Dispose();
using (var session = new InferenceSession(modelPath))
{
var container = new List<NamedOnnxValue>();
var tensorIn = new DenseTensor<sbyte>(new sbyte[] { 1, 2, -3, sbyte.MinValue, sbyte.MaxValue }, new int[] { 1, 5 });
var nov = NamedOnnxValue.CreateFromTensor("input", tensorIn);
container.Add(nov);
using (var res = session.Run(container))
{
var tensorOut = res.First().AsTensor<sbyte>();
Assert.True(tensorOut.SequenceEqual(tensorIn));
}
}
}
[Fact]
@ -380,15 +404,18 @@ namespace Microsoft.ML.OnnxRuntime.Tests
{
// model takes 1x5 input of fixed type, echoes back
string modelPath = Path.Combine(Directory.GetCurrentDirectory(), "test_types_UINT8.pb");
var session = new InferenceSession(modelPath);
var container = new List<NamedOnnxValue>();
var tensorIn = new DenseTensor<byte>(new byte[] { 1, 2, 3, byte.MinValue, byte.MaxValue }, new int[] { 1, 5 });
var nov = NamedOnnxValue.CreateFromTensor("input", tensorIn);
container.Add(nov);
var res = session.Run(container);
var tensorOut = res.First().AsTensor<byte>();
Assert.True(tensorOut.SequenceEqual(tensorIn));
session.Dispose();
using (var session = new InferenceSession(modelPath))
{
var container = new List<NamedOnnxValue>();
var tensorIn = new DenseTensor<byte>(new byte[] { 1, 2, 3, byte.MinValue, byte.MaxValue }, new int[] { 1, 5 });
var nov = NamedOnnxValue.CreateFromTensor("input", tensorIn);
container.Add(nov);
using (var res = session.Run(container))
{
var tensorOut = res.First().AsTensor<byte>();
Assert.True(tensorOut.SequenceEqual(tensorIn));
}
}
}
[Fact]
@ -396,15 +423,18 @@ namespace Microsoft.ML.OnnxRuntime.Tests
{
// model takes 1x5 input of fixed type, echoes back
string modelPath = Path.Combine(Directory.GetCurrentDirectory(), "test_types_UINT16.pb");
var session = new InferenceSession(modelPath);
var container = new List<NamedOnnxValue>();
var tensorIn = new DenseTensor<UInt16>(new UInt16[] { 1, 2, 3, UInt16.MinValue, UInt16.MaxValue }, new int[] { 1, 5 });
var nov = NamedOnnxValue.CreateFromTensor("input", tensorIn);
container.Add(nov);
var res = session.Run(container);
var tensorOut = res.First().AsTensor<UInt16>();
Assert.True(tensorOut.SequenceEqual(tensorIn));
session.Dispose();
using (var session = new InferenceSession(modelPath))
{
var container = new List<NamedOnnxValue>();
var tensorIn = new DenseTensor<UInt16>(new UInt16[] { 1, 2, 3, UInt16.MinValue, UInt16.MaxValue }, new int[] { 1, 5 });
var nov = NamedOnnxValue.CreateFromTensor("input", tensorIn);
container.Add(nov);
using (var res = session.Run(container))
{
var tensorOut = res.First().AsTensor<UInt16>();
Assert.True(tensorOut.SequenceEqual(tensorIn));
}
}
}
[Fact]
@ -412,15 +442,18 @@ namespace Microsoft.ML.OnnxRuntime.Tests
{
// model takes 1x5 input of fixed type, echoes back
string modelPath = Path.Combine(Directory.GetCurrentDirectory(), "test_types_INT16.pb");
var session = new InferenceSession(modelPath);
var container = new List<NamedOnnxValue>();
var tensorIn = new DenseTensor<Int16>(new Int16[] { 1, 2, 3, Int16.MinValue, Int16.MaxValue }, new int[] { 1, 5 });
var nov = NamedOnnxValue.CreateFromTensor("input", tensorIn);
container.Add(nov);
var res = session.Run(container);
var tensorOut = res.First().AsTensor<Int16>();
Assert.True(tensorOut.SequenceEqual(tensorIn));
session.Dispose();
using (var session = new InferenceSession(modelPath))
{
var container = new List<NamedOnnxValue>();
var tensorIn = new DenseTensor<Int16>(new Int16[] { 1, 2, 3, Int16.MinValue, Int16.MaxValue }, new int[] { 1, 5 });
var nov = NamedOnnxValue.CreateFromTensor("input", tensorIn);
container.Add(nov);
using (var res = session.Run(container))
{
var tensorOut = res.First().AsTensor<Int16>();
Assert.True(tensorOut.SequenceEqual(tensorIn));
}
}
}
[Fact]
@ -428,15 +461,18 @@ namespace Microsoft.ML.OnnxRuntime.Tests
{
// model takes 1x5 input of fixed type, echoes back
string modelPath = Path.Combine(Directory.GetCurrentDirectory(), "test_types_INT64.pb");
var session = new InferenceSession(modelPath);
var container = new List<NamedOnnxValue>();
var tensorIn = new DenseTensor<Int64>(new Int64[] { 1, 2, -3, Int64.MinValue, Int64.MaxValue }, new int[] { 1, 5 });
var nov = NamedOnnxValue.CreateFromTensor("input", tensorIn);
container.Add(nov);
var res = session.Run(container);
var tensorOut = res.First().AsTensor<Int64>();
Assert.True(tensorOut.SequenceEqual(tensorIn));
session.Dispose();
using (var session = new InferenceSession(modelPath))
{
var container = new List<NamedOnnxValue>();
var tensorIn = new DenseTensor<Int64>(new Int64[] { 1, 2, -3, Int64.MinValue, Int64.MaxValue }, new int[] { 1, 5 });
var nov = NamedOnnxValue.CreateFromTensor("input", tensorIn);
container.Add(nov);
using (var res = session.Run(container))
{
var tensorOut = res.First().AsTensor<Int64>();
Assert.True(tensorOut.SequenceEqual(tensorIn));
}
}
}
[Fact]
@ -444,46 +480,55 @@ namespace Microsoft.ML.OnnxRuntime.Tests
{
// model takes 1x5 input of fixed type, echoes back
string modelPath = Path.Combine(Directory.GetCurrentDirectory(), "test_types_UINT32.pb");
var session = new InferenceSession(modelPath);
var container = new List<NamedOnnxValue>();
var tensorIn = new DenseTensor<UInt32>(new UInt32[] { 1, 2, 3, UInt32.MinValue, UInt32.MaxValue }, new int[] { 1, 5 });
var nov = NamedOnnxValue.CreateFromTensor("input", tensorIn);
container.Add(nov);
var res = session.Run(container);
var tensorOut = res.First().AsTensor<UInt32>();
Assert.True(tensorOut.SequenceEqual(tensorIn));
session.Dispose();
using (var session = new InferenceSession(modelPath))
{
var container = new List<NamedOnnxValue>();
var tensorIn = new DenseTensor<UInt32>(new UInt32[] { 1, 2, 3, UInt32.MinValue, UInt32.MaxValue }, new int[] { 1, 5 });
var nov = NamedOnnxValue.CreateFromTensor("input", tensorIn);
container.Add(nov);
using (var res = session.Run(container))
{
var tensorOut = res.First().AsTensor<UInt32>();
Assert.True(tensorOut.SequenceEqual(tensorIn));
}
}
}
[Fact]
private void TestModelInputUINT64()
{
// model takes 1x5 input of fixed type, echoes back
string modelPath = Path.Combine(Directory.GetCurrentDirectory(), "test_types_UINT64.pb");
var session = new InferenceSession(modelPath);
var container = new List<NamedOnnxValue>();
var tensorIn = new DenseTensor<UInt64>(new UInt64[] { 1, 2, 3, UInt64.MinValue, UInt64.MaxValue }, new int[] { 1, 5 });
var nov = NamedOnnxValue.CreateFromTensor("input", tensorIn);
container.Add(nov);
var res = session.Run(container);
var tensorOut = res.First().AsTensor<UInt64>();
Assert.True(tensorOut.SequenceEqual(tensorIn));
session.Dispose();
using (var session = new InferenceSession(modelPath))
{
var container = new List<NamedOnnxValue>();
var tensorIn = new DenseTensor<UInt64>(new UInt64[] { 1, 2, 3, UInt64.MinValue, UInt64.MaxValue }, new int[] { 1, 5 });
var nov = NamedOnnxValue.CreateFromTensor("input", tensorIn);
container.Add(nov);
using (var res = session.Run(container))
{
var tensorOut = res.First().AsTensor<UInt64>();
Assert.True(tensorOut.SequenceEqual(tensorIn));
}
}
}
[Fact(Skip = "Boolean FLOAT16 not available in C#")]
[Fact(Skip = "FLOAT16 not available in C#")]
private void TestModelInputFLOAT16()
{
// model takes 1x5 input of fixed type, echoes back
string modelPath = Path.Combine(Directory.GetCurrentDirectory(), "test_types_FLOAT16.pb");
var session = new InferenceSession(modelPath);
var container = new List<NamedOnnxValue>();
var tensorIn = new DenseTensor<float>(new float[] { 1.0f, 2.0f, -3.0f, float.MinValue, float.MaxValue }, new int[] { 1, 5 });
var nov = NamedOnnxValue.CreateFromTensor("input", tensorIn);
container.Add(nov);
var res = session.Run(container);
var tensorOut = res.First().AsTensor<float>();
Assert.True(tensorOut.SequenceEqual(tensorIn));
session.Dispose();
using (var session = new InferenceSession(modelPath))
{
var container = new List<NamedOnnxValue>();
var tensorIn = new DenseTensor<float>(new float[] { 1.0f, 2.0f, -3.0f, float.MinValue, float.MaxValue }, new int[] { 1, 5 });
var nov = NamedOnnxValue.CreateFromTensor("input", tensorIn);
container.Add(nov);
using (var res = session.Run(container))
{
var tensorOut = res.First().AsTensor<float>();
Assert.True(tensorOut.SequenceEqual(tensorIn));
}
}
}
[Fact]
@ -492,15 +537,16 @@ namespace Microsoft.ML.OnnxRuntime.Tests
// TODO: execute based on test pool directly (cpu or gpu)
var gpu = Environment.GetEnvironmentVariable("TESTONGPU");
var tuple = (gpu != null) ? OpenSessionSqueezeNet(Int32.Parse(gpu)) : OpenSessionSqueezeNet();
var session = tuple.Item1;
var inputData = tuple.Item2;
var tensor = tuple.Item3;
var inputMeta = session.InputMetadata;
var container = new List<NamedOnnxValue>();
container.Add(NamedOnnxValue.CreateFromTensor<float>("input", tensor));
var ex = Assert.Throws<OnnxRuntimeException>(() => session.Run(container));
Assert.Equal("[ErrorCode:InvalidArgument] Missing required inputs: data_0", ex.Message);
session.Dispose();
using (var session = tuple.Item1)
{
var inputData = tuple.Item2;
var tensor = tuple.Item3;
var inputMeta = session.InputMetadata;
var container = new List<NamedOnnxValue>();
container.Add(NamedOnnxValue.CreateFromTensor<float>("input", tensor));
var ex = Assert.Throws<OnnxRuntimeException>(() => session.Run(container));
Assert.Equal("[ErrorCode:InvalidArgument] Missing required inputs: data_0", ex.Message);
}
}
[DllImport("kernel32", SetLastError = true)]

View file

@ -53,39 +53,43 @@ namespace Onnx {
"b3RvEhIKCmRvY19zdHJpbmcYCiABKAkSIwoFaW5wdXQYCyADKAsyFC5vbm54",
"LlZhbHVlSW5mb1Byb3RvEiQKBm91dHB1dBgMIAMoCzIULm9ubnguVmFsdWVJ",
"bmZvUHJvdG8SKAoKdmFsdWVfaW5mbxgNIAMoCzIULm9ubnguVmFsdWVJbmZv",
"UHJvdG8ioQQKC1RlbnNvclByb3RvEgwKBGRpbXMYASADKAMSEQoJZGF0YV90",
"UHJvdG8iuAUKC1RlbnNvclByb3RvEgwKBGRpbXMYASADKAMSEQoJZGF0YV90",
"eXBlGAIgASgFEioKB3NlZ21lbnQYAyABKAsyGS5vbm54LlRlbnNvclByb3Rv",
"LlNlZ21lbnQSFgoKZmxvYXRfZGF0YRgEIAMoAkICEAESFgoKaW50MzJfZGF0",
"YRgFIAMoBUICEAESEwoLc3RyaW5nX2RhdGEYBiADKAwSFgoKaW50NjRfZGF0",
"YRgHIAMoA0ICEAESDAoEbmFtZRgIIAEoCRISCgpkb2Nfc3RyaW5nGAwgASgJ",
"EhAKCHJhd19kYXRhGAkgASgMEhcKC2RvdWJsZV9kYXRhGAogAygBQgIQARIX",
"Cgt1aW50NjRfZGF0YRgLIAMoBEICEAEaJQoHU2VnbWVudBINCgViZWdpbhgB",
"IAEoAxILCgNlbmQYAiABKAMi2gEKCERhdGFUeXBlEg0KCVVOREVGSU5FRBAA",
"EgkKBUZMT0FUEAESCQoFVUlOVDgQAhIICgRJTlQ4EAMSCgoGVUlOVDE2EAQS",
"CQoFSU5UMTYQBRIJCgVJTlQzMhAGEgkKBUlOVDY0EAcSCgoGU1RSSU5HEAgS",
"CAoEQk9PTBAJEgsKB0ZMT0FUMTYQChIKCgZET1VCTEUQCxIKCgZVSU5UMzIQ",
"DBIKCgZVSU5UNjQQDRINCglDT01QTEVYNjQQDhIOCgpDT01QTEVYMTI4EA8S",
"DAoIQkZMT0FUMTYQECKVAQoQVGVuc29yU2hhcGVQcm90bxItCgNkaW0YASAD",
"KAsyIC5vbm54LlRlbnNvclNoYXBlUHJvdG8uRGltZW5zaW9uGlIKCURpbWVu",
"c2lvbhITCglkaW1fdmFsdWUYASABKANIABITCglkaW1fcGFyYW0YAiABKAlI",
"ABISCgpkZW5vdGF0aW9uGAMgASgJQgcKBXZhbHVlIsIECglUeXBlUHJvdG8S",
"LQoLdGVuc29yX3R5cGUYASABKAsyFi5vbm54LlR5cGVQcm90by5UZW5zb3JI",
"ABIxCg1zZXF1ZW5jZV90eXBlGAQgASgLMhgub25ueC5UeXBlUHJvdG8uU2Vx",
"dWVuY2VIABInCghtYXBfdHlwZRgFIAEoCzITLm9ubnguVHlwZVByb3RvLk1h",
"cEgAEi0KC29wYXF1ZV90eXBlGAcgASgLMhYub25ueC5UeXBlUHJvdG8uT3Bh",
"cXVlSAASOgoSc3BhcnNlX3RlbnNvcl90eXBlGAggASgLMhwub25ueC5UeXBl",
"UHJvdG8uU3BhcnNlVGVuc29ySAASEgoKZGVub3RhdGlvbhgGIAEoCRpCCgZU",
"ZW5zb3ISEQoJZWxlbV90eXBlGAEgASgFEiUKBXNoYXBlGAIgASgLMhYub25u",
"eC5UZW5zb3JTaGFwZVByb3RvGi4KCFNlcXVlbmNlEiIKCWVsZW1fdHlwZRgB",
"IAEoCzIPLm9ubnguVHlwZVByb3RvGjwKA01hcBIQCghrZXlfdHlwZRgBIAEo",
"BRIjCgp2YWx1ZV90eXBlGAIgASgLMg8ub25ueC5UeXBlUHJvdG8aJgoGT3Bh",
"cXVlEg4KBmRvbWFpbhgBIAEoCRIMCgRuYW1lGAIgASgJGkgKDFNwYXJzZVRl",
"bnNvchIRCgllbGVtX3R5cGUYASABKAUSJQoFc2hhcGUYAiABKAsyFi5vbm54",
"LlRlbnNvclNoYXBlUHJvdG9CBwoFdmFsdWUiNQoST3BlcmF0b3JTZXRJZFBy",
"b3RvEg4KBmRvbWFpbhgBIAEoCRIPCgd2ZXJzaW9uGAIgASgDKmMKB1ZlcnNp",
"b24SEgoOX1NUQVJUX1ZFUlNJT04QABIZChVJUl9WRVJTSU9OXzIwMTdfMTBf",
"MTAQARIZChVJUl9WRVJTSU9OXzIwMTdfMTBfMzAQAhIOCgpJUl9WRVJTSU9O",
"EANiBnByb3RvMw=="));
"EhAKCHJhd19kYXRhGAkgASgMEjMKDWV4dGVybmFsX2RhdGEYDSADKAsyHC5v",
"bm54LlN0cmluZ1N0cmluZ0VudHJ5UHJvdG8SNQoNZGF0YV9sb2NhdGlvbhgO",
"IAEoDjIeLm9ubnguVGVuc29yUHJvdG8uRGF0YUxvY2F0aW9uEhcKC2RvdWJs",
"ZV9kYXRhGAogAygBQgIQARIXCgt1aW50NjRfZGF0YRgLIAMoBEICEAEaJQoH",
"U2VnbWVudBINCgViZWdpbhgBIAEoAxILCgNlbmQYAiABKAMi2gEKCERhdGFU",
"eXBlEg0KCVVOREVGSU5FRBAAEgkKBUZMT0FUEAESCQoFVUlOVDgQAhIICgRJ",
"TlQ4EAMSCgoGVUlOVDE2EAQSCQoFSU5UMTYQBRIJCgVJTlQzMhAGEgkKBUlO",
"VDY0EAcSCgoGU1RSSU5HEAgSCAoEQk9PTBAJEgsKB0ZMT0FUMTYQChIKCgZE",
"T1VCTEUQCxIKCgZVSU5UMzIQDBIKCgZVSU5UNjQQDRINCglDT01QTEVYNjQQ",
"DhIOCgpDT01QTEVYMTI4EA8SDAoIQkZMT0FUMTYQECIpCgxEYXRhTG9jYXRp",
"b24SCwoHREVGQVVMVBAAEgwKCEVYVEVSTkFMEAEilQEKEFRlbnNvclNoYXBl",
"UHJvdG8SLQoDZGltGAEgAygLMiAub25ueC5UZW5zb3JTaGFwZVByb3RvLkRp",
"bWVuc2lvbhpSCglEaW1lbnNpb24SEwoJZGltX3ZhbHVlGAEgASgDSAASEwoJ",
"ZGltX3BhcmFtGAIgASgJSAASEgoKZGVub3RhdGlvbhgDIAEoCUIHCgV2YWx1",
"ZSLCBAoJVHlwZVByb3RvEi0KC3RlbnNvcl90eXBlGAEgASgLMhYub25ueC5U",
"eXBlUHJvdG8uVGVuc29ySAASMQoNc2VxdWVuY2VfdHlwZRgEIAEoCzIYLm9u",
"bnguVHlwZVByb3RvLlNlcXVlbmNlSAASJwoIbWFwX3R5cGUYBSABKAsyEy5v",
"bm54LlR5cGVQcm90by5NYXBIABItCgtvcGFxdWVfdHlwZRgHIAEoCzIWLm9u",
"bnguVHlwZVByb3RvLk9wYXF1ZUgAEjoKEnNwYXJzZV90ZW5zb3JfdHlwZRgI",
"IAEoCzIcLm9ubnguVHlwZVByb3RvLlNwYXJzZVRlbnNvckgAEhIKCmRlbm90",
"YXRpb24YBiABKAkaQgoGVGVuc29yEhEKCWVsZW1fdHlwZRgBIAEoBRIlCgVz",
"aGFwZRgCIAEoCzIWLm9ubnguVGVuc29yU2hhcGVQcm90bxouCghTZXF1ZW5j",
"ZRIiCgllbGVtX3R5cGUYASABKAsyDy5vbm54LlR5cGVQcm90bxo8CgNNYXAS",
"EAoIa2V5X3R5cGUYASABKAUSIwoKdmFsdWVfdHlwZRgCIAEoCzIPLm9ubngu",
"VHlwZVByb3RvGiYKBk9wYXF1ZRIOCgZkb21haW4YASABKAkSDAoEbmFtZRgC",
"IAEoCRpICgxTcGFyc2VUZW5zb3ISEQoJZWxlbV90eXBlGAEgASgFEiUKBXNo",
"YXBlGAIgASgLMhYub25ueC5UZW5zb3JTaGFwZVByb3RvQgcKBXZhbHVlIjUK",
"Ek9wZXJhdG9yU2V0SWRQcm90bxIOCgZkb21haW4YASABKAkSDwoHdmVyc2lv",
"bhgCIAEoAyp9CgdWZXJzaW9uEhIKDl9TVEFSVF9WRVJTSU9OEAASGQoVSVJf",
"VkVSU0lPTl8yMDE3XzEwXzEwEAESGQoVSVJfVkVSU0lPTl8yMDE3XzEwXzMw",
"EAISGAoUSVJfVkVSU0lPTl8yMDE3XzExXzMQAxIOCgpJUl9WRVJTSU9OEARi",
"BnByb3RvMw=="));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { },
new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Onnx.Version), }, new pbr::GeneratedClrTypeInfo[] {
@ -95,7 +99,7 @@ namespace Onnx {
new pbr::GeneratedClrTypeInfo(typeof(global::Onnx.ModelProto), global::Onnx.ModelProto.Parser, new[]{ "IrVersion", "OpsetImport", "ProducerName", "ProducerVersion", "Domain", "ModelVersion", "DocString", "Graph", "MetadataProps" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Onnx.StringStringEntryProto), global::Onnx.StringStringEntryProto.Parser, new[]{ "Key", "Value" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Onnx.GraphProto), global::Onnx.GraphProto.Parser, new[]{ "Node", "Name", "Initializer", "DocString", "Input", "Output", "ValueInfo" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Onnx.TensorProto), global::Onnx.TensorProto.Parser, new[]{ "Dims", "DataType", "Segment", "FloatData", "Int32Data", "StringData", "Int64Data", "Name", "DocString", "RawData", "DoubleData", "Uint64Data" }, null, new[]{ typeof(global::Onnx.TensorProto.Types.DataType) }, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Onnx.TensorProto.Types.Segment), global::Onnx.TensorProto.Types.Segment.Parser, new[]{ "Begin", "End" }, null, null, null)}),
new pbr::GeneratedClrTypeInfo(typeof(global::Onnx.TensorProto), global::Onnx.TensorProto.Parser, new[]{ "Dims", "DataType", "Segment", "FloatData", "Int32Data", "StringData", "Int64Data", "Name", "DocString", "RawData", "ExternalData", "DataLocation", "DoubleData", "Uint64Data" }, null, new[]{ typeof(global::Onnx.TensorProto.Types.DataType), typeof(global::Onnx.TensorProto.Types.DataLocation) }, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Onnx.TensorProto.Types.Segment), global::Onnx.TensorProto.Types.Segment.Parser, new[]{ "Begin", "End" }, null, null, null)}),
new pbr::GeneratedClrTypeInfo(typeof(global::Onnx.TensorShapeProto), global::Onnx.TensorShapeProto.Parser, new[]{ "Dim" }, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Onnx.TensorShapeProto.Types.Dimension), global::Onnx.TensorShapeProto.Types.Dimension.Parser, new[]{ "DimValue", "DimParam", "Denotation" }, new[]{ "Value" }, null, null)}),
new pbr::GeneratedClrTypeInfo(typeof(global::Onnx.TypeProto), global::Onnx.TypeProto.Parser, new[]{ "TensorType", "SequenceType", "MapType", "OpaqueType", "SparseTensorType", "Denotation" }, new[]{ "Value" }, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Onnx.TypeProto.Types.Tensor), global::Onnx.TypeProto.Types.Tensor.Parser, new[]{ "ElemType", "Shape" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Onnx.TypeProto.Types.Sequence), global::Onnx.TypeProto.Types.Sequence.Parser, new[]{ "ElemType" }, null, null, null),
@ -143,7 +147,13 @@ namespace Onnx {
/// - Added opset_import in ModelProto
/// - For vendor extensions, added domain in NodeProto
/// </summary>
[pbr::OriginalName("IR_VERSION")] IrVersion = 3,
[pbr::OriginalName("IR_VERSION_2017_11_3")] IrVersion2017113 = 3,
/// <summary>
/// IR VERSION 4 published on Jan 22, 2019
/// - Relax constraint that initializers should be a subset of graph inputs
/// - Add type BFLOAT16
/// </summary>
[pbr::OriginalName("IR_VERSION")] IrVersion = 4,
}
#endregion
@ -1846,7 +1856,7 @@ namespace Onnx {
/// <summary>
/// A list of named tensor values, used to specify constant inputs of the graph.
/// Each TensorProto entry must have a distinct name (within the list) that
/// also appears in the input list.
/// MAY also appear in the input list.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public pbc::RepeatedField<global::Onnx.TensorProto> Initializer {
@ -2089,6 +2099,8 @@ namespace Onnx {
name_ = other.name_;
docString_ = other.docString_;
rawData_ = other.rawData_;
externalData_ = other.externalData_.Clone();
dataLocation_ = other.dataLocation_;
doubleData_ = other.doubleData_.Clone();
uint64Data_ = other.uint64Data_.Clone();
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
@ -2261,6 +2273,41 @@ namespace Onnx {
}
}
/// <summary>Field number for the "external_data" field.</summary>
public const int ExternalDataFieldNumber = 13;
private static readonly pb::FieldCodec<global::Onnx.StringStringEntryProto> _repeated_externalData_codec
= pb::FieldCodec.ForMessage(106, global::Onnx.StringStringEntryProto.Parser);
private readonly pbc::RepeatedField<global::Onnx.StringStringEntryProto> externalData_ = new pbc::RepeatedField<global::Onnx.StringStringEntryProto>();
/// <summary>
/// Data can be stored inside the protobuf file using type-specific fields or raw_data.
/// Alternatively, raw bytes data can be stored in an external file, using the external_data field.
/// external_data stores key-value pairs describing data location. Recognized keys are:
/// - "location" (required) - POSIX filesystem path relative to the directory where the ONNX
/// protobuf model was stored
/// - "offset" (optional) - position of byte at which stored data begins. Integer stored as string.
/// Offset values SHOULD be multiples 4096 (page size) to enable mmap support.
/// - "length" (optional) - number of bytes containing data. Integer stored as string.
/// - "checksum" (optional) - SHA1 digest of file specified in under 'location' key.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public pbc::RepeatedField<global::Onnx.StringStringEntryProto> ExternalData {
get { return externalData_; }
}
/// <summary>Field number for the "data_location" field.</summary>
public const int DataLocationFieldNumber = 14;
private global::Onnx.TensorProto.Types.DataLocation dataLocation_ = 0;
/// <summary>
/// If value not set, data is stored in raw_data (if set) otherwise in type-specified field.
/// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public global::Onnx.TensorProto.Types.DataLocation DataLocation {
get { return dataLocation_; }
set {
dataLocation_ = value;
}
}
/// <summary>Field number for the "double_data" field.</summary>
public const int DoubleDataFieldNumber = 10;
private static readonly pb::FieldCodec<double> _repeated_doubleData_codec
@ -2318,6 +2365,8 @@ namespace Onnx {
if (Name != other.Name) return false;
if (DocString != other.DocString) return false;
if (RawData != other.RawData) return false;
if(!externalData_.Equals(other.externalData_)) return false;
if (DataLocation != other.DataLocation) return false;
if(!doubleData_.Equals(other.doubleData_)) return false;
if(!uint64Data_.Equals(other.uint64Data_)) return false;
return Equals(_unknownFields, other._unknownFields);
@ -2336,6 +2385,8 @@ namespace Onnx {
if (Name.Length != 0) hash ^= Name.GetHashCode();
if (DocString.Length != 0) hash ^= DocString.GetHashCode();
if (RawData.Length != 0) hash ^= RawData.GetHashCode();
hash ^= externalData_.GetHashCode();
if (DataLocation != 0) hash ^= DataLocation.GetHashCode();
hash ^= doubleData_.GetHashCode();
hash ^= uint64Data_.GetHashCode();
if (_unknownFields != null) {
@ -2378,6 +2429,11 @@ namespace Onnx {
output.WriteRawTag(98);
output.WriteString(DocString);
}
externalData_.WriteTo(output, _repeated_externalData_codec);
if (DataLocation != 0) {
output.WriteRawTag(112);
output.WriteEnum((int) DataLocation);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
@ -2406,6 +2462,10 @@ namespace Onnx {
if (RawData.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeBytesSize(RawData);
}
size += externalData_.CalculateSize(_repeated_externalData_codec);
if (DataLocation != 0) {
size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) DataLocation);
}
size += doubleData_.CalculateSize(_repeated_doubleData_codec);
size += uint64Data_.CalculateSize(_repeated_uint64Data_codec);
if (_unknownFields != null) {
@ -2442,6 +2502,10 @@ namespace Onnx {
if (other.RawData.Length != 0) {
RawData = other.RawData;
}
externalData_.Add(other.externalData_);
if (other.DataLocation != 0) {
DataLocation = other.DataLocation;
}
doubleData_.Add(other.doubleData_);
uint64Data_.Add(other.uint64Data_);
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
@ -2512,6 +2576,14 @@ namespace Onnx {
DocString = input.ReadString();
break;
}
case 106: {
externalData_.AddEntriesFrom(input, _repeated_externalData_codec);
break;
}
case 112: {
dataLocation_ = (global::Onnx.TensorProto.Types.DataLocation) input.ReadEnum();
break;
}
}
}
}
@ -2582,6 +2654,16 @@ namespace Onnx {
[pbr::OriginalName("BFLOAT16")] Bfloat16 = 16,
}
/// <summary>
/// Location of the data for this tensor. MUST be one of:
/// - DEFAULT - data stored inside the protobuf message. Data is stored in raw_data (if set) otherwise in type-specified field.
/// - EXTERNAL - data stored in an external location as described by external_data field.
/// </summary>
public enum DataLocation {
[pbr::OriginalName("DEFAULT")] Default = 0,
[pbr::OriginalName("EXTERNAL")] External = 1,
}
/// <summary>
/// For very large tensors, we may want to store them in chunks, in which
/// case the following fields will specify the segment that is stored in