Browse Source

Change to use tensor as underlying data structure.

tags/v0.60-tf.numpy
Oceania2018 4 years ago
parent
commit
39883aecef
9 changed files with 50 additions and 46 deletions
  1. +4
    -10
      src/TensorFlowNET.Core/Eager/EagerTensor.Creation.cs
  2. +26
    -4
      src/TensorFlowNET.Core/Numpy/NDArray.Creation.cs
  3. +7
    -1
      src/TensorFlowNET.Core/Numpy/NDArray.cs
  4. +2
    -3
      src/TensorFlowNET.Core/Tensors/Tensor.Creation.cs
  5. +4
    -16
      src/TensorFlowNET.Core/Tensors/Tensor.cs
  6. +1
    -1
      src/TensorFlowNET.Core/Tensors/c_api.tensor.cs
  7. +4
    -4
      src/TensorFlowNET.Core/Tensors/constant_op.cs
  8. +2
    -2
      test/TensorFlowNET.Native.UnitTest/Tensors/TensorTest.cs
  9. +0
    -5
      test/TensorFlowNET.UnitTest/EagerModeTestBase.cs

+ 4
- 10
src/TensorFlowNET.Core/Eager/EagerTensor.Creation.cs View File

@@ -10,7 +10,7 @@ namespace Tensorflow.Eager
public EagerTensor(SafeTensorHandleHandle handle) public EagerTensor(SafeTensorHandleHandle handle)
{ {
_id = ops.uid(); _id = ops.uid();
EagerTensorHandle = handle;
_eagerTensorHandle = handle;
Resolve(); Resolve();
} }


@@ -59,20 +59,14 @@ namespace Tensorflow.Eager
void NewEagerTensorHandle(IntPtr h) void NewEagerTensorHandle(IntPtr h)
{ {
_id = ops.uid(); _id = ops.uid();
EagerTensorHandle = c_api.TFE_NewTensorHandle(h, tf.Status.Handle);
_eagerTensorHandle = c_api.TFE_NewTensorHandle(h, tf.Status.Handle);
tf.Status.Check(true); tf.Status.Check(true);
#if TRACK_TENSOR_LIFE
print($"New EagerTensorHandle {EagerTensorHandle} {Id} From 0x{h.ToString("x16")}");
#endif
} }


private void Resolve() private void Resolve()
{ {
_handle = c_api.TFE_TensorHandleResolve(EagerTensorHandle, tf.Status.Handle);
_handle = c_api.TFE_TensorHandleResolve(_eagerTensorHandle, tf.Status.Handle);
tf.Status.Check(true); tf.Status.Check(true);
#if TRACK_TENSOR_LIFE
print($"Take EagerTensorHandle {EagerTensorHandle} {Id} Resolving 0x{_handle.ToString("x16")}");
#endif
} }


/// <summary> /// <summary>
@@ -104,7 +98,7 @@ namespace Tensorflow.Eager
protected override void DisposeUnmanagedResources(IntPtr handle) protected override void DisposeUnmanagedResources(IntPtr handle)
{ {
base.DisposeUnmanagedResources(handle); base.DisposeUnmanagedResources(handle);
EagerTensorHandle.Dispose();
_eagerTensorHandle.Dispose();
} }
} }
} }

+ 26
- 4
src/TensorFlowNET.Core/Numpy/NDArray.Creation.cs View File

@@ -25,6 +25,7 @@ namespace Tensorflow.NumPy
bool val => new NDArray(val), bool val => new NDArray(val),
byte val => new NDArray(val), byte val => new NDArray(val),
int val => new NDArray(val), int val => new NDArray(val),
long val => new NDArray(val),
float val => new NDArray(val), float val => new NDArray(val),
double val => new NDArray(val), double val => new NDArray(val),
_ => throw new NotImplementedException("") _ => throw new NotImplementedException("")
@@ -32,26 +33,44 @@ namespace Tensorflow.NumPy


