diff --git a/src/TensorFlowNET.Core/APIs/tf.math.cs b/src/TensorFlowNET.Core/APIs/tf.math.cs
index 24131a2d..8c6248e3 100644
--- a/src/TensorFlowNET.Core/APIs/tf.math.cs
+++ b/src/TensorFlowNET.Core/APIs/tf.math.cs
@@ -448,6 +448,17 @@ namespace Tensorflow
public Tensor reduce_prod(Tensor input_tensor, int[] axis = null, bool keepdims = false, string name = null)
=> math_ops.reduce_prod(input_tensor, axis: axis, keepdims: keepdims, name: name);
+ ///
+ /// Computes the sum of elements across dimensions of a tensor.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public Tensor reduce_sum(Tensor[] input_tensors, int? axis = null, bool keepdims = false, string name = null)
+ => math_ops.reduce_sum(input_tensors, axis: axis, keepdims: keepdims, name: name);
+
///
/// Computes the sum of elements across dimensions of a tensor.
///
diff --git a/src/TensorFlowNET.Core/Eager/Context.cs b/src/TensorFlowNET.Core/Eager/Context.cs
index b2909327..7f428229 100644
--- a/src/TensorFlowNET.Core/Eager/Context.cs
+++ b/src/TensorFlowNET.Core/Eager/Context.cs
@@ -9,6 +9,7 @@ namespace Tensorflow.Eager
public int default_execution_mode;
public string device_name = "";
+ bool _initialized = false;
public Context(ContextOptions opts, Status status)
{
@@ -16,6 +17,13 @@ namespace Tensorflow.Eager
status.Check(true);
}
+ public void ensure_initialized()
+ {
+ if (_initialized)
+ return;
+ _initialized = true;
+ }
+
///
/// Dispose any unmanaged resources related to given .
///
@@ -27,5 +35,8 @@ namespace Tensorflow.Eager
public static implicit operator IntPtr(Context ctx)
=> ctx._handle;
+
+ public static implicit operator TFE_Context(Context ctx)
+ => new TFE_Context(ctx._handle);
}
}
diff --git a/src/TensorFlowNET.Core/Eager/ContextOptions.cs b/src/TensorFlowNET.Core/Eager/ContextOptions.cs
index 12c4cdfc..8659b6ce 100644
--- a/src/TensorFlowNET.Core/Eager/ContextOptions.cs
+++ b/src/TensorFlowNET.Core/Eager/ContextOptions.cs
@@ -17,6 +17,10 @@ namespace Tensorflow.Eager
public static implicit operator IntPtr(ContextOptions opts)
=> opts._handle;
+
+ public static implicit operator TFE_ContextOptions(ContextOptions opts)
+ => new TFE_ContextOptions(opts._handle);
+
}
}
diff --git a/src/TensorFlowNET.Core/Eager/Execute.cs b/src/TensorFlowNET.Core/Eager/Execute.cs
index e5a2db2f..aece7aab 100644
--- a/src/TensorFlowNET.Core/Eager/Execute.cs
+++ b/src/TensorFlowNET.Core/Eager/Execute.cs
@@ -1,12 +1,67 @@
using System.Collections.Generic;
+using System;
+using System.Linq;
namespace Tensorflow.Eager
{
public class Execute
{
+ ///
+ /// Execute a TensorFlow operation.
+ ///
+ ///
+ /// Name of the TensorFlow operation (see REGISTER_OP in C++ code) to
+ /// execute.
+ ///
+ ///
+ /// The number of outputs of the operation to fetch.
+ ///
+ ///
+ /// A list of inputs to the operation. Each entry should be a Tensor, or
+ /// a value which can be passed to the Tensor constructor to create one.
+ ///
+ ///
+ /// A tuple with alternating string attr names and attr values for this
+ /// operation.
+ ///
+ /// The value of context.context().
+ /// Customized name for the operation.
+ /// List of output Tensor objects. The list is empty if there are no outputs
+ public Tensor execute(Context ctx, string op_name, Tensor[] inputs, object[] attrs, string name = null)
+ {
+ ctx.ensure_initialized();
+ using (var status = new Status())
+ {
+ var retVals = wrap_tfe_src.TFE_Py_Execute(ctx, ctx.device_name, op_name, inputs, attrs, 1, status);
+
+ var t = c_api.TFE_TensorHandleResolve(retVals[0], status);
+ status.Check(true);
+
+ return new EagerTensor(t);
+ }
+ }
+
+ public (TF_DataType, Tensor) args_to_matching_eager(Tensor[] l, Context ctx, TF_DataType default_dtype = TF_DataType.DtInvalid)
+ {
+ var dtype = default_dtype;
+ if(dtype == TF_DataType.DtInvalid)
+ {
+ var tensor = ops.convert_to_tensor(l, dtype, preferred_dtype: default_dtype, ctx: ctx);
+
+ if (dtype == TF_DataType.DtInvalid)
+ dtype = tensor.dtype;
+
+ return (dtype, tensor);
+ }
+ else
+ {
+ return (dtype, l[0]);
+ }
+ }
+
public void record_gradient(string op_name, InputList inputs, Dictionary attrs, Tensor[] results, string name = null)
{
- pywrap_tfe_src.RecordGradient(op_name, inputs._inputs, attrs, results, name);
+ wrap_tfe_src.RecordGradient(op_name, inputs._inputs, attrs, results, name);
}
}
}
diff --git a/src/TensorFlowNET.Core/Eager/TFE_Context.cs b/src/TensorFlowNET.Core/Eager/TFE_Context.cs
new file mode 100644
index 00000000..dc16909d
--- /dev/null
+++ b/src/TensorFlowNET.Core/Eager/TFE_Context.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Tensorflow.Eager
+{
+ public struct TFE_Context
+ {
+ IntPtr _handle;
+
+ public TFE_Context(IntPtr handle)
+ => _handle = handle;
+
+ public static implicit operator TFE_Context(IntPtr handle)
+ => new TFE_Context(handle);
+
+ public static implicit operator IntPtr(TFE_Context tensor)
+ => tensor._handle;
+
+ public override string ToString()
+ => $"TFE_Context {_handle}";
+ }
+}
diff --git a/src/TensorFlowNET.Core/Eager/TFE_ContextOptions.cs b/src/TensorFlowNET.Core/Eager/TFE_ContextOptions.cs
new file mode 100644
index 00000000..f43d97f8
--- /dev/null
+++ b/src/TensorFlowNET.Core/Eager/TFE_ContextOptions.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Tensorflow.Eager
+{
+ public struct TFE_ContextOptions
+ {
+ IntPtr _handle;
+
+ public TFE_ContextOptions(IntPtr handle)
+ => _handle = handle;
+
+ public static implicit operator TFE_ContextOptions(IntPtr handle)
+ => new TFE_ContextOptions(handle);
+
+ public static implicit operator IntPtr(TFE_ContextOptions tensor)
+ => tensor._handle;
+
+ public override string ToString()
+ => $"TFE_ContextOptions {_handle}";
+ }
+}
diff --git a/src/TensorFlowNET.Core/Eager/TFE_Executor.cs b/src/TensorFlowNET.Core/Eager/TFE_Executor.cs
new file mode 100644
index 00000000..ed88dd30
--- /dev/null
+++ b/src/TensorFlowNET.Core/Eager/TFE_Executor.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Tensorflow.Eager
+{
+ public struct TFE_Executor
+ {
+ IntPtr _handle;
+
+ public TFE_Executor(IntPtr handle)
+ => _handle = handle;
+
+ public static implicit operator TFE_Executor(IntPtr handle)
+ => new TFE_Executor(handle);
+
+ public static implicit operator IntPtr(TFE_Executor tensor)
+ => tensor._handle;
+
+ public override string ToString()
+ => $"TFE_Executor {_handle}";
+ }
+}
diff --git a/src/TensorFlowNET.Core/Eager/TFE_Op.cs b/src/TensorFlowNET.Core/Eager/TFE_Op.cs
new file mode 100644
index 00000000..538ada78
--- /dev/null
+++ b/src/TensorFlowNET.Core/Eager/TFE_Op.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Tensorflow.Eager
+{
+ public struct TFE_Op
+ {
+ IntPtr _handle;
+
+ public TFE_Op(IntPtr handle)
+ => _handle = handle;
+
+ public static implicit operator TFE_Op(IntPtr handle)
+ => new TFE_Op(handle);
+
+ public static implicit operator IntPtr(TFE_Op tensor)
+ => tensor._handle;
+
+ public override string ToString()
+ => $"TFE_Op {_handle}";
+ }
+}
diff --git a/src/TensorFlowNET.Core/Eager/TFE_TensorHandle.cs b/src/TensorFlowNET.Core/Eager/TFE_TensorHandle.cs
new file mode 100644
index 00000000..a0c59259
--- /dev/null
+++ b/src/TensorFlowNET.Core/Eager/TFE_TensorHandle.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Tensorflow.Eager
+{
+ public struct TFE_TensorHandle
+ {
+ IntPtr _handle;
+
+ public TFE_TensorHandle(IntPtr handle)
+ => _handle = handle;
+
+ public static implicit operator TFE_TensorHandle(IntPtr handle)
+ => new TFE_TensorHandle(handle);
+
+ public static implicit operator IntPtr(TFE_TensorHandle tensor)
+ => tensor._handle;
+
+ public override string ToString()
+ => $"TFE_TensorHandle {_handle}";
+ }
+}
diff --git a/src/TensorFlowNET.Core/Eager/c_api.eager.cs b/src/TensorFlowNET.Core/Eager/c_api.eager.cs
index 2cd3a68c..a241ee0f 100644
--- a/src/TensorFlowNET.Core/Eager/c_api.eager.cs
+++ b/src/TensorFlowNET.Core/Eager/c_api.eager.cs
@@ -1,5 +1,6 @@
using System;
using System.Runtime.InteropServices;
+using Tensorflow.Eager;
using TFE_Executor = System.IntPtr;
namespace Tensorflow
@@ -11,7 +12,7 @@ namespace Tensorflow
///
/// TFE_ContextOptions*
[DllImport(TensorFlowLibName)]
- public static extern IntPtr TFE_NewContextOptions();
+ public static extern TFE_ContextOptions TFE_NewContextOptions();
///
/// Destroy an options object.
@@ -70,7 +71,7 @@ namespace Tensorflow
/// TF_Status*
/// TFE_Context*
[DllImport(TensorFlowLibName)]
- public static extern IntPtr TFE_NewContext(IntPtr opts, IntPtr status);
+ public static extern TFE_Context TFE_NewContext(IntPtr opts, IntPtr status);
///
///
@@ -88,7 +89,7 @@ namespace Tensorflow
/// int*
/// TF_Status*
[DllImport(TensorFlowLibName)]
- public static extern void TFE_Execute(IntPtr op, IntPtr[] retvals, ref int num_retvals, IntPtr status);
+ public static extern void TFE_Execute(TFE_Op op, IntPtr[] retvals, ref int num_retvals, IntPtr status);
///
///
@@ -98,7 +99,7 @@ namespace Tensorflow
/// TF_Status*
///
[DllImport(TensorFlowLibName)]
- public static extern IntPtr TFE_NewOp(IntPtr ctx, string op_or_function_name, IntPtr status);
+ public static extern TFE_Op TFE_NewOp(IntPtr ctx, string op_or_function_name, IntPtr status);
///
///
@@ -150,7 +151,7 @@ namespace Tensorflow
///
///
[DllImport(TensorFlowLibName)]
- public static extern void TFE_OpSetDevice(IntPtr op, string device_name, IntPtr status);
+ public static extern void TFE_OpSetDevice(TFE_Op op, string device_name, IntPtr status);
///
///
@@ -167,7 +168,7 @@ namespace Tensorflow
/// const tensorflow::Tensor&
/// TFE_TensorHandle*
[DllImport(TensorFlowLibName)]
- public static extern IntPtr TFE_NewTensorHandle(IntPtr t, IntPtr status);
+ public static extern TFE_TensorHandle TFE_NewTensorHandle(IntPtr t, IntPtr status);
///
/// Sets the default execution mode (sync/async). Note that this can be
@@ -195,7 +196,7 @@ namespace Tensorflow
/// TF_Status*
///
[DllImport(TensorFlowLibName)]
- public static extern IntPtr TFE_TensorHandleResolve(IntPtr h, IntPtr status);
+ public static extern TF_Tensor TFE_TensorHandleResolve(IntPtr h, IntPtr status);
///
/// This function will block till the operation that produces `h` has completed.
@@ -252,7 +253,7 @@ namespace Tensorflow
///
/// TFE_Executor*
[DllImport(TensorFlowLibName)]
- public static extern IntPtr TFE_NewExecutor(bool is_async);
+ public static extern TFE_Executor TFE_NewExecutor(bool is_async);
///
/// Deletes the eager Executor without waiting for enqueued nodes. Please call
diff --git a/src/TensorFlowNET.Core/Eager/wrap_tfe_src.RecordGradient.cs b/src/TensorFlowNET.Core/Eager/wrap_tfe_src.RecordGradient.cs
new file mode 100644
index 00000000..88e8ef88
--- /dev/null
+++ b/src/TensorFlowNET.Core/Eager/wrap_tfe_src.RecordGradient.cs
@@ -0,0 +1,33 @@
+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
+ {
+ public static void RecordGradient(string op_name, Tensor[] inputs, Dictionary attrs, Tensor[] results, string name = null)
+ {
+ var input_ids = inputs.Select(x => x.Id).ToArray();
+ var input_dtypes = inputs.Select(x => x.dtype).ToArray();
+
+ bool should_record = false;
+ foreach (var input_dtype in input_dtypes)
+ {
+ if (Tape.IsDtypeTrainable(input_dtype.as_datatype_enum()))
+ {
+ should_record = true;
+ break;
+ }
+ }
+ if (!should_record) return;
+
+ var op_outputs = results;
+ var op_inputs = inputs;
+ }
+ }
+}
diff --git a/src/TensorFlowNET.Core/Eager/wrap_tfe_src.TFE_Execute.cs b/src/TensorFlowNET.Core/Eager/wrap_tfe_src.TFE_Execute.cs
new file mode 100644
index 00000000..0271250e
--- /dev/null
+++ b/src/TensorFlowNET.Core/Eager/wrap_tfe_src.TFE_Execute.cs
@@ -0,0 +1,53 @@
+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
+ {
+ public static IntPtr[] TFE_Py_Execute(Context ctx,
+ string device_name,
+ string op_name,
+ Tensor[] inputs,
+ object[] attrs,
+ int num_outputs,
+ Status status)
+ => TFE_Py_ExecuteCancelable(ctx, device_name, op_name, inputs, attrs, num_outputs, status);
+
+ public static IntPtr[] TFE_Py_ExecuteCancelable(Context ctx,
+ string device_name,
+ string op_name,
+ Tensor[] inputs,
+ object[] attrs,
+ int num_outputs,
+ Status status)
+ {
+ var op = c_api.TFE_NewOp(ctx, op_name, status);
+ status.Check(true);
+ c_api.TFE_OpSetDevice(op, device_name, status);
+ if(status.ok())
+ {
+ for (int i = 0; i < inputs.Length; ++i)
+ {
+ var tensor_handle = c_api.TFE_NewTensorHandle(inputs[i], status);
+ c_api.TFE_OpAddInput(op, tensor_handle, status);
+ }
+ }
+ if (status.ok())
+ SetOpAttrs(ctx, op, attrs, 0, status);
+
+ var outputs = new IntPtr[num_outputs];
+ if (status.ok())
+ {
+ c_api.TFE_Execute(op, outputs, ref num_outputs, status);
+ status.Check(true);
+ }
+ return outputs;
+ }
+ }
+}
diff --git a/src/TensorFlowNET.Core/Eager/pywrap_tfe_src.cs b/src/TensorFlowNET.Core/Eager/wrap_tfe_src.TFE_FastPathExecute.cs
similarity index 85%
rename from src/TensorFlowNET.Core/Eager/pywrap_tfe_src.cs
rename to src/TensorFlowNET.Core/Eager/wrap_tfe_src.TFE_FastPathExecute.cs
index 792e945d..25ed69f5 100644
--- a/src/TensorFlowNET.Core/Eager/pywrap_tfe_src.cs
+++ b/src/TensorFlowNET.Core/Eager/wrap_tfe_src.TFE_FastPathExecute.cs
@@ -8,7 +8,7 @@ namespace Tensorflow.Eager
///
/// python\eager\pywrap_tfe_src.cc
///
- public class pywrap_tfe_src
+ public partial class wrap_tfe_src
{
static int kFastPathExecuteInputStartIndex = 0;
public static EagerTensor TFE_Py_FastPathExecute(Context ctx,
@@ -19,11 +19,10 @@ namespace Tensorflow.Eager
params object[] args)
{
int args_size = args.Length;
- IntPtr op = IntPtr.Zero;
var attr_list_sizes = new Dictionary();
using (var status = new Status())
{
- op = c_api.TFE_NewOp(ctx, opName, status);
+ var op = c_api.TFE_NewOp(ctx, opName, status);
var op_def = Graph.TFE_GetOpDef(opName);
@@ -52,9 +51,9 @@ namespace Tensorflow.Eager
for (int i = 0; i < op_def.InputArg.Count; i++)
{
var input_arg = op_def.InputArg[i];
- int len = (args[kFastPathExecuteInputStartIndex + i] as object[]).Length;
if (!string.IsNullOrEmpty(input_arg.NumberAttr))
{
+ int len = (args[kFastPathExecuteInputStartIndex + i] as object[]).Length;
c_api.TFE_OpSetAttrInt(op, input_arg.NumberAttr, len);
attr_list_sizes[input_arg.NumberAttr] = len;
@@ -125,13 +124,16 @@ namespace Tensorflow.Eager
IntPtr op,
Status status)
{
- IntPtr input_handle = IntPtr.Zero;
+ TFE_TensorHandle input_handle;
switch (inputs)
{
case Tensor input:
input_handle = c_api.TFE_NewTensorHandle(input, status);
break;
+ case Tensor[] input_list:
+ input_handle = c_api.TFE_NewTensorHandle(input_list[0], status);
+ break;
default:
throw new NotImplementedException("");
}
@@ -148,6 +150,25 @@ namespace Tensorflow.Eager
return true;
}
+ private static void SetOpAttrs(Context ctx, TFE_Op op, object[] attrs, int start_index, Status out_status)
+ {
+ var len = attrs.Length;
+ for (int i = 0; i < len; i += 2)
+ {
+ var key = attrs[start_index + i].ToString();
+ var value = attrs[start_index + i + 1];
+
+ byte is_list = 0;
+ var type = c_api.TFE_OpGetAttrType(op, key, ref is_list, out_status);
+ if (!out_status.ok()) return;
+ if (is_list != 0)
+ SetOpAttrList(ctx, op, key, value, type, null, out_status);
+ else
+ SetOpAttrScalar(ctx, op, key, value, type, null, out_status);
+ out_status.Check(true);
+ }
+ }
+
///
/// This function will set the op attrs required. If an attr has the value of
/// None, then it will read the AttrDef to get the default value and set that
@@ -188,6 +209,14 @@ namespace Tensorflow.Eager
}
}
+ private static bool SetOpAttrList(Context ctx, IntPtr op,
+ string key, object value, TF_AttrType type,
+ Dictionary attr_list_sizes,
+ Status status)
+ {
+ return false;
+ }
+
private static bool SetOpAttrScalar(Context ctx, IntPtr op,
string key, object value, TF_AttrType type,
Dictionary attr_list_sizes,
@@ -213,25 +242,5 @@ namespace Tensorflow.Eager
return true;
}
-
- public static void RecordGradient(string op_name, Tensor[] inputs, Dictionary attrs, Tensor[] results, string name = null)
- {
- var input_ids = inputs.Select(x => x.Id).ToArray();
- var input_dtypes = inputs.Select(x => x.dtype).ToArray();
-
- bool should_record = false;
- foreach (var input_dtype in input_dtypes)
- {
- if (Tape.IsDtypeTrainable(input_dtype.as_datatype_enum()))
- {
- should_record = true;
- break;
- }
- }
- if (!should_record) return;
-
- var op_outputs = results;
- var op_inputs = inputs;
- }
}
}
diff --git a/src/TensorFlowNET.Core/Operations/gen_array_ops.cs b/src/TensorFlowNET.Core/Operations/gen_array_ops.cs
index ad7013dd..eea1f1a1 100644
--- a/src/TensorFlowNET.Core/Operations/gen_array_ops.cs
+++ b/src/TensorFlowNET.Core/Operations/gen_array_ops.cs
@@ -125,7 +125,7 @@ namespace Tensorflow
{
if(tf.context.executing_eagerly())
{
- var _result = pywrap_tfe_src.TFE_Py_FastPathExecute(tf.context, tf.context.device_name, "Pack", name, null, values, "axis", axis);
+ var _result = wrap_tfe_src.TFE_Py_FastPathExecute(tf.context, tf.context.device_name, "Pack", name, null, values, "axis", axis);
return _result;
}
diff --git a/src/TensorFlowNET.Core/Operations/gen_math_ops.cs b/src/TensorFlowNET.Core/Operations/gen_math_ops.cs
index b08e4f0c..aa0a6785 100644
--- a/src/TensorFlowNET.Core/Operations/gen_math_ops.cs
+++ b/src/TensorFlowNET.Core/Operations/gen_math_ops.cs
@@ -14,6 +14,7 @@
limitations under the License.
******************************************************************************/
+using System;
using Tensorflow.Eager;
using static Tensorflow.Binding;
@@ -22,6 +23,7 @@ namespace Tensorflow
public static class gen_math_ops
{
public static OpDefLibrary _op_def_lib = new OpDefLibrary();
+ public static Execute _execute = new Execute();
public static Tensor _all(Tensor input, Tensor axis, bool keep_dims = false, string name = null)
{
@@ -114,11 +116,36 @@ namespace Tensorflow
/// A `Tensor`. Has the same type as `input`.
public static Tensor mean(T1 input, T2 axis, bool keep_dims= false, string name = null)
{
+ if (tf.context.executing_eagerly())
+ {
+ try
+ {
+ var _result = wrap_tfe_src.TFE_Py_FastPathExecute(tf.context, tf.context.device_name, "Mean", name, null, input, axis, "keep_dims", keep_dims);
+ return _result;
+ }
+ catch (Exception ex)
+ {
+ return mean_eager_fallback(input as Tensor[], axis as Tensor, keep_dims: keep_dims, name: name, ctx: tf.context);
+ }
+ }
+
var _op = _op_def_lib._apply_op_helper("Mean", name, args: new { input, reduction_indices = axis, keep_dims = keep_dims });
return _op.output;
}
+ private static Tensor mean_eager_fallback(Tensor[] inputs, Tensor axis, bool keep_dims = false, string name = null, Context ctx = null)
+ {
+ var (_attr_T, input) = _execute.args_to_matching_eager(inputs, ctx);
+ var (_attr_Tidx, axis1) = _execute.args_to_matching_eager(new[] { axis }, ctx, TF_DataType.TF_INT32);
+ var _inputs_flat = new Tensor[] { input, axis1 };
+
+ var _attrs = new object[] { "keep_dims", keep_dims, "T", _attr_T, "Tidx", _attr_Tidx };
+
+ var _result = _execute.execute(ctx, "Mean", _inputs_flat, _attrs, name: name);
+ return _result;
+ }
+
public static Tensor prod(T1 input, T2 axis, bool keep_dims = false, string name = null)
{
var _op = _op_def_lib._apply_op_helper("Prod", name, args: new { input, reduction_indices = axis, keep_dims });
@@ -144,7 +171,7 @@ namespace Tensorflow
{
if (tf.context.executing_eagerly())
{
- var _result = pywrap_tfe_src.TFE_Py_FastPathExecute(tf.context, "", "Add", name, null, x, y);
+ var _result = wrap_tfe_src.TFE_Py_FastPathExecute(tf.context, "", "Add", name, null, x, y);
return _result;
}
@@ -466,7 +493,7 @@ namespace Tensorflow
{
if (tf.context.executing_eagerly())
{
- var _result = pywrap_tfe_src.TFE_Py_FastPathExecute(tf.context, "", "Cast", name, null, x, "DstT", DstT, "Truncate", Truncate);
+ var _result = wrap_tfe_src.TFE_Py_FastPathExecute(tf.context, "", "Cast", name, null, x, "DstT", DstT, "Truncate", Truncate);
return _result;
}
@@ -493,7 +520,7 @@ namespace Tensorflow
{
if (tf.context.executing_eagerly())
{
- var _result = pywrap_tfe_src.TFE_Py_FastPathExecute(tf.context, "", "Sub", name, null, x, y);
+ var _result = wrap_tfe_src.TFE_Py_FastPathExecute(tf.context, "", "Sub", name, null, x, y);
return _result;
}
@@ -544,7 +571,7 @@ namespace Tensorflow
{
if (tf.context.executing_eagerly())
{
- var _result = pywrap_tfe_src.TFE_Py_FastPathExecute(tf.context, "", "Mul", name, null, x, y);
+ var _result = wrap_tfe_src.TFE_Py_FastPathExecute(tf.context, "", "Mul", name, null, x, y);
return _result;
}
@@ -564,7 +591,7 @@ namespace Tensorflow
{
if (tf.context.executing_eagerly())
{
- var _result = pywrap_tfe_src.TFE_Py_FastPathExecute(tf.context, "", "RealDiv", name, null, x, y);
+ var _result = wrap_tfe_src.TFE_Py_FastPathExecute(tf.context, "", "RealDiv", name, null, x, y);
return _result;
}
@@ -591,7 +618,7 @@ namespace Tensorflow
{
if (tf.context.executing_eagerly())
{
- var _result = pywrap_tfe_src.TFE_Py_FastPathExecute(tf.context, "", "FloorDiv", name, null, x, y);
+ var _result = wrap_tfe_src.TFE_Py_FastPathExecute(tf.context, "", "FloorDiv", name, null, x, y);
return _result;
}
@@ -709,6 +736,14 @@ namespace Tensorflow
public static Tensor _sum(Tx input, Ty axis = default, bool keep_dims = false, string name = null)
{
+ if (tf.context.executing_eagerly())
+ {
+ var _result = wrap_tfe_src.TFE_Py_FastPathExecute(tf.context, tf.context.device_name,
+ "Sum", name, null,
+ input, axis, "keep_dims", keep_dims);
+ return _result;
+ }
+
var _op = _op_def_lib._apply_op_helper("Sum", name, args: new { input, reduction_indices = axis, keep_dims });
return _op.outputs[0];
@@ -724,6 +759,12 @@ namespace Tensorflow
///
public static Tensor range(Tensor start, Tensor limit, Tensor delta, string name = null)
{
+ if (tf.context.executing_eagerly())
+ {
+ var _result = wrap_tfe_src.TFE_Py_FastPathExecute(tf.context, tf.context.device_name, "Range", name, null, start, limit, delta);
+ return _result;
+ }
+
var _op = _op_def_lib._apply_op_helper("Range", name, new { start, limit, delta });
return _op.outputs[0];
diff --git a/src/TensorFlowNET.Core/Operations/math_ops.cs b/src/TensorFlowNET.Core/Operations/math_ops.cs
index 8e147b41..de9d761c 100644
--- a/src/TensorFlowNET.Core/Operations/math_ops.cs
+++ b/src/TensorFlowNET.Core/Operations/math_ops.cs
@@ -480,6 +480,13 @@ namespace Tensorflow
throw new NotImplementedException();
}
+ public static Tensor reduce_sum(Tensor[] input_tensors, int? axis = null, bool keepdims = false, string name = null)
+ {
+ var dims = _ReductionDims(input_tensors, axis);
+ var m = gen_math_ops._sum(input_tensors, dims, keep_dims: keepdims, name: name);
+ return _may_reduce_to_scalar(keepdims, axis, m);
+ }
+
public static Tensor reduce_sum(Tensor input_tensor, Tensor axis = null, bool keepdims = false, string name = null)
{
var r = _ReductionDims(input_tensor, axis);
diff --git a/src/TensorFlowNET.Core/Status/Status.cs b/src/TensorFlowNET.Core/Status/Status.cs
index 928f39f2..1e2e222c 100644
--- a/src/TensorFlowNET.Core/Status/Status.cs
+++ b/src/TensorFlowNET.Core/Status/Status.cs
@@ -47,6 +47,8 @@ namespace Tensorflow
TF_SetStatus(_handle, code, msg);
}
+ public bool ok() => Code == TF_Code.TF_OK;
+
///
/// Check status
/// Throw exception with error message if code != TF_OK
diff --git a/src/TensorFlowNET.Core/Tensors/TF_Tensor.cs b/src/TensorFlowNET.Core/Tensors/TF_Tensor.cs
index ea80f073..210501f5 100644
--- a/src/TensorFlowNET.Core/Tensors/TF_Tensor.cs
+++ b/src/TensorFlowNET.Core/Tensors/TF_Tensor.cs
@@ -3,11 +3,20 @@ using System.Runtime.InteropServices;
namespace Tensorflow
{
- [StructLayout(LayoutKind.Sequential)]
public struct TF_Tensor
{
- public TF_DataType dtype;
- public IntPtr shape;
- public IntPtr buffer;
+ IntPtr _handle;
+
+ public TF_Tensor(IntPtr handle)
+ => _handle = handle;
+
+ public static implicit operator TF_Tensor(IntPtr handle)
+ => new TF_Tensor(handle);
+
+ public static implicit operator IntPtr(TF_Tensor tensor)
+ => tensor._handle;
+
+ public override string ToString()
+ => $"TF_Tensor {_handle}";
}
}
diff --git a/src/TensorFlowNET.Core/Tensors/Tensor.Implicit.cs b/src/TensorFlowNET.Core/Tensors/Tensor.Implicit.cs
index b5fdde48..94d95eba 100644
--- a/src/TensorFlowNET.Core/Tensors/Tensor.Implicit.cs
+++ b/src/TensorFlowNET.Core/Tensors/Tensor.Implicit.cs
@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
using System.Text;
+using Tensorflow.Eager;
namespace Tensorflow
{
@@ -15,13 +16,12 @@ namespace Tensorflow
}
public static implicit operator Operation(Tensor tensor)
- {
- return tensor.op;
- }
+ => tensor.op;
+
+ public static implicit operator TF_Tensor(Tensor tensor)
+ => new TF_Tensor(tensor._handle);
public static implicit operator Tensor(IntPtr handle)
- {
- return new Tensor(handle);
- }
+ => new Tensor(handle);
}
}
diff --git a/src/TensorFlowNET.Core/Tensors/Tensor.Value.cs b/src/TensorFlowNET.Core/Tensors/Tensor.Value.cs
index c4251e28..0b51bec5 100644
--- a/src/TensorFlowNET.Core/Tensors/Tensor.Value.cs
+++ b/src/TensorFlowNET.Core/Tensors/Tensor.Value.cs
@@ -157,7 +157,15 @@ namespace Tensorflow
}
else
{
- throw new NotImplementedException("numpy not implemented when ndim > 0");
+ switch (dtype)
+ {
+ case TF_DataType.TF_STRING:
+ return StringData();
+ case TF_DataType.TF_INT32:
+ return ToArray();
+ default:
+ return BufferToArray();
+ }
}
}
diff --git a/src/TensorFlowNET.Core/ops.cs b/src/TensorFlowNET.Core/ops.cs
index 9ac0a042..2fe5ef4e 100644
--- a/src/TensorFlowNET.Core/ops.cs
+++ b/src/TensorFlowNET.Core/ops.cs
@@ -23,6 +23,7 @@ using System.Threading;
using NumSharp;
using Tensorflow.Util;
using static Tensorflow.Binding;
+using Tensorflow.Eager;
namespace Tensorflow
{
@@ -95,15 +96,19 @@ namespace Tensorflow
///
///
///
- public static Tensor convert_to_tensor(object value, TF_DataType dtype = TF_DataType.DtInvalid, string name = null, TF_DataType preferred_dtype = TF_DataType.DtInvalid)
+ public static Tensor convert_to_tensor(object value,
+ TF_DataType dtype = TF_DataType.DtInvalid,
+ string name = null,
+ TF_DataType preferred_dtype = TF_DataType.DtInvalid,
+ Context ctx = null)
{
- return convert_to_tensor_v2(value, dtype, preferred_dtype, name);
+ return internal_convert_to_tensor(value,
+ dtype: dtype,
+ name: name,
+ preferred_dtype: preferred_dtype,
+ as_ref: false);
}
- public static Tensor convert_to_tensor_v2(object value, TF_DataType dtype = TF_DataType.DtInvalid, TF_DataType dtype_hint = TF_DataType.DtInvalid, string name = null)
- {
- return internal_convert_to_tensor(value, dtype: dtype, name: name, preferred_dtype: dtype_hint, as_ref: false);
- }
public static Tensor convert_to_tensor_or_composite(Tensor value, TF_DataType dtype = TF_DataType.DtInvalid, string name = null)
{