Browse Source

add SafeTensorHandle to manage tensor handle reference.

tags/v0.60-tf.numpy
Oceania2018 4 years ago
parent
commit
e73ed66b7c
51 changed files with 271 additions and 322 deletions
  1. +1
    -1
      src/TensorFlowNET.Console/Tensorflow.Console.csproj
  2. +1
    -1
      src/TensorFlowNET.Core/Attributes/c_api.ops.cs
  3. +0
    -2
      src/TensorFlowNET.Core/Binding.Util.cs
  4. +1
    -1
      src/TensorFlowNET.Core/Data/MnistDataSet.cs
  5. +1
    -1
      src/TensorFlowNET.Core/Data/ModelLoadSetting.cs
  6. +1
    -1
      src/TensorFlowNET.Core/DisposableObject.cs
  7. +1
    -1
      src/TensorFlowNET.Core/Eager/EagerTensor.Creation.cs
  8. +2
    -2
      src/TensorFlowNET.Core/Eager/c_api.eager.cs
  9. +0
    -6
      src/TensorFlowNET.Core/NumPy/NDArray.Implicit.cs
  10. +30
    -5
      src/TensorFlowNET.Core/NumPy/NDArray.Index.cs
  11. +7
    -6
      src/TensorFlowNET.Core/NumPy/NDArray.Operators.cs
  12. +2
    -2
      src/TensorFlowNET.Core/NumPy/NumPy.Logical.cs
  13. +2
    -2
      src/TensorFlowNET.Core/NumPy/NumPy.Statistics.cs
  14. +9
    -9
      src/TensorFlowNET.Core/NumPy/Numpy.Math.cs
  15. +34
    -64
      src/TensorFlowNET.Core/Numpy/NDArray.Creation.cs
  16. +7
    -26
      src/TensorFlowNET.Core/Numpy/NDArray.cs
  17. +2
    -5
      src/TensorFlowNET.Core/Operations/array_ops.cs
  18. +16
    -21
      src/TensorFlowNET.Core/Operations/image_ops_impl.cs
  19. +0
    -15
      src/TensorFlowNET.Core/Operations/math_ops.cs
  20. +1
    -1
      src/TensorFlowNET.Core/Operations/resource_variable_ops.cs
  21. +5
    -8
      src/TensorFlowNET.Core/Sessions/BaseSession.cs
  22. +44
    -0
      src/TensorFlowNET.Core/Tensors/SafeTensorHandle.cs
  23. +6
    -6
      src/TensorFlowNET.Core/Tensors/Tensor.Creation.cs
  24. +2
    -2
      src/TensorFlowNET.Core/Tensors/Tensor.Equal.cs
  25. +6
    -11
      src/TensorFlowNET.Core/Tensors/Tensor.Implicit.cs
  26. +2
    -32
      src/TensorFlowNET.Core/Tensors/Tensor.Operators.cs
  27. +2
    -2
      src/TensorFlowNET.Core/Tensors/Tensor.String.cs
  28. +11
    -14
      src/TensorFlowNET.Core/Tensors/Tensor.cs
  29. +11
    -11
      src/TensorFlowNET.Core/Tensors/c_api.tensor.cs
  30. +1
    -1
      src/TensorFlowNET.Core/Tensors/constant_op.cs
  31. +8
    -8
      src/TensorFlowNET.Core/Tensors/tensor_util.cs
  32. +1
    -1
      src/TensorFlowNET.Core/Variables/BaseResourceVariable.cs
  33. +2
    -2
      src/TensorFlowNET.Keras/Layers/Rescaling/Rescaling.cs
  34. +4
    -4
      src/TensorFlowNET.Keras/Optimizers/PolynomialDecay.cs
  35. +2
    -2
      src/TensorFlowNET.Keras/Preprocessings/Preprocessing.image_dataset_from_directory.cs
  36. +2
    -2
      src/TensorFlowNET.Keras/Preprocessings/Tokenizer.cs
  37. +2
    -2
      src/TensorFlowNet.Benchmarks/Leak/GpuLeakByCNN.cs
  38. +17
    -17
      test/TensorFlowNET.Graph.UnitTest/GradientTest/GradientTest.cs
  39. +2
    -2
      test/TensorFlowNET.Graph.UnitTest/MultithreadingTests.cs
  40. +1
    -1
      test/TensorFlowNET.Graph.UnitTest/PythonTest.cs
  41. +6
    -6
      test/TensorFlowNET.Native.UnitTest/CApiTest.cs
  42. +2
    -2
      test/TensorFlowNET.Native.UnitTest/Eager/Eager.Execute_MatMul_CPU.cs
  43. +1
    -1
      test/TensorFlowNET.Native.UnitTest/Eager/Eager.TensorHandle.cs
  44. +1
    -1
      test/TensorFlowNET.Native.UnitTest/Eager/Eager.Variables.cs
  45. +1
    -1
      test/TensorFlowNET.Native.UnitTest/Eager/Eager.cs
  46. +1
    -1
      test/TensorFlowNET.Native.UnitTest/Functions/FunctionTest.cs
  47. +5
    -5
      test/TensorFlowNET.Native.UnitTest/Sessions/CSession.cs
  48. +1
    -1
      test/TensorFlowNET.Native.UnitTest/Sessions/SessionTest.cs
  49. +2
    -2
      test/TensorFlowNET.Native.UnitTest/Tensors/TensorTest.cs
  50. +1
    -1
      test/TensorFlowNET.UnitTest/Basics/SessionTest.cs
  51. +1
    -1
      test/TensorFlowNET.UnitTest/PythonTest.cs

+ 1
- 1
src/TensorFlowNET.Console/Tensorflow.Console.csproj View File

@@ -19,7 +19,7 @@
</PropertyGroup> </PropertyGroup>


<ItemGroup> <ItemGroup>
<PackageReference Include="SciSharp.TensorFlow.Redist-Windows-GPU" Version="2.5.0" />
<PackageReference Include="SciSharp.TensorFlow.Redist" Version="2.5.0" />
</ItemGroup> </ItemGroup>


<ItemGroup> <ItemGroup>


+ 1
- 1
src/TensorFlowNET.Core/Attributes/c_api.ops.cs View File

@@ -99,7 +99,7 @@ namespace Tensorflow
public static extern void TF_SetAttrStringList(IntPtr desc, string attr_name, IntPtr[] values, uint[] lengths, int num_values); public static extern void TF_SetAttrStringList(IntPtr desc, string attr_name, IntPtr[] values, uint[] lengths, int num_values);


[DllImport(TensorFlowLibName)] [DllImport(TensorFlowLibName)]
public static extern void TF_SetAttrTensor(IntPtr desc, string attr_name, IntPtr value, SafeStatusHandle status);
public static extern void TF_SetAttrTensor(IntPtr desc, string attr_name, SafeTensorHandle value, SafeStatusHandle status);


[DllImport(TensorFlowLibName)] [DllImport(TensorFlowLibName)]
public static extern void TF_SetAttrType(IntPtr desc, string attr_name, TF_DataType value); public static extern void TF_SetAttrType(IntPtr desc, string attr_name, TF_DataType value);


+ 0
- 2
src/TensorFlowNET.Core/Binding.Util.cs View File

@@ -164,8 +164,6 @@ namespace Tensorflow
return arr.Count; return arr.Count;
case ICollection arr: case ICollection arr:
return arr.Count; return arr.Count;
case NDArray ndArray:
return ndArray.ndim == 0 ? 1 : (int)ndArray.dims[0];
case IEnumerable enumerable: case IEnumerable enumerable:
return enumerable.OfType<object>().Count(); return enumerable.OfType<object>().Count();
case Shape arr: case Shape arr:


+ 1
- 1
src/TensorFlowNET.Core/Data/MnistDataSet.cs View File

@@ -10,7 +10,7 @@ namespace Tensorflow
public int EpochsCompleted { get; private set; } public int EpochsCompleted { get; private set; }
public int IndexInEpoch { get; private set; } public int IndexInEpoch { get; private set; }


public MnistDataSet(NDArray images, NDArray labels, Type dataType, bool reshape)
public MnistDataSet(NDArray images, NDArray labels, TF_DataType dataType, bool reshape)
{ {
EpochsCompleted = 0; EpochsCompleted = 0;
IndexInEpoch = 0; IndexInEpoch = 0;


+ 1
- 1
src/TensorFlowNET.Core/Data/ModelLoadSetting.cs View File

@@ -6,7 +6,7 @@ namespace Tensorflow
{ {
public string TrainDir { get; set; } public string TrainDir { get; set; }
public bool OneHot { get; set; } public bool OneHot { get; set; }
public Type DataType { get; set; } = typeof(float);
public TF_DataType DataType { get; set; } = TF_DataType.TF_FLOAT;
public bool ReShape { get; set; } public bool ReShape { get; set; }
public int ValidationSize { get; set; } = 5000; public int ValidationSize { get; set; } = 5000;
public int? TrainSize { get; set; } public int? TrainSize { get; set; }


+ 1
- 1
src/TensorFlowNET.Core/DisposableObject.cs View File

@@ -48,7 +48,7 @@ namespace Tensorflow
} }


// free unmanaged memory // free unmanaged memory
if (_handle != IntPtr.Zero)
// if (_handle != IntPtr.Zero)
{ {
// Call the appropriate methods to clean up // Call the appropriate methods to clean up
// unmanaged resources here. // unmanaged resources here.


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

@@ -56,7 +56,7 @@ namespace Tensorflow.Eager
public EagerTensor(byte[] bytes, Shape shape, TF_DataType dtype) : base(bytes, shape, dtype) public EagerTensor(byte[] bytes, Shape shape, TF_DataType dtype) : base(bytes, shape, dtype)
=> NewEagerTensorHandle(_handle); => NewEagerTensorHandle(_handle);


void NewEagerTensorHandle(IntPtr h)
void NewEagerTensorHandle(SafeTensorHandle 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);


+ 2
- 2
src/TensorFlowNET.Core/Eager/c_api.eager.cs View File

@@ -303,7 +303,7 @@ namespace Tensorflow
/// <param name="t">const tensorflow::Tensor&amp;</param> /// <param name="t">const tensorflow::Tensor&amp;</param>
/// <returns>TFE_TensorHandle*</returns> /// <returns>TFE_TensorHandle*</returns>
[DllImport(TensorFlowLibName)] [DllImport(TensorFlowLibName)]
public static extern SafeTensorHandleHandle TFE_NewTensorHandle(IntPtr t, SafeStatusHandle status);
public static extern SafeTensorHandleHandle TFE_NewTensorHandle(SafeTensorHandle t, SafeStatusHandle status);


[DllImport(TensorFlowLibName)] [DllImport(TensorFlowLibName)]
public static extern SafeTensorHandleHandle TFE_EagerTensorHandle(IntPtr t); public static extern SafeTensorHandleHandle TFE_EagerTensorHandle(IntPtr t);
@@ -334,7 +334,7 @@ namespace Tensorflow
/// <param name="status">TF_Status*</param> /// <param name="status">TF_Status*</param>
/// <returns></returns> /// <returns></returns>
[DllImport(TensorFlowLibName)] [DllImport(TensorFlowLibName)]
public static extern IntPtr TFE_TensorHandleResolve(SafeTensorHandleHandle h, SafeStatusHandle status);
public static extern SafeTensorHandle TFE_TensorHandleResolve(SafeTensorHandleHandle h, SafeStatusHandle status);




/// <summary> /// <summary>


+ 0
- 6
src/TensorFlowNET.Core/NumPy/NDArray.Implicit.cs View File

@@ -46,11 +46,5 @@ namespace Tensorflow.NumPy


public static implicit operator NDArray(double value) public static implicit operator NDArray(double value)
=> new NDArray(value); => new NDArray(value);

public static implicit operator Tensor(NDArray nd)
=> nd?._tensor;

public static implicit operator NDArray(Tensor tensor)
=> new NDArray(tensor);
} }
} }