void Init<T>(T value) where T : unmanaged void Init<T>(T value) where T : unmanaged
{ {
_tensor = new EagerTensor(value);
_tensor = value switch
{
bool val => new Tensor(val),
byte val => new Tensor(val),
int val => new Tensor(val),
long val => new Tensor(val),
float val => new Tensor(val),
double val => new Tensor(val),
_ => throw new NotImplementedException("")
};
_tensor.SetReferencedByNDArray(); _tensor.SetReferencedByNDArray();

var _handle = c_api.TFE_NewTensorHandle(_tensor, tf.Status.Handle);
_tensor.SetEagerTensorHandle(_handle);
} }


void Init(Array value, Shape? shape = null) void Init(Array value, Shape? shape = null)
{ {
_tensor = new EagerTensor(value, shape ?? value.GetShape());
_tensor = new Tensor(value, shape ?? value.GetShape());
_tensor.SetReferencedByNDArray(); _tensor.SetReferencedByNDArray();

var _handle = c_api.TFE_NewTensorHandle(_tensor, tf.Status.Handle);
_tensor.SetEagerTensorHandle(_handle);
} }


void Init(Shape shape, TF_DataType dtype = TF_DataType.TF_DOUBLE) void Init(Shape shape, TF_DataType dtype = TF_DataType.TF_DOUBLE)
{ {
_tensor = new EagerTensor(shape, dtype: dtype);
_tensor = new Tensor(shape, dtype: dtype);
_tensor.SetReferencedByNDArray(); _tensor.SetReferencedByNDArray();

var _handle = c_api.TFE_NewTensorHandle(_tensor, tf.Status.Handle);
_tensor.SetEagerTensorHandle(_handle);
} }


void Init(Tensor value, Shape? shape = null) void Init(Tensor value, Shape? shape = null)
{ {
if (shape is not null) if (shape is not null)
_tensor = tf.reshape(value, shape);
_tensor = new Tensor(value.TensorDataPointer, shape, value.dtype);
else else
_tensor = value; _tensor = value;


@@ -59,6 +78,9 @@ namespace Tensorflow.NumPy
_tensor = tf.get_default_session().eval(_tensor); _tensor = tf.get_default_session().eval(_tensor);


_tensor.SetReferencedByNDArray(); _tensor.SetReferencedByNDArray();

var _handle = c_api.TFE_NewTensorHandle(_tensor, tf.Status.Handle);
_tensor.SetEagerTensorHandle(_handle);
} }
} }
} }

+ 7
- 1
src/TensorFlowNET.Core/Numpy/NDArray.cs View File

@@ -6,7 +6,7 @@ using static Tensorflow.Binding;


namespace Tensorflow.NumPy namespace Tensorflow.NumPy
{ {
public partial class NDArray
public partial class NDArray : DisposableObject
{ {
Tensor _tensor; Tensor _tensor;
public TF_DataType dtype => _tensor.dtype; public TF_DataType dtype => _tensor.dtype;
@@ -58,5 +58,11 @@ namespace Tensorflow.NumPy
{ {
return tensor_util.to_numpy_string(_tensor); return tensor_util.to_numpy_string(_tensor);
} }

protected override void DisposeUnmanagedResources(IntPtr handle)
{
_tensor.EagerTensorHandle.Dispose();
_tensor.Dispose();
}
} }
} }

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

@@ -53,10 +53,9 @@ namespace Tensorflow
/// <param name="data_ptr">Pointer to unmanaged, fixed or pinned memory which the caller owns</param> /// <param name="data_ptr">Pointer to unmanaged, fixed or pinned memory which the caller owns</param>
/// <param name="shape">Tensor shape</param> /// <param name="shape">Tensor shape</param>
/// <param name="dType">TF data type</param> /// <param name="dType">TF data type</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 unsafe Tensor(IntPtr data_ptr, Shape shape, TF_DataType dtype)
{ {
_handle = TF_NewTensor(dType, dims: shape, num_dims: shape.Length, data: data_ptr, len: (ulong)num_bytes);
_handle = TF_NewTensor(shape, dtype, data: data_ptr.ToPointer());
isCreatedInGraphMode = !tf.executing_eagerly(); isCreatedInGraphMode = !tf.executing_eagerly();
} }




