Browse Source

Tensor.Creation: fixed handling of string Tensor and fixed deallocation of pinned arrays

tags/v0.10
Meinrad Recheis 6 years ago
parent
commit
f6e9a8c75b
2 changed files with 264 additions and 70 deletions
  1. +258
    -67
      src/TensorFlowNET.Core/Tensors/Tensor.Creation.cs
  2. +6
    -3
      src/TensorFlowNET.Core/Tensors/Tensor.cs

+ 258
- 67
src/TensorFlowNET.Core/Tensors/Tensor.Creation.cs View File

@@ -29,9 +29,9 @@ namespace Tensorflow
public partial class Tensor
{
/// <summary>
/// if original buffer is free.
/// true if unmanaged buffer has been freed.
/// </summary>
private bool deallocator_called;
private bool deallocator_called => _deallocatorArgs.deallocator_called;

public Tensor(IntPtr handle)
{
@@ -45,210 +45,395 @@ namespace Tensorflow
/// <summary>
/// Create a 1d Tensor from the given linear array and shape
/// </summary>
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>());
}

/// <summary>
/// Create a N-dimensional Tensor from the given array
/// </summary>
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>());
}

/// <summary>
/// Create a scalar Tensor from the given value
/// </summary>
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
/// <summary>
/// Create a 1d Tensor from the given linear array and shape
/// </summary>
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<sbyte>());
_handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(sbyte)), new long[]{data.Length}, data, Marshal.SizeOf<sbyte>());
}

/// <summary>
/// Create a N-dimensional Tensor from the given array
/// </summary>
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<sbyte>());
_handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(sbyte)), shape, data, Marshal.SizeOf<sbyte>());
}

/// <summary>
/// Create a scalar Tensor from the given value
/// </summary>
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);
}
/// <summary>
/// Create a 1d Tensor from the given linear array and shape
/// </summary>
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<byte>());
_handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(byte)), new long[]{data.Length}, data, Marshal.SizeOf<byte>());
}

/// <summary>
/// Create a N-dimensional Tensor from the given array
/// </summary>
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<byte>());
_handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(byte)), shape, data, Marshal.SizeOf<byte>());
}

/// <summary>
/// Create a scalar Tensor from the given value
/// </summary>
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);
}
/// <summary>
/// Create a 1d Tensor from the given linear array and shape
/// </summary>
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<short>());
_handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(short)), new long[]{data.Length}, data, Marshal.SizeOf<short>());
}

/// <summary>
/// Create a N-dimensional Tensor from the given array
/// </summary>
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<short>());
_handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(short)), shape, data, Marshal.SizeOf<short>());
}

/// <summary>
/// Create a scalar Tensor from the given value
/// </summary>
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);
}
/// <summary>
/// Create a 1d Tensor from the given linear array and shape
/// </summary>
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<ushort>());
_handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(ushort)), new long[]{data.Length}, data, Marshal.SizeOf<ushort>());
}

/// <summary>
/// Create a N-dimensional Tensor from the given array
/// </summary>
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<ushort>());
_handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(ushort)), shape, data, Marshal.SizeOf<ushort>());
}

/// <summary>
/// Create a scalar Tensor from the given value
/// </summary>
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);
}
/// <summary>
/// Create a 1d Tensor from the given linear array and shape
/// </summary>
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<int>());
_handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(int)), new long[]{data.Length}, data, Marshal.SizeOf<int>());
}

/// <summary>
/// Create a N-dimensional Tensor from the given array
/// </summary>
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<int>());
_handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(int)), shape, data, Marshal.SizeOf<int>());
}

/// <summary>
/// Create a scalar Tensor from the given value
/// </summary>
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);
}
/// <summary>
/// Create a 1d Tensor from the given linear array and shape
/// </summary>
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<uint>());
_handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(uint)), new long[]{data.Length}, data, Marshal.SizeOf<uint>());
}

/// <summary>
/// Create a N-dimensional Tensor from the given array
/// </summary>
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<uint>());
_handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(uint)), shape, data, Marshal.SizeOf<uint>());
}