+ 30
- 5
src/TensorFlowNET.Core/NumPy/NDArray.Index.cs View File

@@ -8,16 +8,16 @@ namespace Tensorflow.NumPy
{ {
public partial class NDArray public partial class NDArray
{ {
public NDArray this[params int[] index]
public NDArray this[params int[] indices]
{ {
get => GetData(index.Select(x => new Slice
get => GetData(indices.Select(x => new Slice
{ {
Start = x, Start = x,
Stop = x + 1, Stop = x + 1,
IsIndex = true IsIndex = true
})); }));


set => SetData(index.Select(x =>
set => SetData(indices.Select(x =>
{ {
if(x < 0) if(x < 0)
x = (int)dims[0] + x; x = (int)dims[0] + x;
@@ -57,12 +57,37 @@ namespace Tensorflow.NumPy


NDArray GetData(IEnumerable<Slice> slices) NDArray GetData(IEnumerable<Slice> slices)
{ {
var tensor = _tensor[slices.ToArray()];
return new NDArray(tensor);
if (shape.IsScalar)
return GetScalar();

var tensor = base[slices.ToArray()];
if (tensor.Handle == null)
tensor = tf.defaultSession.eval(tensor);
return new NDArray(tensor.Handle);
}

unsafe T GetAtIndex<T>(params int[] indices) where T : unmanaged
{
var offset = (ulong)ShapeHelper.GetOffset(shape, indices);
return *((T*)data + offset);
}

NDArray GetScalar()
{
var array = new NDArray(Shape.Scalar, dtype: dtype);
unsafe
{
var src = (byte*)data + dtypesize;
System.Buffer.MemoryCopy(src, array.buffer.ToPointer(), bytesize, bytesize);
}
return array;
} }


NDArray GetData(int[] indices, int axis = 0) NDArray GetData(int[] indices, int axis = 0)
{ {
if (shape.IsScalar)
return GetScalar();

if(axis == 0) if(axis == 0)
{ {
var dims = shape.as_int_list(); var dims = shape.as_int_list();


+ 7
- 6
src/TensorFlowNET.Core/NumPy/NDArray.Operators.cs View File

@@ -8,11 +8,12 @@ namespace Tensorflow.NumPy
{ {
public partial class NDArray public partial class NDArray
{ {
public static NDArray operator +(NDArray lhs, NDArray rhs) => lhs.Tensor + rhs.Tensor;
public static NDArray operator -(NDArray lhs, NDArray rhs) => lhs.Tensor - rhs.Tensor;
public static NDArray operator *(NDArray lhs, NDArray rhs) => lhs.Tensor * rhs.Tensor;
public static NDArray operator /(NDArray lhs, NDArray rhs) => lhs.Tensor / rhs.Tensor;
public static NDArray operator >(NDArray lhs, NDArray rhs) => lhs.Tensor > rhs.Tensor;
public static NDArray operator <(NDArray lhs, NDArray rhs) => lhs.Tensor < rhs.Tensor;
public static NDArray operator +(NDArray lhs, NDArray rhs) => new NDArray(BinaryOpWrapper("add", lhs, rhs));
public static NDArray operator -(NDArray lhs, NDArray rhs) => new NDArray(BinaryOpWrapper("sub", lhs, rhs));
public static NDArray operator *(NDArray lhs, NDArray rhs) => new NDArray(BinaryOpWrapper("mul", lhs, rhs));
public static NDArray operator /(NDArray lhs, NDArray rhs) => new NDArray(BinaryOpWrapper("div", lhs, rhs));
public static NDArray operator >(NDArray lhs, NDArray rhs) => new NDArray(gen_math_ops.greater(lhs, rhs));
public static NDArray operator <(NDArray lhs, NDArray rhs) => new NDArray(gen_math_ops.less(lhs, rhs));
public static NDArray operator -(NDArray lhs) => new NDArray(gen_math_ops.neg(lhs));
} }
} }

+ 2
- 2
src/TensorFlowNET.Core/NumPy/NumPy.Logical.cs View File

@@ -10,9 +10,9 @@ namespace Tensorflow.NumPy
public partial class np public partial class np
{ {
public static NDArray logical_or(NDArray x1, NDArray x2) public static NDArray logical_or(NDArray x1, NDArray x2)
=> tf.logical_or(x1, x2);
=> new NDArray(tf.logical_or(x1, x2));


public static NDArray logical_and(NDArray x1, NDArray x2) public static NDArray logical_and(NDArray x1, NDArray x2)
=> tf.logical_and(x1, x2);
=> new NDArray(tf.logical_and(x1, x2));
} }
} }

+ 2
- 2
src/TensorFlowNET.Core/NumPy/NumPy.Statistics.cs View File

@@ -10,9 +10,9 @@ namespace Tensorflow.NumPy
public partial class np public partial class np
{ {
public static NDArray amin(NDArray x, int axis = 0) public static NDArray amin(NDArray x, int axis = 0)
=> tf.arg_min(x, axis);
=> new NDArray(tf.arg_min(x, axis));


public static NDArray amax(NDArray x, int axis = 0) public static NDArray amax(NDArray x, int axis = 0)
=> tf.arg_max(x, axis);
=> new NDArray(tf.arg_max(x, axis));
} }
} }

+ 9
- 9
src/TensorFlowNET.Core/NumPy/Numpy.Math.cs View File

@@ -10,30 +10,30 @@ namespace Tensorflow.NumPy
public partial class np public partial class np
{ {
public static NDArray exp(NDArray x) public static NDArray exp(NDArray x)
=> tf.exp(x);
=> new NDArray(tf.exp(x));


public static NDArray log(NDArray x) public static NDArray log(NDArray x)
=> tf.log(x);
=> new NDArray(tf.log(x));


public static NDArray multiply(NDArray x1, NDArray x2) public static NDArray multiply(NDArray x1, NDArray x2)
=> tf.multiply(x1, x2);
=> new NDArray(tf.multiply(x1, x2));


public static NDArray maximum(NDArray x1, NDArray x2) public static NDArray maximum(NDArray x1, NDArray x2)
=> tf.maximum(x1, x2);
=> new NDArray(tf.maximum(x1, x2));


public static NDArray minimum(NDArray x1, NDArray x2) public static NDArray minimum(NDArray x1, NDArray x2)
=> tf.minimum(x1, x2);
=> new NDArray(tf.minimum(x1, x2));


public static NDArray prod(NDArray array, Axis? axis = null, Type? dtype = null, bool keepdims = false) public static NDArray prod(NDArray array, Axis? axis = null, Type? dtype = null, bool keepdims = false)
=> tf.reduce_prod(array, axis: axis);
=> new NDArray(tf.reduce_prod(array, axis: axis));


public static NDArray prod<T>(params T[] array) where T : unmanaged public static NDArray prod<T>(params T[] array) where T : unmanaged
=> tf.reduce_prod(ops.convert_to_tensor(array));
=> new NDArray(tf.reduce_prod(new NDArray(array)));


public static NDArray sqrt(NDArray x) public static NDArray sqrt(NDArray x)
=> tf.sqrt(x);
=> new NDArray(tf.sqrt(x));


public static NDArray sum(NDArray x1, Axis? axis = null) public static NDArray sum(NDArray x1, Axis? axis = null)
=> tf.math.sum(x1, axis);
=> new NDArray(tf.math.sum(x1, axis));
} }
} }

+ 34
- 64
src/TensorFlowNET.Core/Numpy/NDArray.Creation.cs View File

@@ -8,18 +8,36 @@ namespace Tensorflow.NumPy
{ {
public partial class NDArray public partial class NDArray
{ {
public NDArray(bool value) => Init(value);
public NDArray(byte value) => Init(value);
public NDArray(short value) => Init(value);
public NDArray(int value) => Init(value);
public NDArray(long value) => Init(value);
public NDArray(float value) => Init(value);
public NDArray(double value) => Init(value);
public NDArray(Array value, Shape? shape = null) => Init(value, shape);
public NDArray(Shape shape, TF_DataType dtype = TF_DataType.TF_DOUBLE) => Init(shape, dtype: dtype);
public NDArray(Tensor value, Shape? shape = null) => Init(value, shape);
public NDArray(byte[] bytes, Shape shape, TF_DataType dtype) => Init(bytes, shape, dtype);
public NDArray(IntPtr address, Shape shape, TF_DataType dtype) => Init(address, shape, dtype);
public NDArray(bool value) : base(value) { NewEagerTensorHandle(); }
public NDArray(byte value) : base(value) { NewEagerTensorHandle(); }
public NDArray(short value) : base(value) { NewEagerTensorHandle(); }
public NDArray(int value) : base(value) { NewEagerTensorHandle(); }
public NDArray(long value) : base(value) { NewEagerTensorHandle(); }
public NDArray(float value) : base(value) { NewEagerTensorHandle(); }
public NDArray(double value) : base(value) { NewEagerTensorHandle(); }

public NDArray(Array value, Shape? shape = null)
: base(value, shape) { NewEagerTensorHandle(); }

public NDArray(Shape shape, TF_DataType dtype = TF_DataType.TF_DOUBLE)
: base(shape, dtype: dtype) { NewEagerTensorHandle(); }

public NDArray(byte[] bytes, Shape shape, TF_DataType dtype)
: base(bytes, shape, dtype) { NewEagerTensorHandle(); }

public NDArray(IntPtr address, Shape shape, TF_DataType dtype)
: base(address, shape, dtype) { NewEagerTensorHandle(); }

public NDArray(Tensor tensor) : base(tensor.Handle)
{
if (_handle is null)
{
tensor = tf.defaultSession.eval(tensor);
_handle = tensor.Handle;
}
NewEagerTensorHandle();
}


public static NDArray Scalar<T>(T value) where T : unmanaged public static NDArray Scalar<T>(T value) where T : unmanaged
=> value switch => value switch
@@ -33,59 +51,11 @@ namespace Tensorflow.NumPy
_ => throw new NotImplementedException("") _ => throw new NotImplementedException("")
}; };


void Init<T>(T value) where T : unmanaged
{
_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();
}

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

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

void Init(Tensor value, Shape? shape = null)
{
// created tensor in graph mode
if (value.TensorDataPointer == IntPtr.Zero)
{
if (!value.graph.building_function)
{
value = tf.defaultSession.eval(value);
value = new Tensor(value.TensorDataPointer, shape ?? value.shape, value.dtype);
}
}
_tensor = value;
_tensor.SetReferencedByNDArray();
}

void Init(byte[] bytes, Shape shape, TF_DataType dtype)
{
_tensor = new Tensor(bytes, shape, dtype);
_tensor.SetReferencedByNDArray();
}

void Init(IntPtr address, Shape shape, TF_DataType dtype)
void NewEagerTensorHandle()
{ {
_tensor = new Tensor(address, shape, dtype);
_tensor.SetReferencedByNDArray();
_id = ops.uid();
_eagerTensorHandle = c_api.TFE_NewTensorHandle(_handle, tf.Status.Handle);
tf.Status.Check(true);
} }
} }
} }

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

@@ -18,29 +18,14 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Tensorflow.Eager;
using static Tensorflow.Binding; using static Tensorflow.Binding;


namespace Tensorflow.NumPy namespace Tensorflow.NumPy
{ {
public partial class NDArray
public partial class NDArray : Tensor
{ {
Tensor _tensor;
public Tensor Tensor => _tensor;
public TF_DataType dtype => _tensor.dtype;
public ulong size => _tensor.size;
public ulong dtypesize => _tensor.dtypesize;
public ulong bytesize => _tensor.bytesize;
public int ndim => _tensor.ndim;
public long[] dims => _tensor.dims.Select(x => Convert.ToInt64(x)).ToArray();
public Shape shape => _tensor.shape;
public IntPtr data => _tensor.TensorDataPointer;

public T GetValue<T>(int index) where T : unmanaged
=> _tensor.ToArray<T>()[index];
public T GetAtIndex<T>(int index) where T : unmanaged
=> _tensor.ToArray<T>()[index];
public T[] GetData<T>() where T : unmanaged
=> _tensor.ToArray<T>();
public IntPtr data => TensorDataPointer;


public NDArray[] GetNDArrays() public NDArray[] GetNDArrays()
=> throw new NotImplementedException(""); => throw new NotImplementedException("");
@@ -53,21 +38,17 @@ namespace Tensorflow.NumPy


public bool HasNext() => throw new NotImplementedException(""); public bool HasNext() => throw new NotImplementedException("");
public T MoveNext<T>() => throw new NotImplementedException(""); public T MoveNext<T>() => throw new NotImplementedException("");
public NDArray reshape(Shape newshape) => new NDArray(tf.reshape(_tensor, newshape));
public NDArray astype(Type type) => new NDArray(math_ops.cast(_tensor, type.as_tf_dtype()));
public NDArray astype(TF_DataType dtype) => new NDArray(math_ops.cast(_tensor, dtype));
public NDArray reshape(Shape newshape) => new NDArray(tf.reshape(this, newshape));
public NDArray astype(TF_DataType dtype) => new NDArray(math_ops.cast(this, dtype));
public NDArray ravel() => throw new NotImplementedException(""); public NDArray ravel() => throw new NotImplementedException("");
public void shuffle(NDArray nd) => throw new NotImplementedException(""); public void shuffle(NDArray nd) => throw new NotImplementedException("");
public Array ToMuliDimArray<T>() => throw new NotImplementedException(""); public Array ToMuliDimArray<T>() => throw new NotImplementedException("");
public byte[] ToByteArray() => _tensor.BufferToArray();
public byte[] ToByteArray() => BufferToArray();
public static string[] AsStringArray(NDArray arr) => throw new NotImplementedException(""); public static string[] AsStringArray(NDArray arr) => throw new NotImplementedException("");


public T[] ToArray<T>() where T : unmanaged
=> _tensor.ToArray<T>();

public override string ToString() public override string ToString()
{ {
return tensor_util.to_numpy_string(_tensor);
return tensor_util.to_numpy_string(this);
} }
} }
} }

+ 2
- 5
src/TensorFlowNET.Core/Operations/array_ops.cs View File

@@ -226,9 +226,6 @@ namespace Tensorflow
case Tensor t: case Tensor t:
dtype = t.dtype.as_base_dtype(); dtype = t.dtype.as_base_dtype();
break; break;
case NDArray t:
dtype = t.dtype;
break;
} }


if (dtype != TF_DataType.DtInvalid) if (dtype != TF_DataType.DtInvalid)
@@ -1007,10 +1004,10 @@ namespace Tensorflow
var new_shape = new List<int>(); var new_shape = new List<int>();
foreach ((NDArray padding, int dim) in zip(paddings_constant.GetNDArrays(), np.array(input_shape.dims).GetNDArrays())) foreach ((NDArray padding, int dim) in zip(paddings_constant.GetNDArrays(), np.array(input_shape.dims).GetNDArrays()))
{ {
if (padding is null || dim == -1 || padding.GetData<int>().Contains(-1))
if (padding is null || dim == -1 || padding.ToArray<int>().Contains(-1))
new_shape.Add(-1); new_shape.Add(-1);
else else
new_shape.Add(np.sum(padding) + dim);
new_shape.Add((int)np.sum(padding) + dim);
} }
result.shape = new_shape.ToArray(); result.shape = new_shape.ToArray();
} }


+ 16
- 21
src/TensorFlowNET.Core/Operations/image_ops_impl.cs View File

@@ -355,7 +355,7 @@ or rank = 4. Had rank = {0}", rank));
if ((bool)h[1]) if ((bool)h[1])
{ {
hd = math_ops.cast((IVariableV1)h[0], dtypes.float64); hd = math_ops.cast((IVariableV1)h[0], dtypes.float64);
bbox_h_start = math_ops.cast(((int)hd - (int)hd * central_fraction) / 2, dtypes.int32);
bbox_h_start = ((int)hd - (int)hd * central_fraction) / 2;
} }
else else
{ {
@@ -367,7 +367,7 @@ or rank = 4. Had rank = {0}", rank));
if ((bool)w[1]) if ((bool)w[1])
{ {
wd = math_ops.cast((IVariableV1)w[0], dtypes.float64); wd = math_ops.cast((IVariableV1)w[0], dtypes.float64);
bbox_w_start = math_ops.cast(((int)wd - (int)wd * central_fraction) / 2, dtypes.int32);
bbox_w_start = ((int)wd - (int)wd * central_fraction) / 2;
} }
else else
{ {
@@ -734,20 +734,16 @@ new_height, new_width");
{ {
var _chcw_ = _ImageDimensions(images, rank: 4); var _chcw_ = _ImageDimensions(images, rank: 4);


var scale_factor_height = (
math_ops.cast(size[0], dtypes.float32) /
math_ops.cast(_chcw_[1], dtypes.float32));
var scale_factor_width = (
math_ops.cast(size[1], dtypes.float32) /
math_ops.cast(_chcw_[2], dtypes.float32));
var scale_factor_height =
math_ops.cast(size[0], dtypes.float32) / _chcw_[1];
var scale_factor_width =
math_ops.cast(size[1], dtypes.float32) / _chcw_[2];
var scale_factor = math_ops.minimum(scale_factor_height, scale_factor_width); var scale_factor = math_ops.minimum(scale_factor_height, scale_factor_width);
var scaled_height_const = math_ops.cast( var scaled_height_const = math_ops.cast(
math_ops.round(scale_factor *
math_ops.cast(_chcw_[1], dtypes.float32)),
math_ops.round(scale_factor * _chcw_[1]),
dtypes.int32); dtypes.int32);
var scaled_width_const = math_ops.cast( var scaled_width_const = math_ops.cast(
math_ops.round(scale_factor *
math_ops.cast(_chcw_[2], dtypes.float32)),
math_ops.round(scale_factor * _chcw_[2]),
dtypes.int32); dtypes.int32);


size = ops.convert_to_tensor(new[] { scaled_height_const, scaled_width_const }, size = ops.convert_to_tensor(new[] { scaled_height_const, scaled_width_const },
@@ -903,10 +899,10 @@ new_height, new_width");


var _hw_ = _ImageDimensions(image, rank: 4); var _hw_ = _ImageDimensions(image, rank: 4);


var f_height = math_ops.cast(_hw_[1], dtype: dtypes.float32);
var f_width = math_ops.cast(_hw_[2], dtype: dtypes.float32);
var f_target_height = math_ops.cast(target_height, dtype: dtypes.float32);
var f_target_width = math_ops.cast(target_width, dtype: dtypes.float32);
var f_height = _hw_[1];
var f_width = _hw_[2];
var f_target_height = target_height;
var f_target_width = target_width;


var ratio = (Tensor)max_(f_width / f_target_width, f_height / f_target_height); var ratio = (Tensor)max_(f_width / f_target_width, f_height / f_target_height);
var resized_height_float = f_height / ratio; var resized_height_float = f_height / ratio;
@@ -1520,7 +1516,7 @@ new_height, new_width");
using (ops.control_dependencies(checks)) using (ops.control_dependencies(checks))
img1 = array_ops.identity(img1); img1 = array_ops.identity(img1);


Tensor max_val_tensor = math_ops.cast(max_val, img1.dtype);
Tensor max_val_tensor = constant_op.constant(max_val, img1.dtype);
max_val_tensor = convert_image_dtype(max_val_tensor, dtypes.float32); max_val_tensor = convert_image_dtype(max_val_tensor, dtypes.float32);
img1 = convert_image_dtype(img1, dtypes.float32); img1 = convert_image_dtype(img1, dtypes.float32);
img2 = convert_image_dtype(img2, dtypes.float32); img2 = convert_image_dtype(img2, dtypes.float32);
@@ -1546,7 +1542,7 @@ new_height, new_width");
using (ops.control_dependencies(checks)) using (ops.control_dependencies(checks))
img1 = array_ops.identity(img1); img1 = array_ops.identity(img1);


Tensor max_val_tensor = math_ops.cast(max_val, img1.dtype);
Tensor max_val_tensor = constant_op.constant(max_val);
max_val_tensor = convert_image_dtype(max_val_tensor, dtypes.float32); max_val_tensor = convert_image_dtype(max_val_tensor, dtypes.float32);
img1 = convert_image_dtype(img1, dtypes.float32); img1 = convert_image_dtype(img1, dtypes.float32);
img2 = convert_image_dtype(img2, dtypes.float32); img2 = convert_image_dtype(img2, dtypes.float32);
@@ -2027,8 +2023,7 @@ new_height, new_width");
var pad = math_ops.cast( var pad = math_ops.cast(
gen_math_ops.ceil( gen_math_ops.ceil(
math_ops.cast( math_ops.cast(
math_ops.maximum(num_boxes, max_output_size), dtypes.float32) /
math_ops.cast(tile_size, dtypes.float32)),
math_ops.maximum(num_boxes, max_output_size), dtypes.float32) / tile_size),
dtypes.int32) * tile_size - num_boxes; dtypes.int32) * tile_size - num_boxes;
boxes = array_ops.pad( boxes = array_ops.pad(
math_ops.cast(scores, dtypes.float32), ops.convert_to_tensor(new object[,] { { 0, 0 }, { 0, pad }, { 0, 0 } })); math_ops.cast(scores, dtypes.float32), ops.convert_to_tensor(new object[,] { { 0, 0 }, { 0, pad }, { 0, 0 } }));
@@ -2078,7 +2073,7 @@ new_height, new_width");
array_ops.expand_dims( array_ops.expand_dims(
math_ops.range(num_boxes_after_padding, 0, -1), 0), math_ops.range(num_boxes_after_padding, 0, -1), 0),
max_output_size); max_output_size);
Tensor idx = num_boxes_after_padding - math_ops.cast(values.dims[0], dtypes.int32);
Tensor idx = num_boxes_after_padding - values.shape.as_int_list()[0];
idx = math_ops.minimum(idx, num_boxes - 1); idx = math_ops.minimum(idx, num_boxes - 1);


if (!sorted_input) if (!sorted_input)


+ 0
- 15
src/TensorFlowNET.Core/Operations/math_ops.cs View File

@@ -152,21 +152,6 @@ namespace Tensorflow
}); });
} }


public static Tensor cast(float x, TF_DataType dtype = TF_DataType.DtInvalid, string name = null)
{
var base_type = dtype.as_base_dtype();

return tf_with(ops.name_scope(name, "Cast", new { x }), scope =>
{
name = scope;
var x_tensor = ops.convert_to_tensor(x, name: "x");
if (x_tensor.dtype.as_base_dtype() != base_type)
x_tensor = gen_math_ops.cast(x_tensor, base_type, name: name);

return x_tensor;
});
}

public static Tensor cumsum<T>(Tensor x, T axis = default, bool exclusive = false, bool reverse = false, string name = null) public static Tensor cumsum<T>(Tensor x, T axis = default, bool exclusive = false, bool reverse = false, string name = null)
=> tf_with(ops.name_scope(name, "Cumsum", new { x }), scope => => tf_with(ops.name_scope(name, "Cumsum", new { x }), scope =>
{ {


+ 1
- 1
src/TensorFlowNET.Core/Operations/resource_variable_ops.cs View File

@@ -156,7 +156,7 @@ namespace Tensorflow


private static HandleData get_eager_safe_handle_data(Tensor handle) private static HandleData get_eager_safe_handle_data(Tensor handle)
{ {
if (handle == IntPtr.Zero)
if (handle.Handle == null)
{ {
var data = new HandleData(); var data = new HandleData();
data.ShapeAndType.Add(new HandleShapeAndType data.ShapeAndType.Add(new HandleShapeAndType


+ 5
- 8
src/TensorFlowNET.Core/Sessions/BaseSession.cs View File

@@ -169,10 +169,7 @@ namespace Tensorflow
throw new ValueError($"Tensor {v} does not match the expected dtype {key.dtype}, actual dtype: {v.dtype}"); throw new ValueError($"Tensor {v} does not match the expected dtype {key.dtype}, actual dtype: {v.dtype}");
feeds[i++] = new KeyValuePair<TF_Output, Tensor>(key._as_tf_output(), v); feeds[i++] = new KeyValuePair<TF_Output, Tensor>(key._as_tf_output(), v);
break; break;
case NDArray v:
feeds[i++] = new KeyValuePair<TF_Output, Tensor>(key._as_tf_output(), v);
break;
case IntPtr v:
case SafeTensorHandle v:
var tensor = new Tensor(v); var tensor = new Tensor(v);
if (tensor.dtype != key.dtype) if (tensor.dtype != key.dtype)
throw new ValueError($"Tensor {v} does not match the expected dtype {key.dtype}, actual dtype: {tensor.dtype}"); throw new ValueError($"Tensor {v} does not match the expected dtype {key.dtype}, actual dtype: {tensor.dtype}");
@@ -225,7 +222,7 @@ namespace Tensorflow
c_api.TF_SessionRun(_handle, c_api.TF_SessionRun(_handle,
run_options: null, run_options: null,
inputs: feed_dict.Select(f => f.Key).ToArray(), inputs: feed_dict.Select(f => f.Key).ToArray(),
input_values: feed_dict.Select(f => (IntPtr)f.Value).ToArray(),
input_values: feed_dict.Select(f => f.Value.Handle.DangerousGetHandle()).ToArray(),
ninputs: feed_dict.Length, ninputs: feed_dict.Length,
outputs: fetch_list, outputs: fetch_list,
output_values: output_values, output_values: output_values,
@@ -240,7 +237,7 @@ namespace Tensorflow
var result = new NDArray[fetch_list.Length]; var result = new NDArray[fetch_list.Length];


for (int i = 0; i < fetch_list.Length; i++) for (int i = 0; i < fetch_list.Length; i++)
result[i] = fetchValue(output_values[i]);
result[i] = fetchValue(new SafeTensorHandle(output_values[i]));


return result; return result;
} }
@@ -267,10 +264,10 @@ namespace Tensorflow


status.Check(true); status.Check(true);


return new Tensor(output_values[0]);
return new Tensor(new SafeTensorHandle(output_values[0]));
} }


private static unsafe NDArray fetchValue(IntPtr output)
private static unsafe NDArray fetchValue(SafeTensorHandle output)
{ {
var tensor = new Tensor(output); var tensor = new Tensor(output);
return tensor.numpy(); return tensor.numpy();


+ 44
- 0
src/TensorFlowNET.Core/Tensors/SafeTensorHandle.cs View File

@@ -0,0 +1,44 @@
/*****************************************************************************
Copyright 2018 The TensorFlow.NET Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
******************************************************************************/

using System;
using Tensorflow.Util;
using static Tensorflow.Binding;

namespace Tensorflow
{
public sealed class SafeTensorHandle : SafeTensorflowHandle
{
private SafeTensorHandle()
{
}

public SafeTensorHandle(IntPtr handle)
: base(handle)
{
}

protected override bool ReleaseHandle()
{
#if TRACK_TENSOR_LIFE
print($"Delete TensorHandle 0x{handle.ToString("x16")}");
#endif
c_api.TF_DeleteTensor(handle);
SetHandle(IntPtr.Zero);
return true;
}
}
}

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

@@ -28,7 +28,7 @@ namespace Tensorflow
[SuppressMessage("ReSharper", "InvokeAsExtensionMethod")] [SuppressMessage("ReSharper", "InvokeAsExtensionMethod")]
public partial class Tensor public partial class Tensor
{ {
public IntPtr TensorDataPointer => _handle == IntPtr.Zero ? IntPtr.Zero : TF_TensorData(_handle);
public IntPtr TensorDataPointer => _handle == null ? IntPtr.Zero : TF_TensorData(_handle);


public Tensor() public Tensor()
{ {
@@ -39,7 +39,7 @@ namespace Tensorflow
/// Create a Tensor object from an existing TF handle /// Create a Tensor object from an existing TF handle
/// </summary> /// </summary>
/// <param name="handle">Handle to a <see cref="Tensor"/> object.</param> /// <param name="handle">Handle to a <see cref="Tensor"/> object.</param>
public Tensor(IntPtr handle)
public Tensor(SafeTensorHandle handle)
{ {
_handle = handle; _handle = handle;
isCreatedInGraphMode = !tf.executing_eagerly(); isCreatedInGraphMode = !tf.executing_eagerly();
@@ -174,25 +174,25 @@ namespace Tensorflow
}; };
} }


unsafe IntPtr InitTensor<T>(T[] array, Shape shape, TF_DataType dtype) where T : unmanaged
unsafe SafeTensorHandle InitTensor<T>(T[] array, Shape shape, TF_DataType dtype) where T : unmanaged
{ {
fixed (T* addr = &array[0]) fixed (T* addr = &array[0])
return TF_NewTensor(shape, dtype, addr); return TF_NewTensor(shape, dtype, addr);
} }


unsafe IntPtr InitTensor<T>(T[,] array, Shape shape, TF_DataType dtype) where T : unmanaged
unsafe SafeTensorHandle InitTensor<T>(T[,] array, Shape shape, TF_DataType dtype) where T : unmanaged
{ {
fixed (T* addr = &array[0, 0]) fixed (T* addr = &array[0, 0])
return TF_NewTensor(shape, dtype, addr); return TF_NewTensor(shape, dtype, addr);
} }


unsafe IntPtr InitTensor<T>(T[,,] array, Shape shape, TF_DataType dtype) where T : unmanaged
unsafe SafeTensorHandle InitTensor<T>(T[,,] array, Shape shape, TF_DataType dtype) where T : unmanaged
{ {
fixed (T* addr = &array[0, 0, 0]) fixed (T* addr = &array[0, 0, 0])
return TF_NewTensor(shape, dtype, addr); return TF_NewTensor(shape, dtype, addr);
} }


unsafe IntPtr InitTensor<T>(T[,,,] array, Shape shape, TF_DataType dtype) where T : unmanaged
unsafe SafeTensorHandle InitTensor<T>(T[,,,] array, Shape shape, TF_DataType dtype) where T : unmanaged
{ {
fixed (T* addr = &array[0, 0, 0, 0]) fixed (T* addr = &array[0, 0, 0, 0])
return TF_NewTensor(shape, dtype, addr); return TF_NewTensor(shape, dtype, addr);


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

@@ -6,8 +6,8 @@ namespace Tensorflow
public partial class Tensor public partial class Tensor
{ {
public static Tensor operator !=(Tensor x, int y) public static Tensor operator !=(Tensor x, int y)
=> gen_math_ops.not_equal(x, math_ops.cast(y, dtype: x.dtype));
=> gen_math_ops.not_equal(x, constant_op.constant(y, dtype: x.dtype));
public static Tensor operator ==(Tensor x, int y) public static Tensor operator ==(Tensor x, int y)
=> gen_math_ops.equal(x, math_ops.cast(y, dtype: x.dtype));
=> gen_math_ops.equal(x, constant_op.constant(y, dtype: x.dtype));
} }
} }

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

@@ -1,23 +1,18 @@
using Tensorflow.NumPy;
using System;
using System;
using Tensorflow.NumPy;
using static Tensorflow.Binding; using static Tensorflow.Binding;


namespace Tensorflow namespace Tensorflow
{ {
public partial class Tensor public partial class Tensor
{ {
public static implicit operator IntPtr(Tensor tensor)
{
return tensor._handle;
}

public static implicit operator SafeTensorHandle(Tensor tensor)
=> tensor._handle;
public static implicit operator Operation(Tensor tensor) public static implicit operator Operation(Tensor tensor)
=> tensor?.op; => tensor?.op;


public static implicit operator TF_Tensor(Tensor tensor)
=> new TF_Tensor(tensor._handle);

public static implicit operator Tensor(IntPtr handle)
public static implicit operator Tensor(SafeTensorHandle handle)
=> new Tensor(handle); => new Tensor(handle);
} }
} }

+ 2
- 32
src/TensorFlowNET.Core/Tensors/Tensor.Operators.cs View File

@@ -24,35 +24,6 @@ namespace Tensorflow
{ {
public partial class Tensor public partial class Tensor
{ {
#if _REGEN
#region Compute
%operators = ["add", "sub", "mul", "div", "mod"]
%operators_sign = ["+", "-", "*", "/", "%"]
%operators_comparers = [">", "<", ">=", "<="]
%operators_comparers_names = ["greater", "less", "greater_equal", "less_equal"]

%possabilities = ["NDArray", "sbyte", "byte", "short", "ushort", "int", "uint", "ulong", "long", "float", "double", "Complex"]
%foreach operators, operators_sign%
public static Tensor operator #2(Tensor lhs, Tensor rhs) => BinaryOpWrapper("#1", lhs, rhs);
%foreach possabilities%
public static Tensor operator #2(Tensor lhs, #101 rhs) => BinaryOpWrapper("#1", lhs, rhs);
public static Tensor operator #2(#101 lhs, Tensor rhs) => BinaryOpWrapper("#1", lhs, rhs);
%
%

%foreach operators_comparers_names, operators_comparers %
public static Tensor operator #2(Tensor lhs, Tensor rhs) => gen_math_ops.#1(lhs, rhs);
%foreach possabilities%
public static Tensor operator #2(Tensor lhs, #101 rhs) => gen_math_ops.#1(lhs, rhs);
public static Tensor operator #2(#101 lhs, Tensor rhs) => gen_math_ops.#1(lhs, rhs);
%
%
public static Tensor operator -(Tensor x) => gen_math_ops.neg(x);
#endregion
#else
#region Compute

public static Tensor operator +(Tensor lhs, ResourceVariable rhs) => BinaryOpWrapper("add", lhs, rhs); public static Tensor operator +(Tensor lhs, ResourceVariable rhs) => BinaryOpWrapper("add", lhs, rhs);
public static Tensor operator +(Tensor lhs, Tensor rhs) => BinaryOpWrapper("add", lhs, rhs); public static Tensor operator +(Tensor lhs, Tensor rhs) => BinaryOpWrapper("add", lhs, rhs);
public static Tensor operator +(Tensor lhs, NDArray rhs) => BinaryOpWrapper("add", lhs, rhs); public static Tensor operator +(Tensor lhs, NDArray rhs) => BinaryOpWrapper("add", lhs, rhs);
@@ -281,8 +252,7 @@ namespace Tensorflow
public static Tensor operator <=(Tensor lhs, Complex rhs) => gen_math_ops.less_equal(lhs, rhs); public static Tensor operator <=(Tensor lhs, Complex rhs) => gen_math_ops.less_equal(lhs, rhs);
public static Tensor operator <=(Complex lhs, Tensor rhs) => gen_math_ops.less_equal(lhs, rhs); public static Tensor operator <=(Complex lhs, Tensor rhs) => gen_math_ops.less_equal(lhs, rhs);
public static Tensor operator -(Tensor x) => gen_math_ops.neg(x); public static Tensor operator -(Tensor x) => gen_math_ops.neg(x);
#endregion
#endif



private static readonly TF_DataType[] _intTfDataTypes = { private static readonly TF_DataType[] _intTfDataTypes = {
TF_DataType.TF_INT8, TF_DataType.TF_INT16, TF_DataType.TF_INT32, TF_DataType.TF_INT64, TF_DataType.TF_INT8, TF_DataType.TF_INT16, TF_DataType.TF_INT32, TF_DataType.TF_INT64,
@@ -306,7 +276,7 @@ namespace Tensorflow
return is_floating ? "truediv" : name; return is_floating ? "truediv" : name;
} }


private static Tensor BinaryOpWrapper<Tx, Ty>(string name, Tx x, Ty y)
protected static Tensor BinaryOpWrapper<Tx, Ty>(string name, Tx x, Ty y)
{ {
TF_DataType dtype = TF_DataType.DtInvalid; TF_DataType dtype = TF_DataType.DtInvalid;




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

@@ -10,7 +10,7 @@ namespace Tensorflow
{ {
const int TF_TSRING_SIZE = 24; const int TF_TSRING_SIZE = 24;


public IntPtr StringTensor(string[] strings, Shape shape)
public SafeTensorHandle StringTensor(string[] strings, Shape shape)
{ {
// convert string array to byte[][] // convert string array to byte[][]
var buffer = new byte[strings.Length][]; var buffer = new byte[strings.Length][];
@@ -20,7 +20,7 @@ namespace Tensorflow
return StringTensor(buffer, shape); return StringTensor(buffer, shape);
} }


public IntPtr StringTensor(byte[][] buffer, Shape shape)
public SafeTensorHandle StringTensor(byte[][] buffer, Shape shape)
{ {
var handle = c_api.TF_AllocateTensor(TF_DataType.TF_STRING, var handle = c_api.TF_AllocateTensor(TF_DataType.TF_STRING,
shape.ndim == 0 ? null : shape.dims, shape.ndim == 0 ? null : shape.dims,


+ 11
- 14
src/TensorFlowNET.Core/Tensors/Tensor.cs View File

@@ -70,12 +70,12 @@ namespace Tensorflow
/// <summary> /// <summary>
/// The DType of elements in this tensor. /// The DType of elements in this tensor.
/// </summary> /// </summary>
public TF_DataType dtype => _handle == IntPtr.Zero ? _override_dtype : c_api.TF_TensorType(_handle);
public ulong bytesize => _handle == IntPtr.Zero ? 0 : c_api.TF_TensorByteSize(_handle);
public ulong dtypesize => _handle == IntPtr.Zero ? 0 : c_api.TF_DataTypeSize(dtype);
public ulong size => _handle == IntPtr.Zero ? 0 : bytesize / dtypesize;
public IntPtr buffer => _handle == IntPtr.Zero ? IntPtr.Zero : c_api.TF_TensorData(_handle);
public int num_consumers(TF_Output oper_out) => _handle == IntPtr.Zero ? 0 : c_api.TF_OperationOutputNumConsumers(oper_out);
public TF_DataType dtype => _handle == null ? _override_dtype : c_api.TF_TensorType(_handle);
public ulong bytesize => _handle == null ? 0 : c_api.TF_TensorByteSize(_handle);
public ulong dtypesize => _handle == null ? 0 : c_api.TF_DataTypeSize(dtype);
public ulong size => _handle == null ? 0 : bytesize / dtypesize;
public IntPtr buffer => _handle == null ? IntPtr.Zero : c_api.TF_TensorData(_handle);
public int num_consumers(TF_Output oper_out) => _handle == null ? 0 : c_api.TF_OperationOutputNumConsumers(oper_out);
public int ndim => rank; public int ndim => rank;


/// <summary> /// <summary>
@@ -88,6 +88,8 @@ namespace Tensorflow
/// Used for keep other pointer when do implicit operating /// Used for keep other pointer when do implicit operating
/// </summary> /// </summary>
public object Tag { get; set; } public object Tag { get; set; }
protected new SafeTensorHandle _handle;
public SafeTensorHandle Handle => _handle;


protected SafeTensorHandleHandle _eagerTensorHandle; protected SafeTensorHandleHandle _eagerTensorHandle;
/// <summary> /// <summary>
@@ -118,7 +120,7 @@ namespace Tensorflow


var dims = new Shape(new long[rank]); var dims = new Shape(new long[rank]);


if (_handle == IntPtr.Zero)
if (_handle == null)
{ {
c_api.TF_GraphGetTensorShape(op.graph, _as_tf_output(), dims, rank, tf.Status.Handle); c_api.TF_GraphGetTensorShape(op.graph, _as_tf_output(), dims, rank, tf.Status.Handle);
} }
@@ -183,7 +185,7 @@ namespace Tensorflow
{ {
get get
{ {
if (_handle == IntPtr.Zero)
if (_handle == null)
{ {
var output = _as_tf_output(); var output = _as_tf_output();
int ndim = c_api.TF_GraphGetTensorNumDims(op.graph, output, tf.Status.Handle); int ndim = c_api.TF_GraphGetTensorNumDims(op.graph, output, tf.Status.Handle);
@@ -215,7 +217,7 @@ namespace Tensorflow


public void SetReferencedByNDArray() public void SetReferencedByNDArray()
{ {
if (_handle != IntPtr.Zero)
if (_handle is not null)
{ {
isReferencedByNDArray = true; isReferencedByNDArray = true;
_eagerTensorHandle = c_api.TFE_NewTensorHandle(_handle, tf.Status.Handle); _eagerTensorHandle = c_api.TFE_NewTensorHandle(_handle, tf.Status.Handle);
@@ -278,11 +280,6 @@ namespace Tensorflow
tstr += TF_TSRING_SIZE; tstr += TF_TSRING_SIZE;
} }
} }

c_api.TF_DeleteTensor(handle);

if (_eagerTensorHandle is not null)
_eagerTensorHandle.Dispose();
} }


public bool IsDisposed => _disposed; public bool IsDisposed => _disposed;


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

@@ -32,7 +32,7 @@ namespace Tensorflow
/// <param name="len">size_t</param> /// <param name="len">size_t</param>
/// <returns></returns> /// <returns></returns>
[DllImport(TensorFlowLibName)] [DllImport(TensorFlowLibName)]
public static extern IntPtr TF_AllocateTensor(TF_DataType dtype, long[] dims, int num_dims, ulong len);
public static extern SafeTensorHandle TF_AllocateTensor(TF_DataType dtype, long[] dims, int num_dims, ulong len);


/// <summary> /// <summary>
/// returns the sizeof() for the underlying type corresponding to the given TF_DataType enum value. /// returns the sizeof() for the underlying type corresponding to the given TF_DataType enum value.
@@ -57,7 +57,7 @@ namespace Tensorflow
/// <param name="dim_index"></param> /// <param name="dim_index"></param>
/// <returns></returns> /// <returns></returns>
[DllImport(TensorFlowLibName)] [DllImport(TensorFlowLibName)]
public static extern long TF_Dim(IntPtr tensor, int dim_index);
public static extern long TF_Dim(SafeTensorHandle tensor, int dim_index);


/// <summary> /// <summary>
/// Return a new tensor that holds the bytes data[0,len-1] /// Return a new tensor that holds the bytes data[0,len-1]
@@ -104,7 +104,7 @@ namespace Tensorflow
return 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(byte[] data, Shape shape, TF_DataType dtype)
public static unsafe SafeTensorHandle TF_NewTensor(byte[] data, Shape shape, TF_DataType dtype)
{ {
var length = data.Length; var length = data.Length;
var handle = TF_AllocateTensor(dtype, shape.dims, shape.ndim, (ulong)length); var handle = TF_AllocateTensor(dtype, shape.dims, shape.ndim, (ulong)length);
@@ -116,7 +116,7 @@ namespace Tensorflow
return handle; return handle;
} }


public static unsafe IntPtr TF_NewTensor(Shape shape, TF_DataType dtype, void* data)
public static unsafe SafeTensorHandle TF_NewTensor(Shape shape, TF_DataType dtype, void* data)
{ {
var length = shape.size * dtype.get_datatype_size(); var length = shape.size * dtype.get_datatype_size();
var handle = TF_AllocateTensor(dtype, shape.dims, shape.ndim, (ulong)length); var handle = TF_AllocateTensor(dtype, shape.dims, shape.ndim, (ulong)length);
@@ -128,7 +128,7 @@ namespace Tensorflow
return handle; return handle;
} }


public static unsafe IntPtr TF_NewTensor<T>(T value)
public static unsafe SafeTensorHandle TF_NewTensor<T>(T value)
where T : unmanaged where T : unmanaged
{ {
var dtype = value.GetType().as_tf_dtype(); var dtype = value.GetType().as_tf_dtype();
@@ -157,7 +157,7 @@ namespace Tensorflow
/// <param name="tensor"></param> /// <param name="tensor"></param>
/// <returns></returns> /// <returns></returns>
[DllImport(TensorFlowLibName)] [DllImport(TensorFlowLibName)]
public static extern int TF_NumDims(IntPtr tensor);
public static extern int TF_NumDims(SafeTensorHandle tensor);


/// <summary> /// <summary>
/// Return the size of the underlying data in bytes. /// Return the size of the underlying data in bytes.
@@ -165,7 +165,7 @@ namespace Tensorflow
/// <param name="tensor"></param> /// <param name="tensor"></param>
/// <returns></returns> /// <returns></returns>
[DllImport(TensorFlowLibName)] [DllImport(TensorFlowLibName)]
public static extern ulong TF_TensorByteSize(IntPtr tensor);
public static extern ulong TF_TensorByteSize(SafeTensorHandle tensor);


/// <summary> /// <summary>
/// Return a pointer to the underlying data buffer. /// Return a pointer to the underlying data buffer.
@@ -173,7 +173,7 @@ namespace Tensorflow
/// <param name="tensor"></param> /// <param name="tensor"></param>
/// <returns></returns> /// <returns></returns>
[DllImport(TensorFlowLibName)] [DllImport(TensorFlowLibName)]
public static extern IntPtr TF_TensorData(IntPtr tensor);
public static extern IntPtr TF_TensorData(SafeTensorHandle tensor);


/// <summary> /// <summary>
/// Deletes `tensor` and returns a new TF_Tensor with the same content if /// Deletes `tensor` and returns a new TF_Tensor with the same content if
@@ -182,7 +182,7 @@ namespace Tensorflow
/// <param name="tensor"></param> /// <param name="tensor"></param>
/// <returns></returns> /// <returns></returns>
[DllImport(TensorFlowLibName)] [DllImport(TensorFlowLibName)]
public static extern IntPtr TF_TensorMaybeMove(IntPtr tensor);
public static extern SafeTensorHandle TF_TensorMaybeMove(SafeTensorHandle tensor);


/// <summary> /// <summary>
/// Return the type of a tensor element. /// Return the type of a tensor element.
@@ -190,7 +190,7 @@ namespace Tensorflow
/// <param name="tensor"></param> /// <param name="tensor"></param>
/// <returns></returns> /// <returns></returns>
[DllImport(TensorFlowLibName)] [DllImport(TensorFlowLibName)]
public static extern TF_DataType TF_TensorType(IntPtr tensor);
public static extern TF_DataType TF_TensorType(SafeTensorHandle tensor);


/// <summary> /// <summary>
/// Return the size in bytes required to encode a string `len` bytes long into a /// Return the size in bytes required to encode a string `len` bytes long into a
@@ -232,7 +232,7 @@ namespace Tensorflow
public static extern IntPtr TF_StringGetDataPointer(IntPtr tst); public static extern IntPtr TF_StringGetDataPointer(IntPtr tst);


[DllImport(TensorFlowLibName)] [DllImport(TensorFlowLibName)]
public static extern TF_TString_Type TF_StringGetType(IntPtr tst);
public static extern TF_TString_Type TF_StringGetType(SafeTensorHandle tst);


[DllImport(TensorFlowLibName)] [DllImport(TensorFlowLibName)]
public static extern ulong TF_StringGetSize(IntPtr tst); public static extern ulong TF_StringGetSize(IntPtr tst);


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

@@ -101,7 +101,7 @@ namespace Tensorflow
value is NDArray nd && value is NDArray nd &&
nd.dtype != dtype) nd.dtype != dtype)
{ {
value = nd.astype(dtype.as_system_dtype());
value = nd.astype(dtype);
} }


// non ascii char // non ascii char


+ 8
- 8
src/TensorFlowNET.Core/Tensors/tensor_util.cs View File

@@ -35,8 +35,8 @@ namespace Tensorflow
/// <returns></returns> /// <returns></returns>
public static NDArray constant_value(Tensor tensor, bool partial = false) public static NDArray constant_value(Tensor tensor, bool partial = false)
{ {
if (tensor.IsReferencedByNDArray)
return new NDArray(tensor);
if (tensor is NDArray nd)
return nd;
else if (tensor is EagerTensor) else if (tensor is EagerTensor)
return tensor.numpy(); return tensor.numpy();


@@ -230,7 +230,7 @@ namespace Tensorflow
throw new ValueError( throw new ValueError(
@"Received a scalar with unknown value as shape; require a statically @"Received a scalar with unknown value as shape; require a statically
known scalar with value '-1' to describe an unknown shape."); known scalar with value '-1' to describe an unknown shape.");
if (value_ != -1)
if ((int)value_ != -1)
throw new ValueError( throw new ValueError(
String.Format(@"Received a scalar value {0} as shape; require a statically known String.Format(@"Received a scalar value {0} as shape; require a statically known
scalar with value '-1' to describe an unknown shape.", value_)); scalar with value '-1' to describe an unknown shape.", value_));
@@ -257,7 +257,7 @@ scalar with value '-1' to describe an unknown shape.", value_));
x_[x_.Length] = x; x_[x_.Length] = x;
else else
x_[x_.Length] = -1; x_[x_.Length] = -1;
var dest_dtype_shape_array = np.array(x_).astype(cast_dtype.as_system_dtype());
var dest_dtype_shape_array = np.array(x_).astype(cast_dtype);


long[] y_ = { }; long[] y_ = { };
foreach (int y in dest_dtype_shape_array.ToArray<int>()) foreach (int y in dest_dtype_shape_array.ToArray<int>())
@@ -280,7 +280,7 @@ scalar with value '-1' to describe an unknown shape.", value_));
would not be rank 1.", tensor.op.get_attr("axis"))); would not be rank 1.", tensor.op.get_attr("axis")));
foreach (Tensor pack_input in tensor.op.inputs) foreach (Tensor pack_input in tensor.op.inputs)
{ {
var pack_input_val = constant_value(pack_input);
var pack_input_val = (int)constant_value(pack_input);
Dimension new_dim; Dimension new_dim;
if (pack_input_val < 0) if (pack_input_val < 0)
{ {
@@ -350,12 +350,12 @@ would not be rank 1.", tensor.op.get_attr("axis")));
// sorry for the mess here, but this hacky solution was the best way // sorry for the mess here, but this hacky solution was the best way
// i could come up with to implement the things done in python in c# // i could come up with to implement the things done in python in c#
var prev_ = constant_value_as_shape(tensor.op.inputs[0]).dims; var prev_ = constant_value_as_shape(tensor.op.inputs[0]).dims;
var prev = prev_.Skip(begin).Take(end - begin).ToArray();
var prev = prev_.Skip((int)begin).Take((int)end - (int)begin).ToArray();
// 100 being the comparison doesn't really matter here; it's going to break anyway // 100 being the comparison doesn't really matter here; it's going to break anyway
for (int iter = 0; iter != 100; iter = iter + strides)
for (int iter = 0; iter != 100; iter = iter + (int)strides)
{ {
prev[prev.Length] = prev_[iter]; prev[prev.Length] = prev_[iter];
if ((iter + strides) > prev_.Length)
if ((iter + (int)strides) > prev_.Length)
break; break;
} }
var ret_ = new Shape(prev); var ret_ = new Shape(prev);


+ 1
- 1
src/TensorFlowNET.Core/Variables/BaseResourceVariable.cs View File

@@ -75,7 +75,7 @@ namespace Tensorflow
} }
else else
{ {
_handle = handle;
_handle = handle.Handle == null ? IntPtr.Zero : handle.Handle.DangerousGetHandle();
} }


#if TRACK_TENSOR_LIFE #if TRACK_TENSOR_LIFE


+ 2
- 2
src/TensorFlowNET.Keras/Layers/Rescaling/Rescaling.cs View File

@@ -19,8 +19,8 @@ namespace Tensorflow.Keras.Layers


protected override Tensors Call(Tensors inputs, Tensor state = null, bool? training = null) protected override Tensors Call(Tensors inputs, Tensor state = null, bool? training = null)
{ {
scale = math_ops.cast(args.Scale, args.DType);
offset = math_ops.cast(args.Offset, args.DType);
scale = constant_op.constant(args.Scale, args.DType);
offset = constant_op.constant(args.Offset, args.DType);
return math_ops.cast(inputs, args.DType) * scale + offset; return math_ops.cast(inputs, args.DType) * scale + offset;
} }




+ 4
- 4
src/TensorFlowNET.Keras/Optimizers/PolynomialDecay.cs View File

@@ -37,11 +37,11 @@ namespace Tensorflow.Keras.Optimizers
name = scope; name = scope;
var initial_learning_rate_tensor = ops.convert_to_tensor(initial_learning_rate, name: "initial_learning_rate"); var initial_learning_rate_tensor = ops.convert_to_tensor(initial_learning_rate, name: "initial_learning_rate");
var dtype = initial_learning_rate_tensor.dtype; var dtype = initial_learning_rate_tensor.dtype;
var end_learning_rate_tensor = math_ops.cast(end_learning_rate, dtype);
var power_tensor = math_ops.cast(power, dtype);
var end_learning_rate_tensor = constant_op.constant(end_learning_rate, dtype);
var power_tensor = constant_op.constant(power, dtype);


var global_step_recomp = math_ops.cast(step, dtype);
var decay_steps_recomp = math_ops.cast(decay_steps, dtype);
var global_step_recomp = constant_op.constant(step, dtype);
var decay_steps_recomp = constant_op.constant(decay_steps, dtype);


if (cycle) if (cycle)
{ {


+ 2
- 2
src/TensorFlowNET.Keras/Preprocessings/Preprocessing.image_dataset_from_directory.cs View File

@@ -119,8 +119,8 @@ namespace Tensorflow.Keras
rng.shuffle(start_positions); rng.shuffle(start_positions);
} }


var sequence_length_tensor = math_ops.cast(sequence_length, dtype: index_dtype);
var sampling_rate_tensor = math_ops.cast(sampling_rate, dtype: index_dtype);
var sequence_length_tensor = constant_op.constant(sequence_length, dtype: index_dtype);
var sampling_rate_tensor = constant_op.constant(sampling_rate, dtype: index_dtype);


var start_positions_tensor = tf.constant(start_positions); var start_positions_tensor = tf.constant(start_positions);
var positions_ds = tf.data.Dataset.from_tensors(start_positions_tensor).repeat(); var positions_ds = tf.data.Dataset.from_tensors(start_positions_tensor).repeat();


+ 2
- 2
src/TensorFlowNET.Keras/Preprocessings/Tokenizer.cs View File

@@ -429,9 +429,9 @@ namespace Tensorflow.Keras.Text
var c = kv.Value + 0.0; var c = kv.Value + 0.0;
var id = 0; var id = 0;
var _ = index_docs.TryGetValue(j, out id); var _ = index_docs.TryGetValue(j, out id);
var tf = 1.0 + np.log(c);
var tf = 1.0 + (double)np.log(c);
var idf = np.log(1.0 + document_count / (1 + id)); var idf = np.log(1.0 + document_count / (1 + id));
x[i, j] = tf * idf;
x[i, j] = tf * (double)idf;
} }
} }
} }


+ 2
- 2
src/TensorFlowNet.Benchmarks/Leak/GpuLeakByCNN.cs View File

@@ -24,7 +24,7 @@ namespace Tensorflow.Benchmark.Leak


var bytes = new byte[num * width * height * 3]; var bytes = new byte[num * width * height * 3];
var inputImages = np.array(bytes) / 255.0f; var inputImages = np.array(bytes) / 255.0f;
inputImages = inputImages.reshape((num, height, width, 3));
// inputImages = inputImages.reshape((num, height, width, 3));


bytes = new byte[num]; bytes = new byte[num];
var outLables = np.array(bytes); var outLables = np.array(bytes);
@@ -50,7 +50,7 @@ namespace Tensorflow.Benchmark.Leak
optimizer: keras.optimizers.RMSprop(), optimizer: keras.optimizers.RMSprop(),
metrics: new[] { "accuracy" }); metrics: new[] { "accuracy" });


model.fit(inputImages, outLables, batch_size: 32, epochs: 200);
model.fit(new NDArray(inputImages), outLables, batch_size: 32, epochs: 200);


keras.backend.clear_session(); keras.backend.clear_session();
} }


+ 17
- 17
test/TensorFlowNET.Graph.UnitTest/GradientTest/GradientTest.cs View File

@@ -81,8 +81,8 @@ namespace TensorFlowNET.UnitTest.Gradient
using (var sess = tf.Session()) using (var sess = tf.Session())
{ {
var result = sess.run(g); var result = sess.run(g);
var resultList = result[0].GetData<float>().ToList();
resultList.AddRange(result[1].GetData<float>());
var resultList = result[0].ToArray<float>().ToList();
resultList.AddRange(result[1].ToArray<float>());
Console.WriteLine(result.ToString()); Console.WriteLine(result.ToString());
CollectionAssert.AreEqual(resultList.ToArray(), checkG); CollectionAssert.AreEqual(resultList.ToArray(), checkG);
} }
@@ -100,7 +100,7 @@ namespace TensorFlowNET.UnitTest.Gradient
using (var session = tf.Session()) using (var session = tf.Session())
{ {
var result = session.run(new[] { y, g[0] }); var result = session.run(new[] { y, g[0] });
return (result[0].GetData<T>()[0], result[1].GetData<T>()[0]);
return (result[0].ToArray<T>()[0], result[1].ToArray<T>()[0]);
} }
} }


@@ -184,8 +184,8 @@ namespace TensorFlowNET.UnitTest.Gradient
using (var sess = tf.Session()) using (var sess = tf.Session())
{ {
var result = sess.run(g); var result = sess.run(g);
var actual = result[0].GetData<float>()[0];
self.assertEquals(0.41997434127f, actual);
var actual = result[0];
Assert.AreEqual(actual, 0.41997434127f);
} }
} }


@@ -199,10 +199,10 @@ namespace TensorFlowNET.UnitTest.Gradient
using (var sess = tf.Session()) using (var sess = tf.Session())
{ {
var result = sess.run(new object[] { g, b }); var result = sess.run(new object[] { g, b });
var actualDeriv = result[0].GetData<float>()[0];
var actual = result[1].GetData<float>()[0];
self.assertEquals(1.5061177f, actualDeriv);
self.assertEquals(3.17805386f, actual);
var actualDeriv = result[0];
var actual = result[1];
Assert.AreEqual(actualDeriv, 1.5061177f);
Assert.AreEqual(actual, 3.17805386f);
} }
} }


@@ -221,8 +221,8 @@ namespace TensorFlowNET.UnitTest.Gradient
var result = sess.run(new object[] { g, b }); var result = sess.run(new object[] { g, b });
var actualDeriv = np.squeeze(result[0]); var actualDeriv = np.squeeze(result[0]);
var actual = np.squeeze(result[1]); var actual = np.squeeze(result[1]);
self.assertEquals(new float[] { 1, 0 }, new float[] { actualDeriv[0], actualDeriv[1] });
self.assertEquals(0.9640276f, (float)actual);
Assert.AreEqual(actualDeriv, new float[] { 1, 0 });
Assert.AreEqual(actual, 0.9640276f);
} }
} }


@@ -236,10 +236,10 @@ namespace TensorFlowNET.UnitTest.Gradient
using (var sess = tf.Session()) using (var sess = tf.Session())
{ {
var result = sess.run(new object[] { g, a }); var result = sess.run(new object[] { g, a });
var actualDeriv = result[0].GetData<float>()[0];
var actual = result[1].GetData<float>()[0];
self.assertEquals(1f, actualDeriv);
self.assertEquals(2f, actual);
var actualDeriv = result[0][0];
var actual = result[1][0];
Assert.AreEqual(actualDeriv, 1f);
Assert.AreEqual(actual, 2f);
} }
} }


@@ -252,8 +252,8 @@ namespace TensorFlowNET.UnitTest.Gradient
using (var sess = tf.Session()) using (var sess = tf.Session())
{ {
var result = sess.run(g); var result = sess.run(g);
var actual = result[0].GetData<float>()[0];
self.assertEquals(0.41997434127f, actual);
var actual = result[0];
Assert.AreEqual(actual, 0.41997434127f);
} }
} }
[Ignore("TODO")] [Ignore("TODO")]


+ 2
- 2
test/TensorFlowNET.Graph.UnitTest/MultithreadingTests.cs View File

@@ -195,7 +195,7 @@ namespace TensorFlowNET.UnitTest
using (var sess = tf.Session()) using (var sess = tf.Session())
{ {
var result = sess.run(math); var result = sess.run(math);
Assert.AreEqual(result.GetAtIndex<float>(0), 5f);
Assert.AreEqual(result[0], 5f);
} }
} }
} }
@@ -218,7 +218,7 @@ namespace TensorFlowNET.UnitTest
var math = a1 + a2; var math = a1 + a2;


var result = sess.run(math); var result = sess.run(math);
Assert.AreEqual(result.GetAtIndex<float>(0), 5f);
Assert.AreEqual(result[0], 5f);
} }
} }
} }


+ 1
- 1
test/TensorFlowNET.Graph.UnitTest/PythonTest.cs View File

@@ -127,7 +127,7 @@ namespace TensorFlowNET.UnitTest
public void assertAllClose(double value, NDArray array2, double eps = 1e-5) public void assertAllClose(double value, NDArray array2, double eps = 1e-5)
{ {
var array1 = np.ones_like(array2) * value; var array1 = np.ones_like(array2) * value;
Assert.IsTrue(np.allclose(array1, array2, rtol: eps));
// Assert.IsTrue(np.allclose(array1, array2, rtol: eps));
} }


public void assertProtoEquals(object toProto, object o) public void assertProtoEquals(object toProto, object o)


+ 6
- 6
test/TensorFlowNET.Native.UnitTest/CApiTest.cs View File

@@ -74,13 +74,13 @@ namespace Tensorflow.Native.UnitTest
protected SafeStatusHandle TF_NewStatus() protected SafeStatusHandle TF_NewStatus()
=> c_api.TF_NewStatus(); => c_api.TF_NewStatus();


protected void TF_DeleteTensor(IntPtr t)
=> c_api.TF_DeleteTensor(t);
protected void TF_DeleteTensor(SafeTensorHandle t)
=> c_api.TF_DeleteTensor(t.DangerousGetHandle());


protected IntPtr TF_TensorData(IntPtr t)
protected IntPtr TF_TensorData(SafeTensorHandle t)
=> c_api.TF_TensorData(t); => c_api.TF_TensorData(t);


protected ulong TF_TensorByteSize(IntPtr t)
protected ulong TF_TensorByteSize(SafeTensorHandle t)
=> c_api.TF_TensorByteSize(t); => c_api.TF_TensorByteSize(t);


protected void TFE_OpAddInput(SafeOpHandle op, SafeTensorHandleHandle h, SafeStatusHandle status) protected void TFE_OpAddInput(SafeOpHandle op, SafeTensorHandleHandle h, SafeStatusHandle status)
@@ -98,7 +98,7 @@ namespace Tensorflow.Native.UnitTest
protected SafeOpHandle TFE_NewOp(SafeContextHandle ctx, string op_or_function_name, SafeStatusHandle status) protected SafeOpHandle TFE_NewOp(SafeContextHandle ctx, string op_or_function_name, SafeStatusHandle status)
=> c_api.TFE_NewOp(ctx, op_or_function_name, status); => c_api.TFE_NewOp(ctx, op_or_function_name, status);


protected SafeTensorHandleHandle TFE_NewTensorHandle(IntPtr t, SafeStatusHandle status)
protected SafeTensorHandleHandle TFE_NewTensorHandle(SafeTensorHandle t, SafeStatusHandle status)
=> c_api.TFE_NewTensorHandle(t, status); => c_api.TFE_NewTensorHandle(t, status);


protected void TFE_Execute(SafeOpHandle op, SafeTensorHandleHandle[] retvals, out int num_retvals, SafeStatusHandle status) protected void TFE_Execute(SafeOpHandle op, SafeTensorHandleHandle[] retvals, out int num_retvals, SafeStatusHandle status)
@@ -128,7 +128,7 @@ namespace Tensorflow.Native.UnitTest
protected void TFE_ExecutorWaitForAllPendingNodes(SafeExecutorHandle executor, SafeStatusHandle status) protected void TFE_ExecutorWaitForAllPendingNodes(SafeExecutorHandle executor, SafeStatusHandle status)
=> c_api.TFE_ExecutorWaitForAllPendingNodes(executor, status); => c_api.TFE_ExecutorWaitForAllPendingNodes(executor, status);


protected IntPtr TFE_TensorHandleResolve(SafeTensorHandleHandle h, SafeStatusHandle status)
protected SafeTensorHandle TFE_TensorHandleResolve(SafeTensorHandleHandle h, SafeStatusHandle status)
=> c_api.TFE_TensorHandleResolve(h, status); => c_api.TFE_TensorHandleResolve(h, status);


protected string TFE_TensorHandleDeviceName(SafeTensorHandleHandle h, SafeStatusHandle status) protected string TFE_TensorHandleDeviceName(SafeTensorHandleHandle h, SafeStatusHandle status)


+ 2
- 2
test/TensorFlowNET.Native.UnitTest/Eager/Eager.Execute_MatMul_CPU.cs View File

@@ -27,7 +27,7 @@ namespace Tensorflow.Native.UnitTest.Eager
return c_api.TFE_NewContext(opts, status); return c_api.TFE_NewContext(opts, status);
} }