+ 4
- 16
src/TensorFlowNET.Core/Tensors/Tensor.cs View File

@@ -89,10 +89,11 @@ namespace Tensorflow
/// </summary> /// </summary>
public object Tag { get; set; } public object Tag { get; set; }


protected SafeTensorHandleHandle _eagerTensorHandle;
/// <summary> /// <summary>
/// TFE_TensorHandle /// TFE_TensorHandle
/// </summary> /// </summary>
public SafeTensorHandleHandle EagerTensorHandle { get; set; }
public SafeTensorHandleHandle EagerTensorHandle => _eagerTensorHandle;


protected bool isReferencedByNDArray; protected bool isReferencedByNDArray;
public bool IsReferencedByNDArray => isReferencedByNDArray; public bool IsReferencedByNDArray => isReferencedByNDArray;
@@ -212,6 +213,7 @@ namespace Tensorflow
} }


public void SetReferencedByNDArray() => isReferencedByNDArray = true; public void SetReferencedByNDArray() => isReferencedByNDArray = true;
public void SetEagerTensorHandle(SafeTensorHandleHandle handle) => _eagerTensorHandle = handle;


public Tensor MaybeMove() public Tensor MaybeMove()
{ {
@@ -254,30 +256,16 @@ namespace Tensorflow
} }
} }


/// <summary>
/// Dispose any managed resources.
/// </summary>
/// <remarks>Equivalent to what you would perform inside <see cref="DisposableObject.Dispose"/></remarks>
protected override void DisposeManagedResources()
{

}

