diff --git a/src/TensorFlowNET.Core/Tensors/Tensor.Creation.cs b/src/TensorFlowNET.Core/Tensors/Tensor.Creation.cs index f6d49192..2032374a 100644 --- a/src/TensorFlowNET.Core/Tensors/Tensor.Creation.cs +++ b/src/TensorFlowNET.Core/Tensors/Tensor.Creation.cs @@ -29,9 +29,9 @@ namespace Tensorflow public partial class Tensor { /// - /// if original buffer is free. + /// true if unmanaged buffer has been freed. /// - private bool deallocator_called; + private bool deallocator_called => _deallocatorArgs.deallocator_called; public Tensor(IntPtr handle) { @@ -45,210 +45,395 @@ namespace Tensorflow /// /// Create a 1d Tensor from the given linear array and shape /// - public Tensor(#1[] data) + public Tensor(#1[] data, TF_DataType? dType = null) { - _handle = CreateTensorWithoutCopying(dtypes.as_dtype(typeof(#1)), new long[]{data.Length}, data, Marshal.SizeOf<#1>()); + _handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(#1)), new long[]{data.Length}, data, Marshal.SizeOf<#1>()); } /// /// Create a N-dimensional Tensor from the given array /// - public Tensor(#1[] data, long[] shape) + public Tensor(#1[] data, long[] shape, TF_DataType? dType = null) { - _handle = CreateTensorWithoutCopying(dtypes.as_dtype(typeof(#1)), shape, data, Marshal.SizeOf<#1>()); + _handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(#1)), shape, data, Marshal.SizeOf<#1>()); } + /// + /// Create a scalar Tensor from the given value + /// + public unsafe Tensor(#1 value, TF_DataType? dType = null) + { + var v = (#1*)Marshal.AllocHGlobal(sizeof(#1)); + *v = value; + Deallocator deallocator = (IntPtr values, IntPtr len, ref DeallocatorArgs arg) => { + Marshal.FreeHGlobal(values); + arg.deallocator_called = true; + //_handle = IntPtr.Zero; + }; + _handle = TF_NewTensor(dType ?? dtypes.as_dtype(typeof(#1)), dims:new long[0], num_dims: 0, data: (IntPtr)v, len: (UIntPtr)sizeof(#1), deallocator: deallocator, ref _deallocatorArgs); + } % #else - /// /// Create a 1d Tensor from the given linear array and shape /// - public Tensor(sbyte[] data) + public Tensor(sbyte[] data, TF_DataType? dType = null) { - _handle = CreateTensorWithoutCopying(dtypes.as_dtype(typeof(sbyte)), new long[]{data.Length}, data, Marshal.SizeOf()); + _handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(sbyte)), new long[]{data.Length}, data, Marshal.SizeOf()); } /// /// Create a N-dimensional Tensor from the given array /// - public Tensor(sbyte[] data, long[] shape) + public Tensor(sbyte[] data, long[] shape, TF_DataType? dType = null) { - _handle = CreateTensorWithoutCopying(dtypes.as_dtype(typeof(sbyte)), shape, data, Marshal.SizeOf()); + _handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(sbyte)), shape, data, Marshal.SizeOf()); } + /// + /// Create a scalar Tensor from the given value + /// + public unsafe Tensor(sbyte value, TF_DataType? dType = null) + { + var v = (sbyte*)Marshal.AllocHGlobal(sizeof(sbyte)); + *v = value; + Deallocator deallocator = (IntPtr values, IntPtr len, ref DeallocatorArgs arg) => { + Marshal.FreeHGlobal(values); + arg.deallocator_called = true; + //_handle = IntPtr.Zero; + }; + _handle = TF_NewTensor(dType ?? dtypes.as_dtype(typeof(sbyte)), dims:new long[0], num_dims: 0, data: (IntPtr)v, len: (UIntPtr)sizeof(sbyte), deallocator: deallocator, ref _deallocatorArgs); + } /// /// Create a 1d Tensor from the given linear array and shape /// - public Tensor(byte[] data) + public Tensor(byte[] data, TF_DataType? dType = null) { - _handle = CreateTensorWithoutCopying(dtypes.as_dtype(typeof(byte)), new long[]{data.Length}, data, Marshal.SizeOf()); + _handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(byte)), new long[]{data.Length}, data, Marshal.SizeOf()); } /// /// Create a N-dimensional Tensor from the given array /// - public Tensor(byte[] data, long[] shape) + public Tensor(byte[] data, long[] shape, TF_DataType? dType = null) { - _handle = CreateTensorWithoutCopying(dtypes.as_dtype(typeof(byte)), shape, data, Marshal.SizeOf()); + _handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(byte)), shape, data, Marshal.SizeOf()); } + /// + /// Create a scalar Tensor from the given value + /// + public unsafe Tensor(byte value, TF_DataType? dType = null) + { + var v = (byte*)Marshal.AllocHGlobal(sizeof(byte)); + *v = value; + Deallocator deallocator = (IntPtr values, IntPtr len, ref DeallocatorArgs arg) => { + Marshal.FreeHGlobal(values); + arg.deallocator_called = true; + //_handle = IntPtr.Zero; + }; + _handle = TF_NewTensor(dType ?? dtypes.as_dtype(typeof(byte)), dims:new long[0], num_dims: 0, data: (IntPtr)v, len: (UIntPtr)sizeof(byte), deallocator: deallocator, ref _deallocatorArgs); + } /// /// Create a 1d Tensor from the given linear array and shape /// - public Tensor(short[] data) + public Tensor(short[] data, TF_DataType? dType = null) { - _handle = CreateTensorWithoutCopying(dtypes.as_dtype(typeof(short)), new long[]{data.Length}, data, Marshal.SizeOf()); + _handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(short)), new long[]{data.Length}, data, Marshal.SizeOf()); } /// /// Create a N-dimensional Tensor from the given array /// - public Tensor(short[] data, long[] shape) + public Tensor(short[] data, long[] shape, TF_DataType? dType = null) { - _handle = CreateTensorWithoutCopying(dtypes.as_dtype(typeof(short)), shape, data, Marshal.SizeOf()); + _handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(short)), shape, data, Marshal.SizeOf()); } + /// + /// Create a scalar Tensor from the given value + /// + public unsafe Tensor(short value, TF_DataType? dType = null) + { + var v = (short*)Marshal.AllocHGlobal(sizeof(short)); + *v = value; + Deallocator deallocator = (IntPtr values, IntPtr len, ref DeallocatorArgs arg) => { + Marshal.FreeHGlobal(values); + arg.deallocator_called = true; + //_handle = IntPtr.Zero; + }; + _handle = TF_NewTensor(dType ?? dtypes.as_dtype(typeof(short)), dims:new long[0], num_dims: 0, data: (IntPtr)v, len: (UIntPtr)sizeof(short), deallocator: deallocator, ref _deallocatorArgs); + } /// /// Create a 1d Tensor from the given linear array and shape /// - public Tensor(ushort[] data) + public Tensor(ushort[] data, TF_DataType? dType = null) { - _handle = CreateTensorWithoutCopying(dtypes.as_dtype(typeof(ushort)), new long[]{data.Length}, data, Marshal.SizeOf()); + _handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(ushort)), new long[]{data.Length}, data, Marshal.SizeOf()); } /// /// Create a N-dimensional Tensor from the given array /// - public Tensor(ushort[] data, long[] shape) + public Tensor(ushort[] data, long[] shape, TF_DataType? dType = null) { - _handle = CreateTensorWithoutCopying(dtypes.as_dtype(typeof(ushort)), shape, data, Marshal.SizeOf()); + _handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(ushort)), shape, data, Marshal.SizeOf()); } + /// + /// Create a scalar Tensor from the given value + /// + public unsafe Tensor(ushort value, TF_DataType? dType = null) + { + var v = (ushort*)Marshal.AllocHGlobal(sizeof(ushort)); + *v = value; + Deallocator deallocator = (IntPtr values, IntPtr len, ref DeallocatorArgs arg) => { + Marshal.FreeHGlobal(values); + arg.deallocator_called = true; + //_handle = IntPtr.Zero; + }; + _handle = TF_NewTensor(dType ?? dtypes.as_dtype(typeof(ushort)), dims:new long[0], num_dims: 0, data: (IntPtr)v, len: (UIntPtr)sizeof(ushort), deallocator: deallocator, ref _deallocatorArgs); + } /// /// Create a 1d Tensor from the given linear array and shape /// - public Tensor(int[] data) + public Tensor(int[] data, TF_DataType? dType = null) { - _handle = CreateTensorWithoutCopying(dtypes.as_dtype(typeof(int)), new long[]{data.Length}, data, Marshal.SizeOf()); + _handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(int)), new long[]{data.Length}, data, Marshal.SizeOf()); } /// /// Create a N-dimensional Tensor from the given array /// - public Tensor(int[] data, long[] shape) + public Tensor(int[] data, long[] shape, TF_DataType? dType = null) { - _handle = CreateTensorWithoutCopying(dtypes.as_dtype(typeof(int)), shape, data, Marshal.SizeOf()); + _handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(int)), shape, data, Marshal.SizeOf()); } + /// + /// Create a scalar Tensor from the given value + /// + public unsafe Tensor(int value, TF_DataType? dType = null) + { + var v = (int*)Marshal.AllocHGlobal(sizeof(int)); + *v = value; + Deallocator deallocator = (IntPtr values, IntPtr len, ref DeallocatorArgs arg) => { + Marshal.FreeHGlobal(values); + arg.deallocator_called = true; + //_handle = IntPtr.Zero; + }; + _handle = TF_NewTensor(dType ?? dtypes.as_dtype(typeof(int)), dims:new long[0], num_dims: 0, data: (IntPtr)v, len: (UIntPtr)sizeof(int), deallocator: deallocator, ref _deallocatorArgs); + } /// /// Create a 1d Tensor from the given linear array and shape /// - public Tensor(uint[] data) + public Tensor(uint[] data, TF_DataType? dType = null) { - _handle = CreateTensorWithoutCopying(dtypes.as_dtype(typeof(uint)), new long[]{data.Length}, data, Marshal.SizeOf()); + _handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(uint)), new long[]{data.Length}, data, Marshal.SizeOf()); } /// /// Create a N-dimensional Tensor from the given array /// - public Tensor(uint[] data, long[] shape) + public Tensor(uint[] data, long[] shape, TF_DataType? dType = null) { - _handle = CreateTensorWithoutCopying(dtypes.as_dtype(typeof(uint)), shape, data, Marshal.SizeOf()); + _handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(uint)), shape, data, Marshal.SizeOf()); } + /// + /// Create a scalar Tensor from the given value + /// + public unsafe Tensor(uint value, TF_DataType? dType = null) + { + var v = (uint*)Marshal.AllocHGlobal(sizeof(uint)); + *v = value; + Deallocator deallocator = (IntPtr values, IntPtr len, ref DeallocatorArgs arg) => { + Marshal.FreeHGlobal(values); + arg.deallocator_called = true; + //_handle = IntPtr.Zero; + }; + _handle = TF_NewTensor(dType ?? dtypes.as_dtype(typeof(uint)), dims:new long[0], num_dims: 0, data: (IntPtr)v, len: (UIntPtr)sizeof(uint), deallocator: deallocator, ref _deallocatorArgs); + } /// /// Create a 1d Tensor from the given linear array and shape /// - public Tensor(long[] data) + public Tensor(long[] data, TF_DataType? dType = null) { - _handle = CreateTensorWithoutCopying(dtypes.as_dtype(typeof(long)), new long[]{data.Length}, data, Marshal.SizeOf()); + _handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(long)), new long[]{data.Length}, data, Marshal.SizeOf()); } /// /// Create a N-dimensional Tensor from the given array /// - public Tensor(long[] data, long[] shape) + public Tensor(long[] data, long[] shape, TF_DataType? dType = null) { - _handle = CreateTensorWithoutCopying(dtypes.as_dtype(typeof(long)), shape, data, Marshal.SizeOf()); + _handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(long)), shape, data, Marshal.SizeOf()); } + /// + /// Create a scalar Tensor from the given value + /// + public unsafe Tensor(long value, TF_DataType? dType = null) + { + var v = (long*)Marshal.AllocHGlobal(sizeof(long)); + *v = value; + Deallocator deallocator = (IntPtr values, IntPtr len, ref DeallocatorArgs arg) => { + Marshal.FreeHGlobal(values); + arg.deallocator_called = true; + //_handle = IntPtr.Zero; + }; + _handle = TF_NewTensor(dType ?? dtypes.as_dtype(typeof(long)), dims:new long[0], num_dims: 0, data: (IntPtr)v, len: (UIntPtr)sizeof(long), deallocator: deallocator, ref _deallocatorArgs); + } /// /// Create a 1d Tensor from the given linear array and shape /// - public Tensor(ulong[] data) + public Tensor(ulong[] data, TF_DataType? dType = null) { - _handle = CreateTensorWithoutCopying(dtypes.as_dtype(typeof(ulong)), new long[]{data.Length}, data, Marshal.SizeOf()); + _handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(ulong)), new long[]{data.Length}, data, Marshal.SizeOf()); } /// /// Create a N-dimensional Tensor from the given array /// - public Tensor(ulong[] data, long[] shape) + public Tensor(ulong[] data, long[] shape, TF_DataType? dType = null) { - _handle = CreateTensorWithoutCopying(dtypes.as_dtype(typeof(ulong)), shape, data, Marshal.SizeOf()); + _handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(ulong)), shape, data, Marshal.SizeOf()); } + /// + /// Create a scalar Tensor from the given value + /// + public unsafe Tensor(ulong value, TF_DataType? dType = null) + { + var v = (ulong*)Marshal.AllocHGlobal(sizeof(ulong)); + *v = value; + Deallocator deallocator = (IntPtr values, IntPtr len, ref DeallocatorArgs arg) => { + Marshal.FreeHGlobal(values); + arg.deallocator_called = true; + //_handle = IntPtr.Zero; + }; + _handle = TF_NewTensor(dType ?? dtypes.as_dtype(typeof(ulong)), dims:new long[0], num_dims: 0, data: (IntPtr)v, len: (UIntPtr)sizeof(ulong), deallocator: deallocator, ref _deallocatorArgs); + } /// /// Create a 1d Tensor from the given linear array and shape /// - public Tensor(float[] data) + public Tensor(float[] data, TF_DataType? dType = null) { - _handle = CreateTensorWithoutCopying(dtypes.as_dtype(typeof(float)), new long[]{data.Length}, data, Marshal.SizeOf()); + _handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(float)), new long[]{data.Length}, data, Marshal.SizeOf()); } /// /// Create a N-dimensional Tensor from the given array /// - public Tensor(float[] data, long[] shape) + public Tensor(float[] data, long[] shape, TF_DataType? dType = null) { - _handle = CreateTensorWithoutCopying(dtypes.as_dtype(typeof(float)), shape, data, Marshal.SizeOf()); + _handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(float)), shape, data, Marshal.SizeOf()); } + /// + /// Create a scalar Tensor from the given value + /// + public unsafe Tensor(float value, TF_DataType? dType = null) + { + var v = (float*)Marshal.AllocHGlobal(sizeof(float)); + *v = value; + Deallocator deallocator = (IntPtr values, IntPtr len, ref DeallocatorArgs arg) => { + Marshal.FreeHGlobal(values); + arg.deallocator_called = true; + //_handle = IntPtr.Zero; + }; + _handle = TF_NewTensor(dType ?? dtypes.as_dtype(typeof(float)), dims:new long[0], num_dims: 0, data: (IntPtr)v, len: (UIntPtr)sizeof(float), deallocator: deallocator, ref _deallocatorArgs); + } /// /// Create a 1d Tensor from the given linear array and shape /// - public Tensor(double[] data) + public Tensor(double[] data, TF_DataType? dType = null) { - _handle = CreateTensorWithoutCopying(dtypes.as_dtype(typeof(double)), new long[]{data.Length}, data, Marshal.SizeOf()); + _handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(double)), new long[]{data.Length}, data, Marshal.SizeOf()); } /// /// Create a N-dimensional Tensor from the given array /// - public Tensor(double[] data, long[] shape) + public Tensor(double[] data, long[] shape, TF_DataType? dType = null) { - _handle = CreateTensorWithoutCopying(dtypes.as_dtype(typeof(double)), shape, data, Marshal.SizeOf()); + _handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(double)), shape, data, Marshal.SizeOf()); } + /// + /// Create a scalar Tensor from the given value + /// + public unsafe Tensor(double value, TF_DataType? dType = null) + { + var v = (double*)Marshal.AllocHGlobal(sizeof(double)); + *v = value; + Deallocator deallocator = (IntPtr values, IntPtr len, ref DeallocatorArgs arg) => { + Marshal.FreeHGlobal(values); + arg.deallocator_called = true; + //_handle = IntPtr.Zero; + }; + _handle = TF_NewTensor(dType ?? dtypes.as_dtype(typeof(double)), dims:new long[0], num_dims: 0, data: (IntPtr)v, len: (UIntPtr)sizeof(double), deallocator: deallocator, ref _deallocatorArgs); + } /// /// Create a 1d Tensor from the given linear array and shape /// - public Tensor(Complex[] data) + public Tensor(Complex[] data, TF_DataType? dType = null) { - _handle = CreateTensorWithoutCopying(dtypes.as_dtype(typeof(Complex)), new long[]{data.Length}, data, Marshal.SizeOf()); + _handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(Complex)), new long[]{data.Length}, data, Marshal.SizeOf()); } /// /// Create a N-dimensional Tensor from the given array /// - public Tensor(Complex[] data, long[] shape) + public Tensor(Complex[] data, long[] shape, TF_DataType? dType = null) + { + _handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(Complex)), shape, data, Marshal.SizeOf()); + } + + /// + /// Create a scalar Tensor from the given value + /// + public unsafe Tensor(Complex value, TF_DataType? dType = null) { - _handle = CreateTensorWithoutCopying(dtypes.as_dtype(typeof(Complex)), shape, data, Marshal.SizeOf()); + var v = (Complex*)Marshal.AllocHGlobal(sizeof(Complex)); + *v = value; + Deallocator deallocator = (IntPtr values, IntPtr len, ref DeallocatorArgs arg) => { + Marshal.FreeHGlobal(values); + arg.deallocator_called = true; + //_handle = IntPtr.Zero; + }; + _handle = TF_NewTensor(dType ?? dtypes.as_dtype(typeof(Complex)), dims:new long[0], num_dims: 0, data: (IntPtr)v, len: (UIntPtr)sizeof(Complex), deallocator: deallocator, ref _deallocatorArgs); } #endif + /// + /// Create a string Tensor from the given string + /// + public unsafe Tensor(string str) + { + var buffer = Encoding.UTF8.GetBytes(str); + var size = c_api.TF_StringEncodedSize((UIntPtr)buffer.Length); + var handle = TF_AllocateTensor(TF_DataType.TF_STRING, IntPtr.Zero, 0, (UIntPtr)((ulong)size + 8)); + + IntPtr tensor = c_api.TF_TensorData(handle); + Marshal.WriteInt64(tensor, 0); + fixed (byte* src = &buffer[0]) + c_api.TF_StringEncode(src, (UIntPtr)buffer.Length, (sbyte*)(tensor + sizeof(Int64)), size, status); + _handle = handle; + status.Check(true); + } + public Tensor(NDArray nd, TF_DataType? tensorDType = null) { _handle = Allocate(nd, tensorDType: tensorDType); @@ -309,16 +494,16 @@ namespace Tensorflow Marshal.Copy(nd1.Data(), 0, dotHandle, nd.size); break; case "String": - return new Tensor(UTF8Encoding.UTF8.GetBytes(nd.Data(0))); + return new Tensor(UTF8Encoding.UTF8.GetBytes(nd.Data(0)), TF_DataType.TF_STRING); default: throw new NotImplementedException($"Marshal.Copy failed for {nd.dtype.Name}."); } // Free the original buffer and set flag - Deallocator deallocator = (IntPtr values, IntPtr len, ref bool closure) => + Deallocator deallocator = (IntPtr values, IntPtr len, ref DeallocatorArgs args) => { Marshal.FreeHGlobal(values); - closure = true; + args.deallocator_called = true; }; var tfHandle = c_api.TF_NewTensor(dataType, @@ -327,7 +512,7 @@ namespace Tensorflow dotHandle, (UIntPtr)buffersize, deallocator, - ref deallocator_called); + ref _deallocatorArgs); return tfHandle; } @@ -340,6 +525,8 @@ namespace Tensorflow _id = ops.uid(); } + private bool _isPinnedArray = false; + /// /// Creates a new tensor from the given array without copying memory. The array is pinned down and the pointer passed on. /// @@ -356,8 +543,8 @@ namespace Tensorflow protected IntPtr CreateTensorWithoutCopying(TF_DataType dt, long[] shape, Array data, int element_size) { return CreateTensorWithoutCopying(dt, shape, data, 0, data.Length, element_size); - } - + } + /// /// Creates a new tensor from a subsection of the given array without copying memory. The array is pinned down and the pointer passed on. /// @@ -373,25 +560,29 @@ namespace Tensorflow /// specified dimensions. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected IntPtr CreateTensorWithoutCopying(TF_DataType dt, long[] shape, Array data, int start, int count, int element_size) + protected unsafe IntPtr CreateTensorWithoutCopying(TF_DataType dt, long[] shape, Array data, int start, int count, int element_size) { if (start < 0 || start > data.Length - count) throw new ArgumentException($"Array length {data.Length} does not match the given shape {new Shape(shape.Cast().ToArray())}"); - - // get a handle to the pinned array which we will pass on to the tensor computation engine to use - var dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned); + // get a handle to the pinned array which we will pass on to the tensor computation engine to use + var gcHandle = GCHandle.Alloc(data, GCHandleType.Pinned); + _isPinnedArray = true; + _deallocatorArgs=new DeallocatorArgs(){ gc_handle = GCHandle.ToIntPtr( gcHandle) }; // Free the original buffer and set flag - Deallocator deallocator = (IntPtr values, IntPtr len, ref bool closure) => + Deallocator deallocator = (IntPtr ptr, IntPtr len, ref DeallocatorArgs args) => { - dataHandle.Free(); - closure = true; + // note: since the ptr given to tensorflow is just the addr of the pinned object we can not directly free it! we need to free the gcHandle instead + GCHandle.FromIntPtr(args.gc_handle).Free(); + args.deallocator_called = true; }; - if (shape == null) - return TF_NewTensor(dt, null, 0, dataHandle.AddrOfPinnedObject() + start * element_size, (UIntPtr)(count * element_size), deallocator, ref deallocator_called); + if (shape == null || shape.Length==0) + return TF_NewTensor(dt, new long[0], 0, gcHandle.AddrOfPinnedObject() + start * element_size, (UIntPtr)(count * element_size), deallocator, ref _deallocatorArgs); else - return TF_NewTensor(dt, shape, shape.Length, dataHandle.AddrOfPinnedObject() + start * element_size, (UIntPtr)(count * element_size), deallocator, ref deallocator_called); + return TF_NewTensor(dt, shape, shape.Length, gcHandle.AddrOfPinnedObject() + start * element_size, (UIntPtr)(count * element_size), deallocator, ref _deallocatorArgs); } + + private DeallocatorArgs _deallocatorArgs=new DeallocatorArgs(); } } diff --git a/src/TensorFlowNET.Core/Tensors/Tensor.cs b/src/TensorFlowNET.Core/Tensors/Tensor.cs index cc54c667..06b245af 100644 --- a/src/TensorFlowNET.Core/Tensors/Tensor.cs +++ b/src/TensorFlowNET.Core/Tensors/Tensor.cs @@ -44,7 +44,7 @@ namespace Tensorflow /// /// The string name of this tensor. /// - public string name => $"{(op == null ? "Operation was not named" : $"{op.name}:{_value_index}")}"; + public string name => $"{(op == null ? "" : $"{op.name}:{_value_index}")}"; private int _value_index; public int value_index => _value_index; @@ -350,8 +350,11 @@ namespace Tensorflow public void Dispose() { - c_api.TF_DeleteTensor(_handle); - _handle = IntPtr.Zero; + if (_handle != IntPtr.Zero) + { + c_api.TF_DeleteTensor(_handle); + _handle = IntPtr.Zero; + } status.Dispose(); }