IntPtr t;
SafeTensorHandle t;
using (var ctx = NewContext(async, status)) using (var ctx = NewContext(async, status))
{ {
CHECK_EQ(TF_OK, TF_GetCode(status), TF_Message(status)); CHECK_EQ(TF_OK, TF_GetCode(status), TF_Message(status));
@@ -58,7 +58,7 @@ namespace Tensorflow.Native.UnitTest.Eager
EXPECT_EQ(product.Length * sizeof(float), (int)TF_TensorByteSize(t)); EXPECT_EQ(product.Length * sizeof(float), (int)TF_TensorByteSize(t));
tf.memcpy(product, TF_TensorData(t), TF_TensorByteSize(t)); tf.memcpy(product, TF_TensorData(t), TF_TensorByteSize(t));


c_api.TF_DeleteTensor(t);
c_api.TF_DeleteTensor(t.DangerousGetHandle());
EXPECT_EQ(7f, product[0]); EXPECT_EQ(7f, product[0]);
EXPECT_EQ(10f, product[1]); EXPECT_EQ(10f, product[1]);
EXPECT_EQ(15f, product[2]); EXPECT_EQ(15f, product[2]);


+ 1
- 1
test/TensorFlowNET.Native.UnitTest/Eager/Eager.TensorHandle.cs View File

@@ -25,7 +25,7 @@ namespace Tensorflow.Native.UnitTest.Eager
EXPECT_EQ(2.0f, data[1]); EXPECT_EQ(2.0f, data[1]);
EXPECT_EQ(3.0f, data[2]); EXPECT_EQ(3.0f, data[2]);
EXPECT_EQ(4.0f, data[3]); EXPECT_EQ(4.0f, data[3]);
c_api.TF_DeleteTensor(t);
c_api.TF_DeleteTensor(t.DangerousGetHandle());
} }
} }
} }

