| @@ -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); | |||
| /// <summary> | |||
| /// Computes the sum of elements across dimensions of a tensor. | |||
| /// </summary> | |||
| /// <param name="input_tensors"></param> | |||
| /// <param name="axis"></param> | |||
| /// <param name="keepdims"></param> | |||
| /// <param name="name"></param> | |||
| /// <returns></returns> | |||
| 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); | |||
| /// <summary> | |||
| /// Computes the sum of elements across dimensions of a tensor. | |||
| /// </summary> | |||
| @@ -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; | |||
| } | |||
| /// <summary> | |||
| /// Dispose any unmanaged resources related to given <paramref name="handle"/>. | |||
| /// </summary> | |||
| @@ -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); | |||
| } | |||
| } | |||
| @@ -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); | |||
| } | |||
| } | |||
| @@ -1,12 +1,67 @@ | |||
| using System.Collections.Generic; | |||
| using System; | |||
| using System.Linq; | |||
| namespace Tensorflow.Eager | |||
| { | |||
| public class Execute | |||
| { | |||
| /// <summary> | |||
| /// Execute a TensorFlow operation. | |||
| /// </summary> | |||
| /// <param name="op_name"> | |||
| /// Name of the TensorFlow operation (see REGISTER_OP in C++ code) to | |||
| /// execute. | |||
| /// </param> | |||
| /// <param name="num_outputs"> | |||
| /// The number of outputs of the operation to fetch. | |||
| /// </param> | |||
| /// <param name="inputs"> | |||
| /// 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. | |||
| /// </param> | |||
| /// <param name="attrs"> | |||
| /// A tuple with alternating string attr names and attr values for this | |||
| /// operation. | |||
| /// </param> | |||
| /// <param name="ctx">The value of context.context().</param> | |||
| /// <param name="name">Customized name for the operation.</param> | |||
| /// <returns>List of output Tensor objects. The list is empty if there are no outputs</returns> | |||
| 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<string, object> 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); | |||
| } | |||
| } | |||
| } | |||
| @@ -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}"; | |||
| } | |||
| } | |||
| @@ -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}"; | |||
| } | |||
| } | |||
| @@ -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}"; | |||
| } | |||
| } | |||
| @@ -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}"; | |||
| } | |||
| } | |||
| @@ -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}"; | |||
| } | |||
| } | |||
| @@ -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 | |||
| /// </summary> | |||
| /// <returns>TFE_ContextOptions*</returns> | |||
| [DllImport(TensorFlowLibName)] | |||
| public static extern IntPtr TFE_NewContextOptions(); | |||
| public static extern TFE_ContextOptions TFE_NewContextOptions(); | |||
| /// <summary> | |||
| /// Destroy an options object. | |||
| @@ -70,7 +71,7 @@ namespace Tensorflow | |||
| /// <param name="status">TF_Status*</param> | |||
| /// <returns>TFE_Context*</returns> | |||
| [DllImport(TensorFlowLibName)] | |||
| public static extern IntPtr TFE_NewContext(IntPtr opts, IntPtr status); | |||
| public static extern TFE_Context TFE_NewContext(IntPtr opts, IntPtr status); | |||
| /// <summary> | |||
| /// | |||
| @@ -88,7 +89,7 @@ namespace Tensorflow | |||
| /// <param name="num_retvals">int*</param> | |||
| /// <param name="status">TF_Status*</param> | |||
| [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); | |||
| /// <summary> | |||
| /// | |||
| @@ -98,7 +99,7 @@ namespace Tensorflow | |||
| /// <param name="status">TF_Status*</param> | |||
| /// <returns></returns> | |||
| [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); | |||
| /// <summary> | |||
| /// | |||
| @@ -150,7 +151,7 @@ namespace Tensorflow | |||
| /// <param name="device_name"></param> | |||
| /// <param name="status"></param> | |||
| [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); | |||
| /// <summary> | |||
| /// | |||
| @@ -167,7 +168,7 @@ namespace Tensorflow | |||
| /// <param name="t">const tensorflow::Tensor&</param> | |||
| /// <returns>TFE_TensorHandle*</returns> | |||
| [DllImport(TensorFlowLibName)] | |||
| public static extern IntPtr TFE_NewTensorHandle(IntPtr t, IntPtr status); | |||
| public static extern TFE_TensorHandle TFE_NewTensorHandle(IntPtr t, IntPtr status); | |||
| /// <summary> | |||
| /// Sets the default execution mode (sync/async). Note that this can be | |||
| @@ -195,7 +196,7 @@ namespace Tensorflow | |||
| /// <param name="status">TF_Status*</param> | |||
| /// <returns></returns> | |||
| [DllImport(TensorFlowLibName)] | |||
| public static extern IntPtr TFE_TensorHandleResolve(IntPtr h, IntPtr status); | |||
| public static extern TF_Tensor TFE_TensorHandleResolve(IntPtr h, IntPtr status); | |||
| /// <summary> | |||
| /// This function will block till the operation that produces `h` has completed. | |||
| @@ -252,7 +253,7 @@ namespace Tensorflow | |||
| /// <param name="is_async"></param> | |||
| /// <returns>TFE_Executor*</returns> | |||
| [DllImport(TensorFlowLibName)] | |||
| public static extern IntPtr TFE_NewExecutor(bool is_async); | |||
| public static extern TFE_Executor TFE_NewExecutor(bool is_async); | |||
| /// <summary> | |||
| /// Deletes the eager Executor without waiting for enqueued nodes. Please call | |||
| @@ -0,0 +1,33 @@ | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System; | |||
| using static Tensorflow.OpDef.Types; | |||
| namespace Tensorflow.Eager | |||
| { | |||
| /// <summary> | |||
| /// python\eager\pywrap_tfe_src.cc | |||
| /// </summary> | |||
| public partial class wrap_tfe_src | |||
| { | |||
| public static void RecordGradient(string op_name, Tensor[] inputs, Dictionary<string, object> 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; | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,53 @@ | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System; | |||
| using static Tensorflow.OpDef.Types; | |||
| namespace Tensorflow.Eager | |||
| { | |||
| /// <summary> | |||
| /// python\eager\pywrap_tfe_src.cc | |||
| /// </summary> | |||
| 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; | |||
| } | |||
| } | |||
| } | |||
| @@ -8,7 +8,7 @@ namespace Tensorflow.Eager | |||
| /// <summary> | |||
| /// python\eager\pywrap_tfe_src.cc | |||
| /// </summary> | |||
| 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<string, long>(); | |||
| 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); | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// 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<string, long> attr_list_sizes, | |||
| Status status) | |||
| { | |||
| return false; | |||
| } | |||
| private static bool SetOpAttrScalar(Context ctx, IntPtr op, | |||
| string key, object value, TF_AttrType type, | |||
| Dictionary<string, long> attr_list_sizes, | |||
| @@ -213,25 +242,5 @@ namespace Tensorflow.Eager | |||
| return true; | |||
| } | |||
| public static void RecordGradient(string op_name, Tensor[] inputs, Dictionary<string, object> 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; | |||
| } | |||
| } | |||
| } | |||
| @@ -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; | |||
| } | |||
| @@ -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 | |||
| /// <returns> A `Tensor`. Has the same type as `input`.</returns> | |||
| public static Tensor mean<T1, T2>(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, T2>(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, Ty>(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 | |||
| /// <returns></returns> | |||
| 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]; | |||
| @@ -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); | |||
| @@ -47,6 +47,8 @@ namespace Tensorflow | |||
| TF_SetStatus(_handle, code, msg); | |||
| } | |||
| public bool ok() => Code == TF_Code.TF_OK; | |||
| /// <summary> | |||
| /// Check status | |||
| /// Throw exception with error message if code != TF_OK | |||
| @@ -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}"; | |||
| } | |||
| } | |||
| @@ -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); | |||
| } | |||
| } | |||
| @@ -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<int>(); | |||
| default: | |||
| return BufferToArray(); | |||
| } | |||
| } | |||
| } | |||
| @@ -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 | |||
| /// <param name="dtype"></param> | |||
| /// <param name="name"></param> | |||
| /// <returns></returns> | |||
| 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) | |||
| { | |||