[SuppressMessage("ReSharper", "ConvertIfStatementToSwitchStatement")] [SuppressMessage("ReSharper", "ConvertIfStatementToSwitchStatement")]
protected override void DisposeUnmanagedResources(IntPtr handle) protected override void DisposeUnmanagedResources(IntPtr handle)
{ {
#if TRACK_TENSOR_LIFE
print($"Delete Tensor 0x{handle.ToString("x16")} {AllocationType} Data: 0x{TensorDataPointer.ToString("x16")}");
#endif
if (dtype == TF_DataType.TF_STRING) if (dtype == TF_DataType.TF_STRING)
{ {
long size = 1; long size = 1;
foreach (var s in TensorShape.dims) foreach (var s in TensorShape.dims)
size *= s; size *= s;
var tstr = TensorDataPointer; var tstr = TensorDataPointer;
#if TRACK_TENSOR_LIFE
print($"Delete TString 0x{handle.ToString("x16")} {AllocationType} Data: 0x{tstr.ToString("x16")}");
#endif

for (int i = 0; i < size; i++) for (int i = 0; i < size; i++)
{ {
c_api.TF_StringDealloc(tstr); c_api.TF_StringDealloc(tstr);


+ 1
- 1
src/TensorFlowNET.Core/Tensors/c_api.tensor.cs View File

@@ -101,7 +101,7 @@ namespace Tensorflow
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe IntPtr TF_NewTensor(TF_DataType dataType, long[] dims, int num_dims, IntPtr data, ulong len) public static unsafe IntPtr TF_NewTensor(TF_DataType dataType, long[] dims, int num_dims, IntPtr data, ulong len)
{ {
return c_api.TF_NewTensor(dataType, dims, num_dims, data, len, EmptyDeallocator, DeallocatorArgs.Empty);
return TF_NewTensor(dataType, dims, num_dims, data, len, EmptyDeallocator, DeallocatorArgs.Empty);
} }


public static unsafe IntPtr TF_NewTensor(Shape shape, TF_DataType dtype, void* data) public static unsafe IntPtr TF_NewTensor(Shape shape, TF_DataType dtype, void* data)


+ 4
- 4
src/TensorFlowNET.Core/Tensors/constant_op.cs View File

@@ -101,7 +101,7 @@ namespace Tensorflow
return op.outputs[0]; return op.outputs[0];
} }


private static Tensor _eager_reshape(EagerTensor tensor, int[] shape, Context ctx)
private static Tensor _eager_reshape(Tensor tensor, int[] shape, Context ctx)
{ {
var attr_t = tensor.dtype.as_datatype_enum(); var attr_t = tensor.dtype.as_datatype_enum();
var dims_t = convert_to_eager_tensor(shape, ctx, dtypes.int32); var dims_t = convert_to_eager_tensor(shape, ctx, dtypes.int32);
@@ -111,7 +111,7 @@ namespace Tensorflow
return result[0]; return result[0];
} }


private static Tensor _eager_fill(int[] dims, EagerTensor value, Context ctx)
private static Tensor _eager_fill(int[] dims, Tensor value, Context ctx)
{ {
var attr_t = value.dtype.as_datatype_enum(); var attr_t = value.dtype.as_datatype_enum();
var dims_t = convert_to_eager_tensor(dims, ctx, dtypes.int32); var dims_t = convert_to_eager_tensor(dims, ctx, dtypes.int32);
@@ -121,7 +121,7 @@ namespace Tensorflow
return result[0]; return result[0];
} }


private static EagerTensor convert_to_eager_tensor(object value, Context ctx, TF_DataType dtype = TF_DataType.DtInvalid)
private static Tensor convert_to_eager_tensor(object value, Context ctx, TF_DataType dtype = TF_DataType.DtInvalid)
{ {
ctx.ensure_initialized(); ctx.ensure_initialized();
// convert data type // convert data type
@@ -161,7 +161,7 @@ namespace Tensorflow
case EagerTensor val: case EagerTensor val:
return val; return val;
case NDArray val: case NDArray val:
return (EagerTensor)val;
return val;
case Shape val: case Shape val:
return new EagerTensor(val.dims, new Shape(val.ndim)); return new EagerTensor(val.dims, new Shape(val.ndim));
case TensorShape val: case TensorShape val:


+ 2
- 2
test/TensorFlowNET.Native.UnitTest/Tensors/TensorTest.cs View File

@@ -18,7 +18,7 @@ namespace Tensorflow.Native.UnitTest.Tensors
var span = new Span<float>(array, 100, 500); var span = new Span<float>(array, 100, 500);
fixed (float* ptr = &MemoryMarshal.GetReference(span)) fixed (float* ptr = &MemoryMarshal.GetReference(span))
{ {
using (var t = new Tensor((IntPtr)ptr, new long[] { span.Length }, tf.float32, 4 * span.Length))
using (var t = new Tensor((IntPtr)ptr, new long[] { span.Length }, tf.float32))
{ {
Assert.IsFalse(t.IsDisposed); Assert.IsFalse(t.IsDisposed);
Assert.AreEqual(2000, (int)t.bytesize); Assert.AreEqual(2000, (int)t.bytesize);
@@ -27,7 +27,7 @@ namespace Tensorflow.Native.UnitTest.Tensors


fixed (float* ptr = &array[0]) fixed (float* ptr = &array[0])
{ {
using (var t = new Tensor((IntPtr)ptr, new long[] { array.Length }, tf.float32, 4 * array.Length))
using (var t = new Tensor((IntPtr)ptr, new long[] { array.Length }, tf.float32))
{ {
Assert.IsFalse(t.IsDisposed); Assert.IsFalse(t.IsDisposed);
Assert.AreEqual(4000, (int)t.bytesize); Assert.AreEqual(4000, (int)t.bytesize);


+ 0
- 5
test/TensorFlowNET.UnitTest/EagerModeTestBase.cs View File

@@ -14,11 +14,6 @@ namespace TensorFlowNET.UnitTest
tf.Context.ensure_initialized(); tf.Context.ensure_initialized();
} }


[TestCleanup]
public void TestClean()
{
}

public bool Equal(float[] f1, float[] f2) public bool Equal(float[] f1, float[] f2)
{ {
bool ret = false; bool ret = false;


Loading…
Cancel
Save