+ 1
- 1
test/TensorFlowNET.Native.UnitTest/Eager/Eager.Variables.cs View File

@@ -51,7 +51,7 @@ namespace Tensorflow.Native.UnitTest.Eager
ASSERT_EQ(TF_OK, TF_GetCode(status), TF_Message(status)); ASSERT_EQ(TF_OK, TF_GetCode(status), TF_Message(status));
ASSERT_EQ(sizeof(float), (int)TF_TensorByteSize(t)); ASSERT_EQ(sizeof(float), (int)TF_TensorByteSize(t));
tf.memcpy(&value, TF_TensorData(t).ToPointer(), sizeof(float)); tf.memcpy(&value, TF_TensorData(t).ToPointer(), sizeof(float));
c_api.TF_DeleteTensor(t);
c_api.TF_DeleteTensor(t.DangerousGetHandle());
EXPECT_EQ(12.0f, value); EXPECT_EQ(12.0f, value);
} }
finally finally


+ 1
- 1
test/TensorFlowNET.Native.UnitTest/Eager/Eager.cs View File

@@ -21,7 +21,7 @@ namespace Tensorflow.Native.UnitTest.Eager
using var status = c_api.TF_NewStatus(); using var status = c_api.TF_NewStatus();
var th = c_api.TFE_NewTensorHandle(t, status); var th = c_api.TFE_NewTensorHandle(t, status);
CHECK_EQ(TF_OK, TF_GetCode(status), TF_Message(status)); CHECK_EQ(TF_OK, TF_GetCode(status), TF_Message(status));
c_api.TF_DeleteTensor(t);
c_api.TF_DeleteTensor(t.DangerousGetHandle());
return th; return th;
} }




