Browse Source

Tensor: made the deallocator functions static (they should not have access to anything anyway)

tags/v0.10
Meinrad Recheis 6 years ago
parent
commit
a79382b15e
1 changed files with 94 additions and 167 deletions
  1. +94
    -167
      src/TensorFlowNET.Core/Tensors/Tensor.Creation.cs

+ 94
- 167
src/TensorFlowNET.Core/Tensors/Tensor.Creation.cs View File

@@ -36,8 +36,8 @@ namespace Tensorflow
public Tensor(IntPtr handle)
{
_handle = handle;
}
}
#if _REGEN
%types=["sbyte", "byte", "short", "ushort", "int", "uint", "long", "ulong", "float", "double", "Complex"]
%foreach types%
@@ -65,26 +65,18 @@ namespace Tensorflow
{
var v = (#1*)Marshal.AllocHGlobal(sizeof(#1));
*v = value;
Deallocator deallocator = (IntPtr values, IntPtr len, ref DeallocatorArgs arg) => {
if (arg.deallocator_called)
return;
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);
_handle = TF_NewTensor(dType ?? dtypes.as_dtype(typeof(#1)), dims:new long[0], num_dims: 0, data: (IntPtr)v, len: (UIntPtr)sizeof(#1), deallocator: hGlobalDeallocator, ref _deallocatorArgs);
}
%
#else

/// <summary>
/// Create a 1d Tensor from the given linear array and shape
/// </summary>
public Tensor(sbyte[] data, TF_DataType? dType = null)
{
_handle = CreateTensorWithoutCopying(dType ?? 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>
@@ -102,23 +94,15 @@ namespace Tensorflow
{
var v = (sbyte*)Marshal.AllocHGlobal(sizeof(sbyte));
*v = value;
Deallocator deallocator = (IntPtr values, IntPtr len, ref DeallocatorArgs arg) =>
{
if (arg.deallocator_called)
return;
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);
}
_handle = TF_NewTensor(dType ?? dtypes.as_dtype(typeof(sbyte)), dims:new long[0], num_dims: 0, data: (IntPtr)v, len: (UIntPtr)sizeof(sbyte), deallocator: hGlobalDeallocator, ref _deallocatorArgs);
}
/// <summary>
/// Create a 1d Tensor from the given linear array and shape
/// </summary>
public Tensor(byte[] data, TF_DataType? dType = null)
{
_handle = CreateTensorWithoutCopying(dType ?? 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>
@@ -136,23 +120,15 @@ namespace Tensorflow
{
var v = (byte*)Marshal.AllocHGlobal(sizeof(byte));
*v = value;
Deallocator deallocator = (IntPtr values, IntPtr len, ref DeallocatorArgs arg) =>
{
if (arg.deallocator_called)
return;
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);
}
_handle = TF_NewTensor(dType ?? dtypes.as_dtype(typeof(byte)), dims:new long[0], num_dims: 0, data: (IntPtr)v, len: (UIntPtr)sizeof(byte), deallocator: hGlobalDeallocator, ref _deallocatorArgs);
}
/// <summary>
/// Create a 1d Tensor from the given linear array and shape
/// </summary>
public Tensor(short[] data, TF_DataType? dType = null)
{
_handle = CreateTensorWithoutCopying(dType ?? 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>
@@ -170,23 +146,15 @@ namespace Tensorflow
{
var v = (short*)Marshal.AllocHGlobal(sizeof(short));
*v = value;
Deallocator deallocator = (IntPtr values, IntPtr len, ref DeallocatorArgs arg) =>
{
if (arg.deallocator_called)
return;
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);
}
_handle = TF_NewTensor(dType ?? dtypes.as_dtype(typeof(short)), dims:new long[0], num_dims: 0, data: (IntPtr)v, len: (UIntPtr)sizeof(short), deallocator: hGlobalDeallocator, ref _deallocatorArgs);
}
/// <summary>
/// Create a 1d Tensor from the given linear array and shape
/// </summary>
public Tensor(ushort[] data, TF_DataType? dType = null)
{
_handle = CreateTensorWithoutCopying(dType ?? 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>
@@ -204,23 +172,15 @@ namespace Tensorflow
{
var v = (ushort*)Marshal.AllocHGlobal(sizeof(ushort));
*v = value;
Deallocator deallocator = (IntPtr values, IntPtr len, ref DeallocatorArgs arg) =>
{
if (arg.deallocator_called)
return;
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);
}
_handle = TF_NewTensor(dType ?? dtypes.as_dtype(typeof(ushort)), dims:new long[0], num_dims: 0, data: (IntPtr)v, len: (UIntPtr)sizeof(ushort), deallocator: hGlobalDeallocator, ref _deallocatorArgs);
}
/// <summary>
/// Create a 1d Tensor from the given linear array and shape
/// </summary>
public Tensor(int[] data, TF_DataType? dType = null)
{
_handle = CreateTensorWithoutCopying(dType ?? 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>
@@ -238,23 +198,15 @@ namespace Tensorflow
{
var v = (int*)Marshal.AllocHGlobal(sizeof(int));
*v = value;
Deallocator deallocator = (IntPtr values, IntPtr len, ref DeallocatorArgs arg) =>
{
if (arg.deallocator_called)
return;
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);
}
_handle = TF_NewTensor(dType ?? dtypes.as_dtype(typeof(int)), dims:new long[0], num_dims: 0, data: (IntPtr)v, len: (UIntPtr)sizeof(int), deallocator: hGlobalDeallocator, ref _deallocatorArgs);
}
/// <summary>
/// Create a 1d Tensor from the given linear array and shape
/// </summary>
public Tensor(uint[] data, TF_DataType? dType = null)
{
_handle = CreateTensorWithoutCopying(dType ?? 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>
@@ -272,23 +224,15 @@ namespace Tensorflow
{
var v = (uint*)Marshal.AllocHGlobal(sizeof(uint));
*v = value;
Deallocator deallocator = (IntPtr values, IntPtr len, ref DeallocatorArgs arg) =>
{
if (arg.deallocator_called)
return;
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);
}
_handle = TF_NewTensor(dType ?? dtypes.as_dtype(typeof(uint)), dims:new long[0], num_dims: 0, data: (IntPtr)v, len: (UIntPtr)sizeof(uint), deallocator: hGlobalDeallocator, ref _deallocatorArgs);
}
/// <summary>
/// Create a 1d Tensor from the given linear array and shape
/// </summary>
public Tensor(long[] data, TF_DataType? dType = null)
{
_handle = CreateTensorWithoutCopying(dType ?? 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>
@@ -306,23 +250,15 @@ namespace Tensorflow
{
var v = (long*)Marshal.AllocHGlobal(sizeof(long));
*v = value;
Deallocator deallocator = (IntPtr values, IntPtr len, ref DeallocatorArgs arg) =>
{
if (arg.deallocator_called)
return;
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);
}
_handle = TF_NewTensor(dType ?? dtypes.as_dtype(typeof(long)), dims:new long[0], num_dims: 0, data: (IntPtr)v, len: (UIntPtr)sizeof(long), deallocator: hGlobalDeallocator, ref _deallocatorArgs);
}
/// <summary>
/// Create a 1d Tensor from the given linear array and shape
/// </summary>
public Tensor(ulong[] data, TF_DataType? dType = null)
{
_handle = CreateTensorWithoutCopying(dType ?? 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>
@@ -340,23 +276,15 @@ namespace Tensorflow
{
var v = (ulong*)Marshal.AllocHGlobal(sizeof(ulong));
*v = value;
Deallocator deallocator = (IntPtr values, IntPtr len, ref DeallocatorArgs arg) =>
{
if (arg.deallocator_called)
return;
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);
}
_handle = TF_NewTensor(dType ?? dtypes.as_dtype(typeof(ulong)), dims:new long[0], num_dims: 0, data: (IntPtr)v, len: (UIntPtr)sizeof(ulong), deallocator: hGlobalDeallocator, ref _deallocatorArgs);
}
/// <summary>
/// Create a 1d Tensor from the given linear array and shape
/// </summary>
public Tensor(float[] data, TF_DataType? dType = null)
{
_handle = CreateTensorWithoutCopying(dType ?? 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>
@@ -374,23 +302,15 @@ namespace Tensorflow
{
var v = (float*)Marshal.AllocHGlobal(sizeof(float));
*v = value;
Deallocator deallocator = (IntPtr values, IntPtr len, ref DeallocatorArgs arg) =>
{
if (arg.deallocator_called)
return;
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);
}
_handle = TF_NewTensor(dType ?? dtypes.as_dtype(typeof(float)), dims:new long[0], num_dims: 0, data: (IntPtr)v, len: (UIntPtr)sizeof(float), deallocator: hGlobalDeallocator, ref _deallocatorArgs);
}
/// <summary>
/// Create a 1d Tensor from the given linear array and shape
/// </summary>
public Tensor(double[] data, TF_DataType? dType = null)
{
_handle = CreateTensorWithoutCopying(dType ?? 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>
@@ -408,23 +328,15 @@ namespace Tensorflow
{
var v = (double*)Marshal.AllocHGlobal(sizeof(double));
*v = value;
Deallocator deallocator = (IntPtr values, IntPtr len, ref DeallocatorArgs arg) =>
{
if (arg.deallocator_called)
return;
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);
}
_handle = TF_NewTensor(dType ?? dtypes.as_dtype(typeof(double)), dims:new long[0], num_dims: 0, data: (IntPtr)v, len: (UIntPtr)sizeof(double), deallocator: hGlobalDeallocator, ref _deallocatorArgs);
}
/// <summary>
/// Create a 1d Tensor from the given linear array and shape
/// </summary>
public Tensor(Complex[] data, TF_DataType? dType = null)
{
_handle = CreateTensorWithoutCopying(dType ?? 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>
@@ -442,15 +354,7 @@ namespace Tensorflow
{
var v = (Complex*)Marshal.AllocHGlobal(sizeof(Complex));
*v = value;
Deallocator deallocator = (IntPtr values, IntPtr len, ref DeallocatorArgs arg) =>
{
if (arg.deallocator_called)
return;
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);
_handle = TF_NewTensor(dType ?? dtypes.as_dtype(typeof(Complex)), dims:new long[0], num_dims: 0, data: (IntPtr)v, len: (UIntPtr)sizeof(Complex), deallocator: hGlobalDeallocator, ref _deallocatorArgs);
}
#endif

@@ -534,23 +438,13 @@ namespace Tensorflow
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 DeallocatorArgs args) =>
{
if (args.deallocator_called)
return;
Marshal.FreeHGlobal(values);
args.deallocator_called = true;
};

}
var tfHandle = c_api.TF_NewTensor(dataType,
dims,
dims.Length,
dotHandle,
(UIntPtr)buffersize,
deallocator,
hGlobalDeallocator,
ref _deallocatorArgs);

return tfHandle;
@@ -621,22 +515,55 @@ namespace Tensorflow
// 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);
_deallocatorArgs = new DeallocatorArgs() { gc_handle = GCHandle.ToIntPtr(gcHandle) };
// Free the original buffer and set flag
Deallocator deallocator = (IntPtr ptr, IntPtr len, ref DeallocatorArgs args) =>
{
if (args.deallocator_called || args.gc_handle==IntPtr.Zero)
return;
// 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 || shape.Length == 0)
return TF_NewTensor(dt, new long[0], 0, gcHandle.AddrOfPinnedObject() + start * element_size, (UIntPtr)(count * element_size), deallocator, ref _deallocatorArgs);
return TF_NewTensor(dt, new long[0], 0, gcHandle.AddrOfPinnedObject() + start * element_size, (UIntPtr)(count * element_size), gcHandleDeallocator, ref _deallocatorArgs);
else
return TF_NewTensor(dt, shape, shape.Length, gcHandle.AddrOfPinnedObject() + start * element_size, (UIntPtr)(count * element_size), deallocator, ref _deallocatorArgs);
return TF_NewTensor(dt, shape, shape.Length, gcHandle.AddrOfPinnedObject() + start * element_size, (UIntPtr)(count * element_size), gcHandleDeallocator, ref _deallocatorArgs);
}

private DeallocatorArgs _deallocatorArgs = new DeallocatorArgs() { gc_handle = IntPtr.Zero };

// note: they must be assigned to a static variable in order to work as unmanaged callbacks
static Deallocator hGlobalDeallocator = FreeHGlobalMemory;
static Deallocator gcHandleDeallocator = FreeGCHandle;

[MonoPInvokeCallback(typeof(Deallocator))]
internal static void FreeHGlobalMemory(IntPtr dataPtr, IntPtr len, ref DeallocatorArgs args)
{
if (args.deallocator_called)
return;
Marshal.FreeHGlobal(dataPtr);
args.deallocator_called = true;
}

[MonoPInvokeCallback(typeof(Deallocator))]
internal static void FreeGCHandle(IntPtr dataPtr, IntPtr len, ref DeallocatorArgs args)
{
if (args.deallocator_called || args.gc_handle == IntPtr.Zero)
return;
// 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;
}
}

/// <summary>
/// This attribute can be applied to callback functions that will be invoked
/// from unmanaged code to managed code.
/// </summary>
/// <remarks>
/// <code>
/// [TensorFlow.MonoPInvokeCallback (typeof (BufferReleaseFunc))]
/// internal static void MyFreeFunc (IntPtr data, IntPtr length){..}
/// </code>
/// </remarks>
public sealed class MonoPInvokeCallbackAttribute : Attribute
{
/// <summary>
/// Use this constructor to annotate the type of the callback function that
/// will be invoked from unmanaged code.
/// </summary>
/// <param name="t">T.</param>
public MonoPInvokeCallbackAttribute(Type t) { }
}
}

Loading…
Cancel
Save