diff --git a/README.md b/README.md
index 8130fbd7..15f72bf5 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@
[](https://996.icu/#/en_US)
[](https://mybinder.org/v2/gh/javiercp/BinderTF.NET/master?urlpath=lab)
-*master branch is based on tensorflow 2.1 now, v0.15-tensorflow1.15 is from tensorflow1.15.*
+*master branch is based on tensorflow 2.2 now, v0.15-tensorflow1.15 is from tensorflow1.15.*
TF.NET is a member project of [SciSharp STACK](https://github.com/SciSharp).
@@ -28,7 +28,7 @@ In comparison to other projects, like for instance TensorFlowSharp which only pr
### How to use
-| TensorFlow | tf 1.13 | tf 1.14 | tf 1.15 | tf 2.0 |
+| TensorFlow | tf 1.13 | tf 1.14 | tf 1.15 | tf 2.2 |
| ----------- | ------- | ------- | ------- | ------ |
| tf.net 0.20 | | | x | x |
| tf.net 0.15 | | x | x | |
diff --git a/docs/assets/tf2.jpg b/docs/assets/tf2.jpg
new file mode 100644
index 00000000..c4ebd31e
Binary files /dev/null and b/docs/assets/tf2.jpg differ
diff --git a/docs/assets/tf2.psd b/docs/assets/tf2.psd
new file mode 100644
index 00000000..1cde3023
Binary files /dev/null and b/docs/assets/tf2.psd differ
diff --git a/src/TensorFlowNET.Core/Eager/EagerTensor.cs b/src/TensorFlowNET.Core/Eager/EagerTensor.cs
index 85cc731e..d7474e7d 100644
--- a/src/TensorFlowNET.Core/Eager/EagerTensor.cs
+++ b/src/TensorFlowNET.Core/Eager/EagerTensor.cs
@@ -13,31 +13,37 @@ namespace Tensorflow.Eager
{
tfe_tensor_handle = handle;
_handle = c_api.TFE_TensorHandleResolve(handle, status);
+ _id = ops.uid();
}
public EagerTensor(string value, string device_name) : base(value)
{
tfe_tensor_handle = c_api.TFE_NewTensorHandle(_handle, status);
+ _id = ops.uid();
}
public EagerTensor(int value, string device_name) : base(value)
{
tfe_tensor_handle = c_api.TFE_NewTensorHandle(_handle, status);
+ _id = ops.uid();
}
public EagerTensor(float[] value, string device_name) : base(value)
{
tfe_tensor_handle = c_api.TFE_NewTensorHandle(_handle, status);
+ _id = ops.uid();
}
public EagerTensor(double[] value, string device_name) : base(value)
{
tfe_tensor_handle = c_api.TFE_NewTensorHandle(_handle, status);
+ _id = ops.uid();
}
public EagerTensor(NDArray value, string device_name) : base(value)
{
tfe_tensor_handle = c_api.TFE_NewTensorHandle(_handle, status);
+ _id = ops.uid();
}
public override string ToString()
diff --git a/src/TensorFlowNET.Core/Eager/c_api.eager.cs b/src/TensorFlowNET.Core/Eager/c_api.eager.cs
index bb75f153..4d9c2f32 100644
--- a/src/TensorFlowNET.Core/Eager/c_api.eager.cs
+++ b/src/TensorFlowNET.Core/Eager/c_api.eager.cs
@@ -102,14 +102,20 @@ namespace Tensorflow
public static extern TFE_Op TFE_NewOp(IntPtr ctx, string op_or_function_name, IntPtr status);
///
- ///
+ /// Resets `op_to_reset` with `op_or_function_name` and `raw_device_name`. This
+ /// is for performance optimization by reusing an exiting unused op rather than
+ /// creating a new op every time. If `raw_device_name` is `NULL` or empty, it
+ /// does not set the device name. If it's not `NULL`, then it attempts to parse
+ /// and set the device name. It's effectively `TFE_OpSetDevice`, but it is faster
+ /// than separately calling it because if the existing op has the same
+ /// `raw_device_name`, it skips parsing and just leave as it is.
///
- /// TFE_Context*
+ /// TFE_Op*
/// const char*
+ /// const char*
/// TF_Status*
- /// TFE_Op*
[DllImport(TensorFlowLibName)]
- public static extern void TFE_OpReset(IntPtr ctx, string op_or_function_name, IntPtr status, IntPtr op_to_reset);
+ public static extern void TFE_OpReset(IntPtr op_to_reset, string op_or_function_name, string raw_device_name, IntPtr status);
///
///
@@ -304,5 +310,17 @@ namespace Tensorflow
/// TFE_Executor*
[DllImport(TensorFlowLibName)]
public static extern TFE_Executor TFE_ContextGetExecutorForThread(IntPtr ctx);
+
+ [DllImport(TensorFlowLibName)]
+ public static extern void TFE_Test();
+
+ [DllImport(TensorFlowLibName)]
+ public static extern IntPtr TFE_TapeSetNew(bool persistent, bool watch_accessed_variables);
+
+ [DllImport(TensorFlowLibName)]
+ public static extern void TFE_TapeWatch(IntPtr tape, IntPtr tensor, int tensor_id);
+
+ [DllImport(TensorFlowLibName)]
+ public static extern void TFE_TapeGradient(IntPtr tape, long[] targetTensorIds, IntPtr[] target, long[] sourcesTensorIds, IntPtr status);
}
}
diff --git a/src/TensorFlowNET.Core/Eager/wrap_tfe_src..cs b/src/TensorFlowNET.Core/Eager/wrap_tfe_src..cs
new file mode 100644
index 00000000..fd5810ee
--- /dev/null
+++ b/src/TensorFlowNET.Core/Eager/wrap_tfe_src..cs
@@ -0,0 +1,15 @@
+using System.Collections.Generic;
+using System.Linq;
+using System;
+using static Tensorflow.OpDef.Types;
+
+namespace Tensorflow.Eager
+{
+ ///
+ /// python\eager\pywrap_tfe_src.cc
+ ///
+ public partial class wrap_tfe_src
+ {
+
+ }
+}
diff --git a/src/TensorFlowNET.Core/Eager/wrap_tfe_src.TFE_FastPathExecute.cs b/src/TensorFlowNET.Core/Eager/wrap_tfe_src.TFE_FastPathExecute.cs
index 01302805..b9aaeab2 100644
--- a/src/TensorFlowNET.Core/Eager/wrap_tfe_src.TFE_FastPathExecute.cs
+++ b/src/TensorFlowNET.Core/Eager/wrap_tfe_src.TFE_FastPathExecute.cs
@@ -110,7 +110,7 @@ namespace Tensorflow.Eager
var maybe_op = ReleaseThreadLocalOp();
if (maybe_op != IntPtr.Zero)
{
- c_api.TFE_OpReset(ctx, op_or_function_name, status, maybe_op);
+ c_api.TFE_OpReset(maybe_op, op_or_function_name, ctx.device_name, status);
}
else
{
diff --git a/src/TensorFlowNET.Core/Gradients/GradientActor.cs b/src/TensorFlowNET.Core/Gradients/GradientActor.cs
index 7bc8ccde..f650aa9e 100644
--- a/src/TensorFlowNET.Core/Gradients/GradientActor.cs
+++ b/src/TensorFlowNET.Core/Gradients/GradientActor.cs
@@ -23,7 +23,6 @@ namespace Tensorflow.Gradients
bool _watch_accessed_variables;
bool _created_eagerly;
Tape _tape;
- int tape_nesting_id_counter = 0;
public GradientActor(bool persistent = false,
bool watch_accessed_variables = true)
@@ -41,18 +40,28 @@ namespace Tensorflow.Gradients
"re-enter an already-active tape.");
if (_tape == null)
- {
- _tape = new Tape();
- _tape.tape = new GradientTape(_persistent, _watch_accessed_variables);
- _tape.nesting_id = tape_nesting_id_counter++;
- }
+ _tape = new Tape(_persistent, _watch_accessed_variables);
+ else
+ throw new NotImplementedException("");
_recording = true;
}
+ ///
+ /// Marks this tensor to be watched by the given tape.
+ ///
+ ///
public void watch(Tensor x)
{
+ _tape.watch(x);
+ }
+ public Tensor gradient(Tensor target, Tensor sources)
+ {
+ c_api.TFE_Test();
+ //using (var status = new Status())
+ //c_api.TFE_TapeGradient(_tape, new long[] { target.Id }, status);
+ return null;
}
public void Dispose()
diff --git a/src/TensorFlowNET.Core/Gradients/Tape.cs b/src/TensorFlowNET.Core/Gradients/Tape.cs
index 852bdf28..a61898fe 100644
--- a/src/TensorFlowNET.Core/Gradients/Tape.cs
+++ b/src/TensorFlowNET.Core/Gradients/Tape.cs
@@ -4,11 +4,21 @@ using System.Text;
namespace Tensorflow.Gradients
{
- public class Tape
+ public class Tape : DisposableObject
{
public GradientTape tape { get; set; }
public int nesting_id { get; set; }
+ public Tape(bool persistent, bool watch_accessed_variables)
+ {
+ _handle = c_api.TFE_TapeSetNew(persistent, watch_accessed_variables);
+ }
+
+ public void watch(Tensor x)
+ {
+ c_api.TFE_TapeWatch(_handle, x, x.Id);
+ }
+
public static bool IsDtypeTrainable(DataType dtype)
{
switch (dtype)
@@ -26,5 +36,12 @@ namespace Tensorflow.Gradients
return false;
}
}
+
+ protected override void DisposeUnmanagedResources(IntPtr handle)
+ {
+ }
+
+ public static implicit operator IntPtr(Tape tape)
+ => tape._handle;
}
}
diff --git a/src/TensorFlowNET.Core/Tensors/Tensor.cs b/src/TensorFlowNET.Core/Tensors/Tensor.cs
index 24af4ec9..c9703699 100644
--- a/src/TensorFlowNET.Core/Tensors/Tensor.cs
+++ b/src/TensorFlowNET.Core/Tensors/Tensor.cs
@@ -39,7 +39,7 @@ namespace Tensorflow
IPackable,
ICanBeFlattened
{
- private readonly int _id;
+ protected int _id;
private readonly Operation _op;
private readonly int _value_index;
private TF_Output? _tf_output;
diff --git a/src/TensorFlowNET.Core/Variables/ResourceVariable.Operators.cs b/src/TensorFlowNET.Core/Variables/ResourceVariable.Operators.cs
index eddb97ea..d6eafbc1 100644
--- a/src/TensorFlowNET.Core/Variables/ResourceVariable.Operators.cs
+++ b/src/TensorFlowNET.Core/Variables/ResourceVariable.Operators.cs
@@ -30,6 +30,8 @@ namespace Tensorflow
public static Tensor operator -(ResourceVariable x, double y) => op_helper("sub", x, y);
public static Tensor operator -(ResourceVariable x, Tensor y) => op_helper("sub", x, y);
+ public static Tensor operator *(ResourceVariable x, ResourceVariable y) => gen_math_ops.mul(x, y);
+
public static Tensor operator <(ResourceVariable x, Tensor y) => gen_math_ops.less(x.value(), y);
public static Tensor operator >(ResourceVariable x, Tensor y) => gen_math_ops.greater(x.value(), y);
diff --git a/tensorflowlib/README.md b/tensorflowlib/README.md
index fdc6953f..33f36a22 100644
--- a/tensorflowlib/README.md
+++ b/tensorflowlib/README.md
@@ -44,7 +44,9 @@ We can't found official prebuild binaries for each platform since tensorflow 2.0
https://www.tensorflow.org/install/source_windows
-Download [Bazel 0.29.1](https://github.com/bazelbuild/bazel/releases/tag/0.29.1) to build tensorflow2.x. We build customized binary to export c_api from this [fork](https://github.com/SciSharp/tensorflow).
+Download [Bazel 2.0.0](https://github.com/bazelbuild/bazel/releases/tag/2.0.0) to build tensorflow2.x. We build customized binary to export c_api from this [fork](https://github.com/SciSharp/tensorflow).
+
+Set ENV `BAZEL_VC=C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC`.
`pacman -S git patch unzip`
diff --git a/test/TensorFlowNET.UnitTest/Tensorflow.UnitTest.csproj b/test/TensorFlowNET.UnitTest/Tensorflow.UnitTest.csproj
index d269bcdc..0211b584 100644
--- a/test/TensorFlowNET.UnitTest/Tensorflow.UnitTest.csproj
+++ b/test/TensorFlowNET.UnitTest/Tensorflow.UnitTest.csproj
@@ -29,7 +29,7 @@
-
+