+ 1
- 1
test/TensorFlowNET.Native.UnitTest/Functions/FunctionTest.cs View File

@@ -452,7 +452,7 @@ namespace Tensorflow.Native.UnitTest
for (int i = 0; i < expected_results.Length; ++i) for (int i = 0; i < expected_results.Length; ++i)
{ {
var output = csession.output_tensor(i); var output = csession.output_tensor(i);
ASSERT_TRUE(output != IntPtr.Zero);
ASSERT_TRUE(!output.IsInvalid);
EXPECT_EQ(TF_DataType.TF_INT32, c_api.TF_TensorType(output)); EXPECT_EQ(TF_DataType.TF_INT32, c_api.TF_TensorType(output));
EXPECT_EQ(0, c_api.TF_NumDims(output)); EXPECT_EQ(0, c_api.TF_NumDims(output));
ASSERT_EQ(sizeof(int), (int)c_api.TF_TensorByteSize(output)); ASSERT_EQ(sizeof(int), (int)c_api.TF_TensorByteSize(output));


+ 5
- 5
test/TensorFlowNET.Native.UnitTest/Sessions/CSession.cs View File

@@ -64,7 +64,7 @@ namespace Tensorflow.Native.UnitTest
foreach (var output in outputs) foreach (var output in outputs)
{ {
outputs_.Add(output); outputs_.Add(output);
output_values_.Add(IntPtr.Zero);
output_values_.Add(new SafeTensorHandle(IntPtr.Zero));
} }
} }


