| @@ -1,27 +0,0 @@ | |||||
| namespace Tensorflow | |||||
| { | |||||
| /// <summary> | |||||
| /// Used internally to | |||||
| /// </summary> | |||||
| public enum AllocationType | |||||
| { | |||||
| None = 0, | |||||
| /// <summary> | |||||
| /// Allocation was done by passing in a pointer, might be also holding reference to a C# object. | |||||
| /// </summary> | |||||
| FromPointer = 1, | |||||
| /// <summary> | |||||
| /// Allocation was done by calling c_api.TF_AllocateTensor or TF decided it has to copy data during c_api.TF_NewTensor. <br></br> | |||||
| /// Deallocation is handled solely by Tensorflow. | |||||
| /// </summary> | |||||
| Tensorflow = 2, | |||||
| /// <summary> | |||||
| /// Allocation was done by Marshal.AllocateHGlobal | |||||
| /// </summary> | |||||
| Marshal = 3, | |||||
| /// <summary> | |||||
| /// Allocation was done by GCHandle.Alloc | |||||
| /// </summary> | |||||
| GCHandle = 4, | |||||
| } | |||||
| } | |||||
| @@ -19,8 +19,6 @@ using System; | |||||
| using System.Diagnostics.CodeAnalysis; | using System.Diagnostics.CodeAnalysis; | ||||
| using System.Linq; | using System.Linq; | ||||
| using System.Numerics; | using System.Numerics; | ||||
| using System.Runtime.CompilerServices; | |||||
| using System.Runtime.InteropServices; | |||||
| using System.Text; | using System.Text; | ||||
| using static Tensorflow.c_api; | using static Tensorflow.c_api; | ||||
| @@ -29,21 +27,6 @@ namespace Tensorflow | |||||
| [SuppressMessage("ReSharper", "InvokeAsExtensionMethod")] | [SuppressMessage("ReSharper", "InvokeAsExtensionMethod")] | ||||
| public partial class Tensor | public partial class Tensor | ||||
| { | { | ||||
| /// <summary> | |||||
| /// The handle that was used to allocate this tensor, dependent on <see cref="AllocationType"/>. | |||||
| /// </summary> | |||||
| protected object AllocationHandle; | |||||
| /// <summary> | |||||
| /// True if this Tensor holds data allocated by C#. | |||||
| /// </summary> | |||||
| public bool IsMemoryOwner => AllocationType >= AllocationType.Marshal; | |||||
| /// <summary> | |||||
| /// The allocation method used to create this Tensor. | |||||
| /// </summary> | |||||
| public AllocationType AllocationType { get; protected set; } | |||||
| public IntPtr TensorDataPointer => _handle == IntPtr.Zero ? IntPtr.Zero : TF_TensorData(_handle); | public IntPtr TensorDataPointer => _handle == IntPtr.Zero ? IntPtr.Zero : TF_TensorData(_handle); | ||||
| public Tensor() | public Tensor() | ||||
| @@ -125,11 +108,7 @@ namespace Tensorflow | |||||
| /// <param name="num_bytes">Size of the tensor in memory</param> | /// <param name="num_bytes">Size of the tensor in memory</param> | ||||
| public Tensor(IntPtr data_ptr, long[] shape, TF_DataType dType, int num_bytes) | public Tensor(IntPtr data_ptr, long[] shape, TF_DataType dType, int num_bytes) | ||||
| { | { | ||||
| unsafe | |||||
| { | |||||
| _handle = TF_NewTensor(dType, dims: shape, num_dims: shape.Length, data: data_ptr, len: (ulong)num_bytes); | |||||
| AllocationType = TF_TensorData(_handle) == data_ptr ? AllocationType.FromPointer : AllocationType.Tensorflow; | |||||
| } | |||||
| _handle = TF_NewTensor(dType, dims: shape, num_dims: shape.Length, data: data_ptr, len: (ulong)num_bytes); | |||||
| } | } | ||||
| public unsafe Tensor(NDArray nd) | public unsafe Tensor(NDArray nd) | ||||
| @@ -93,7 +93,8 @@ namespace Tensorflow | |||||
| /// TFE_TensorHandle | /// TFE_TensorHandle | ||||
| /// </summary> | /// </summary> | ||||
| public SafeTensorHandleHandle EagerTensorHandle { get; set; } | public SafeTensorHandleHandle EagerTensorHandle { get; set; } | ||||
| protected bool _createdInGraphMode; | |||||
| public bool CreatedInGraphMode => _createdInGraphMode; | |||||
| public bool IsEagerTensor => this is EagerTensor; | public bool IsEagerTensor => this is EagerTensor; | ||||
| public bool IsSparseTensor => this is SparseTensor; | public bool IsSparseTensor => this is SparseTensor; | ||||
| @@ -262,29 +263,6 @@ namespace Tensorflow | |||||
| #if TRACK_TENSOR_LIFE | #if TRACK_TENSOR_LIFE | ||||
| print($"Delete Tensor 0x{handle.ToString("x16")} {AllocationType} Data: 0x{TensorDataPointer.ToString("x16")}"); | print($"Delete Tensor 0x{handle.ToString("x16")} {AllocationType} Data: 0x{TensorDataPointer.ToString("x16")}"); | ||||
| #endif | #endif | ||||
| if (AllocationHandle != null) | |||||
| { | |||||
| if (AllocationType == AllocationType.GCHandle) | |||||
| { | |||||
| ((GCHandle)AllocationHandle).Free(); | |||||
| AllocationHandle = null; | |||||
| AllocationType = AllocationType.None; | |||||
| } | |||||
| else if (AllocationType == AllocationType.Marshal) | |||||
| { | |||||
| Marshal.FreeHGlobal((IntPtr)AllocationHandle); | |||||
| AllocationHandle = null; | |||||
| AllocationType = AllocationType.None; | |||||
| } | |||||
| else if (AllocationType == AllocationType.FromPointer) | |||||
| { | |||||
| AllocationHandle = null; | |||||
| AllocationType = AllocationType.None; | |||||
| } | |||||
| else | |||||
| throw new InvalidOperationException($"Tensor.AllocationHandle is not null ({AllocationHandle}) but AllocationType is not matched to a C# allocation type ({AllocationType})."); | |||||
| } | |||||
| if (dtype == TF_DataType.TF_STRING) | if (dtype == TF_DataType.TF_STRING) | ||||
| { | { | ||||
| long size = 1; | long size = 1; | ||||