/// <summary>
/// Create a scalar Tensor from the given value
/// </summary>
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);
}
/// <summary>
/// Create a 1d Tensor from the given linear array and shape
/// </summary>
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<long>());
_handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(long)), new long[]{data.Length}, data, Marshal.SizeOf<long>());
}

/// <summary>
/// Create a N-dimensional Tensor from the given array
/// </summary>
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<long>());
_handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(long)), shape, data, Marshal.SizeOf<long>());
}

/// <summary>
/// Create a scalar Tensor from the given value
/// </summary>
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);
}
/// <summary>
/// Create a 1d Tensor from the given linear array and shape
/// </summary>
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<ulong>());
_handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(ulong)), new long[]{data.Length}, data, Marshal.SizeOf<ulong>());
}

/// <summary>
/// Create a N-dimensional Tensor from the given array
/// </summary>
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<ulong>());
_handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(ulong)), shape, data, Marshal.SizeOf<ulong>());
}

/// <summary>
/// Create a scalar Tensor from the given value
/// </summary>
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);
}
/// <summary>
/// Create a 1d Tensor from the given linear array and shape
/// </summary>
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<float>());
_handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(float)), new long[]{data.Length}, data, Marshal.SizeOf<float>());
}

/// <summary>
/// Create a N-dimensional Tensor from the given array
/// </summary>
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<float>());
_handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(float)), shape, data, Marshal.SizeOf<float>());
}

/// <summary>
/// Create a scalar Tensor from the given value
/// </summary>
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);
}
/// <summary>
/// Create a 1d Tensor from the given linear array and shape
/// </summary>
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<double>());
_handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(double)), new long[]{data.Length}, data, Marshal.SizeOf<double>());
}

/// <summary>
/// Create a N-dimensional Tensor from the given array
/// </summary>
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<double>());
_handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(double)), shape, data, Marshal.SizeOf<double>());
}

/// <summary>
/// Create a scalar Tensor from the given value
/// </summary>
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);
}
/// <summary>
/// Create a 1d Tensor from the given linear array and shape
/// </summary>
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<Complex>());
_handle = CreateTensorWithoutCopying(dType ?? dtypes.as_dtype(typeof(Complex)), new long[]{data.Length}, data, Marshal.SizeOf<Complex>());
}

/// <summary>
/// Create a N-dimensional Tensor from the given array
/// </summary>
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<Complex>());
}

/// <summary>
/// Create a scalar Tensor from the given value
/// </summary>
public unsafe Tensor(Complex value, TF_DataType? dType = null)
{
_handle = CreateTensorWithoutCopying(dtypes.as_dtype(typeof(Complex)), shape, data, Marshal.SizeOf<Complex>());
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

/// <summary>
/// Create a string Tensor from the given string
/// </summary>
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<byte>(), 0, dotHandle, nd.size);
break;
case "String":
return new Tensor(UTF8Encoding.UTF8.GetBytes(nd.Data<string>(0)));
return new Tensor(UTF8Encoding.UTF8.GetBytes(nd.Data<string>(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;

/// <summary>
/// Creates a new tensor from the given array without copying memory. The array is pinned down and the pointer passed on.
/// </summary>
@@ -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);
}
}
/// <summary>
/// Creates a new tensor from a subsection of the given array without copying memory. The array is pinned down and the pointer passed on.
/// </summary>
@@ -373,25 +560,29 @@ namespace Tensorflow
/// specified dimensions.
/// </remarks>
[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<int>().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();
}
}

+ 6
- 3
src/TensorFlowNET.Core/Tensors/Tensor.cs View File

@@ -44,7 +44,7 @@ namespace Tensorflow
/// <summary>
/// The string name of this tensor.
/// </summary>
public string name => $"{(op == null ? "Operation was not named" : $"{op.name}:{_value_index}")}";
public string name => $"{(op == null ? "<unnamed Operation>" : $"{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();
}



Loading…
Cancel
Save