@@ -77,7 +77,7 @@ namespace Tensorflow.Native.UnitTest
public unsafe void Run(Status s) public unsafe void Run(Status s)
{ {
var inputs_ptr = inputs_.ToArray(); var inputs_ptr = inputs_.ToArray();
var input_values_ptr = input_values_.Select(x => (IntPtr)x).ToArray();
var input_values_ptr = input_values_.Select(x => x.Handle.DangerousGetHandle()).ToArray();
var outputs_ptr = outputs_.ToArray(); var outputs_ptr = outputs_.ToArray();
var output_values_ptr = output_values_.Select(x => IntPtr.Zero).ToArray(); var output_values_ptr = output_values_.Select(x => IntPtr.Zero).ToArray();
IntPtr[] targets_ptr = new IntPtr[0]; IntPtr[] targets_ptr = new IntPtr[0];
@@ -90,12 +90,12 @@ namespace Tensorflow.Native.UnitTest
s.Check(); s.Check();


for (var i = 0; i < outputs_.Count; i++) for (var i = 0; i < outputs_.Count; i++)
output_values_[i] = output_values_ptr[i];
output_values_[i] = new SafeTensorHandle(output_values_ptr[i]);
} }


public IntPtr output_tensor(int i)
public SafeTensorHandle output_tensor(int i)
{ {
return output_values_[i];
return output_values_[i].Handle;
} }


public void CloseAndDelete(Status s) public void CloseAndDelete(Status s)


+ 1
- 1
test/TensorFlowNET.Native.UnitTest/Sessions/SessionTest.cs View File

@@ -59,7 +59,7 @@ namespace Tensorflow.Native.UnitTest.Sessions
ASSERT_EQ(TF_Code.TF_OK, s.Code); ASSERT_EQ(TF_Code.TF_OK, s.Code);


outTensor = csession.output_tensor(0); outTensor = csession.output_tensor(0);
ASSERT_TRUE(outTensor != IntPtr.Zero);
ASSERT_TRUE(outTensor.Handle.DangerousGetHandle() != IntPtr.Zero);
EXPECT_EQ(TF_DataType.TF_INT32, outTensor.dtype); EXPECT_EQ(TF_DataType.TF_INT32, outTensor.dtype);
EXPECT_EQ(0, outTensor.ndim); // scalar EXPECT_EQ(0, outTensor.ndim); // scalar
ASSERT_EQ((ulong)sizeof(uint), outTensor.bytesize); ASSERT_EQ((ulong)sizeof(uint), outTensor.bytesize);


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

@@ -83,7 +83,7 @@ namespace Tensorflow.Native.UnitTest.Tensors
NDArray nd = np.array(2, 3); NDArray nd = np.array(2, 3);
Tensor t = new Tensor(nd); Tensor t = new Tensor(nd);
Tensor o = t.MaybeMove(); Tensor o = t.MaybeMove();
ASSERT_TRUE(o == IntPtr.Zero); // It is unsafe to move memory TF might not own.
ASSERT_TRUE(o.Handle.IsInvalid); // It is unsafe to move memory TF might not own.
t.Dispose(); t.Dispose();
} }


@@ -91,7 +91,7 @@ namespace Tensorflow.Native.UnitTest.Tensors
/// Port from c_api_test.cc /// Port from c_api_test.cc
/// `TEST(CAPI, Tensor)` /// `TEST(CAPI, Tensor)`
/// </summary> /// </summary>
[TestMethod, Ignore("")]
[TestMethod]
public void Tensor() public void Tensor()
{ {
var nd = np.array(1f, 2f, 3f, 4f, 5f, 6f).reshape((2, 3)); var nd = np.array(1f, 2f, 3f, 4f, 5f, 6f).reshape((2, 3));


+ 1
- 1
test/TensorFlowNET.UnitTest/Basics/SessionTest.cs View File

@@ -24,7 +24,7 @@ namespace TensorFlowNET.UnitTest
using (var sess = tf.Session()) using (var sess = tf.Session())
{ {
var result = c.eval(sess); var result = c.eval(sess);
Assert.AreEqual(6, result.GetAtIndex<double>(0));
Assert.AreEqual(result[0], 6.0);
} }
} }
} }


+ 1
- 1
test/TensorFlowNET.UnitTest/PythonTest.cs View File

@@ -141,7 +141,7 @@ namespace TensorFlowNET.UnitTest
public void assertAllClose(double value, NDArray array2, double eps = 1e-5) public void assertAllClose(double value, NDArray array2, double eps = 1e-5)
{ {
var array1 = np.ones_like(array2) * value; var array1 = np.ones_like(array2) * value;
Assert.IsTrue(np.allclose(array1, array2, rtol: eps));
Assert.IsTrue(np.allclose(new NDArray(array1), array2, rtol: eps));
} }


public void assertProtoEquals(object toProto, object o) public void assertProtoEquals(object toProto, object o)


Loading…
Cancel
Save