From f5a355177d92c78b41b8e7b90a0b1ef99f3fcfab Mon Sep 17 00:00:00 2001 From: Oceania2018 Date: Sun, 14 Feb 2021 16:57:05 -0600 Subject: [PATCH] Refactor RunInAutoMode2. --- .../Contexts/AutoModeArgs.cs | 13 ++++ .../Contexts/Context.AutoMode.cs | 61 ++++++++++++++-- .../Eager/EagerRunner.TFE_FastPathExecute.cs | 15 ++++ src/TensorFlowNET.Core/Eager/IEagerRunner.cs | 8 ++ .../Operations/array_ops.cs | 73 +++++++------------ .../Operations/gen_image_ops.cs | 32 +++----- .../Operations/gen_math_ops.cs | 70 +++++------------- src/TensorFlowNET.Core/Operations/math_ops.cs | 57 +++------------ 8 files changed, 155 insertions(+), 174 deletions(-) create mode 100644 src/TensorFlowNET.Core/Contexts/AutoModeArgs.cs diff --git a/src/TensorFlowNET.Core/Contexts/AutoModeArgs.cs b/src/TensorFlowNET.Core/Contexts/AutoModeArgs.cs new file mode 100644 index 00000000..4fcd4bf0 --- /dev/null +++ b/src/TensorFlowNET.Core/Contexts/AutoModeArgs.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tensorflow +{ + public class AutoModeArgs + { + public Func GetGradientAttrs { get; set; } + public object OpInputArgs { get; set; } + public object OpAttrs { get; set; } + } +} diff --git a/src/TensorFlowNET.Core/Contexts/Context.AutoMode.cs b/src/TensorFlowNET.Core/Contexts/Context.AutoMode.cs index b076c90f..2f22865c 100644 --- a/src/TensorFlowNET.Core/Contexts/Context.AutoMode.cs +++ b/src/TensorFlowNET.Core/Contexts/Context.AutoMode.cs @@ -20,6 +20,7 @@ using System.Linq; using Tensorflow.Eager; using static Tensorflow.Binding; using Google.Protobuf; +using System.Collections.Generic; namespace Tensorflow.Contexts { @@ -57,14 +58,39 @@ namespace Tensorflow.Contexts } } } - + // [DebuggerStepThrough] - public Tensors RunInAutoMode2(Func graphAction, - Func eagerAction, - Action recordGradient, - Tensors tensors) + public Tensors RunInAutoMode2(string OpType, string Name, AutoModeArgs args) { - if (tf.Context.has_graph_arg(tensors)) + var inputArgs = ConvertToDict(args.OpInputArgs); + var attrDict = ConvertToDict(args.OpAttrs); + + Func graphAction = () => + { + foreach (var attr in attrDict) + inputArgs[attr.Key] = attr.Value; + return tf.OpDefLib._apply_op_helper(OpType, Name, inputArgs).output; + }; + + Func eagerAction = () => + { + var attrs = new object[attrDict.Count() * 2]; + int i = 0; + foreach(var arg in attrDict) + { + attrs[i]= arg.Key; + attrs[i + 1] = arg.Value; + i += 2; + } + + return tf.Runner.TFE_FastPathExecute2(tf.Context, tf.Context.DeviceName, + OpType, Name, + null, + inputArgs.Values.ToArray(), + attrs).FirstOrDefault(); + }; + + if (tf.Context.has_graph_arg(inputArgs.Values)) { if (executing_eagerly()) { @@ -77,7 +103,28 @@ namespace Tensorflow.Contexts { var result = graphAction(); if (tf.Runner.MustRecordGradient()) - recordGradient(result[0].op); + { + var op = result[0].op; + Dictionary attrs; + if (args.GetGradientAttrs == null) + { + attrs = new Dictionary(); + attrs["T"] = op.get_attr("T"); + } + else + { + attrs = ConvertToDict(args.GetGradientAttrs(op)); + } + var args1 = new object[attrs.Count() * 2]; + int i = 0; + foreach (var arg in attrs) + { + args1[i] = arg.Key; + args1[i + 1] = arg.Value; + i += 2; + } + tf.Runner.RecordGradient(OpType, op.inputs, args1, op.outputs); + } return result; } } diff --git a/src/TensorFlowNET.Core/Eager/EagerRunner.TFE_FastPathExecute.cs b/src/TensorFlowNET.Core/Eager/EagerRunner.TFE_FastPathExecute.cs index ea0cdd96..a7d8503a 100644 --- a/src/TensorFlowNET.Core/Eager/EagerRunner.TFE_FastPathExecute.cs +++ b/src/TensorFlowNET.Core/Eager/EagerRunner.TFE_FastPathExecute.cs @@ -18,6 +18,21 @@ namespace Tensorflow.Eager int kFastPathExecuteInputStartIndex = 0; UnorderedMap thread_local_eager_operation_map = new UnorderedMap(); + public Tensor[] TFE_FastPathExecute2(Context ctx, + string device_name, + string opName, + string name, + Action callbacks, + object[] inputArgs, + object[] attrs) + { + var args = new List(); + args.AddRange(inputArgs); + if (attrs != null) + args.AddRange(attrs); + return TFE_FastPathExecute(ctx, device_name, opName, name, callbacks, args.ToArray()); + } + public Tensor[] TFE_FastPathExecute(Context ctx, string device_name, string opName, diff --git a/src/TensorFlowNET.Core/Eager/IEagerRunner.cs b/src/TensorFlowNET.Core/Eager/IEagerRunner.cs index 6f401c1d..c1fb8607 100644 --- a/src/TensorFlowNET.Core/Eager/IEagerRunner.cs +++ b/src/TensorFlowNET.Core/Eager/IEagerRunner.cs @@ -16,6 +16,14 @@ namespace Tensorflow.Eager TF_DataType default_dtype = TF_DataType.DtInvalid, object[] args = null); + Tensor[] TFE_FastPathExecute2(Context ctx, + string device_name, + string opName, + string name, + Action callbacks, + object[] inputArgs, + object[] attrs); + Tensor[] TFE_FastPathExecute(Context ctx, string device_name, string opName, diff --git a/src/TensorFlowNET.Core/Operations/array_ops.cs b/src/TensorFlowNET.Core/Operations/array_ops.cs index 625d76a1..bc4b1206 100644 --- a/src/TensorFlowNET.Core/Operations/array_ops.cs +++ b/src/TensorFlowNET.Core/Operations/array_ops.cs @@ -737,44 +737,35 @@ namespace Tensorflow public static Tensor strided_slice_grad(Tensor shape, Tensor begin, Tensor end, Tensor strides, Tensor dy, long begin_mask = 0, long end_mask = 0, long ellipsis_mask = 0, long new_axis_mask = 0, long shrink_axis_mask = 0, string name = null) - => tf.Context.RunInAutoMode2( - () => tf.OpDefLib._apply_op_helper("StridedSliceGrad", name, new + => tf.Context.RunInAutoMode2("StridedSliceGrad", name, new AutoModeArgs + { + OpInputArgs = new { shape, begin, end, strides, - dy, + dy + }, + OpAttrs = new + { begin_mask, end_mask, ellipsis_mask, new_axis_mask, shrink_axis_mask - }).output, - () => tf.Runner.TFE_FastPathExecute(tf.Context, tf.Context.DeviceName, - "StridedSliceGrad", name, - null, - shape, begin, end, strides, dy, - "begin_mask", begin_mask, - "end_mask", end_mask, - "ellipsis_mask", ellipsis_mask, - "new_axis_mask", new_axis_mask, - "shrink_axis_mask", shrink_axis_mask).FirstOrDefault(), - (op) => - { - var attrs = new object[] - { - "T", op.get_attr("T"), - "Index", op.get_attr("Index"), - "begin_mask", op.get_attr("begin_mask"), - "end_mask", op.get_attr("end_mask"), - "ellipsis_mask", op.get_attr("ellipsis_mask"), - "new_axis_mask", op.get_attr("new_axis_mask"), - "shrink_axis_mask", op.get_attr("shrink_axis_mask") - }; - tf.Runner.RecordGradient("StridedSliceGrad", op.inputs, attrs, op.outputs); }, - new Tensors(shape, begin, end, strides, dy)); + GetGradientAttrs = (op) => new + { + T = op.get_attr("T"), + Index = op.get_attr("Index"), + begin_mask = op.get_attr("begin_mask"), + end_mask = op.get_attr("end_mask"), + ellipsis_mask = op.get_attr("ellipsis_mask"), + new_axis_mask = op.get_attr("new_axis_mask"), + shrink_axis_mask = op.get_attr("shrink_axis_mask") + } + }); /// /// Removes dimensions of size 1 from the shape of a tensor. @@ -969,27 +960,15 @@ namespace Tensorflow => gen_array_ops.slice(input, begin, size, name: name); public static Tensor slice(Tensor input, Tensor begin, Tensor size, string name = null) - => tf.Context.RunInAutoMode2( - () => tf.OpDefLib._apply_op_helper("Slice", name, new - { - input, - begin, - size - }).output, - () => tf.Runner.TFE_FastPathExecute(tf.Context, tf.Context.DeviceName, - "Slice", name, - null, - input, begin, size).FirstOrDefault(), - (op) => + => tf.Context.RunInAutoMode2("Slice", name, new AutoModeArgs + { + OpInputArgs = new { input, begin, size }, + GetGradientAttrs = (op) => new { - var attrs = new object[] - { - "T", op.get_attr("T"), - "Index", op.get_attr("Index") - }; - tf.Runner.RecordGradient("Slice", op.inputs, attrs, op.outputs); - }, - new Tensors(input, begin, size)); + T = op.get_attr("T"), + Index = op.get_attr("Index") + } + }); public static Tensor stack(object values, int axis = 0, string name = "stack") { diff --git a/src/TensorFlowNET.Core/Operations/gen_image_ops.cs b/src/TensorFlowNET.Core/Operations/gen_image_ops.cs index 87bc12ee..955f2db3 100644 --- a/src/TensorFlowNET.Core/Operations/gen_image_ops.cs +++ b/src/TensorFlowNET.Core/Operations/gen_image_ops.cs @@ -240,30 +240,16 @@ namespace Tensorflow public static Tensor resize_nearest_neighbor_grad(Tensor grads, Tensor size, bool align_corners = false, bool half_pixel_centers = false, string name = null) - => tf.Context.RunInAutoMode2( - () => tf.OpDefLib._apply_op_helper("ResizeNearestNeighborGrad", name, new + => tf.Context.RunInAutoMode2("ResizeNearestNeighborGrad", name, new AutoModeArgs { - grads, - size, - align_corners, - half_pixel_centers - }).output, - () => tf.Runner.TFE_FastPathExecute(tf.Context, tf.Context.DeviceName, - "ResizeNearestNeighborGrad", name, - null, - grads, size, - "align_corners", align_corners, - "half_pixel_centers", half_pixel_centers).FirstOrDefault(), - (op) => - { - var attrs = new object[] + OpInputArgs = new { grads, size }, + OpAttrs = new { align_corners, half_pixel_centers }, + GetGradientAttrs = (op) => new { - "T", op.get_attr("T"), - "align_corners", op.get_attr("align_corners"), - "half_pixel_centers", op.get_attr("half_pixel_centers") - }; - tf.Runner.RecordGradient("ResizeNearestNeighborGrad", op.inputs, attrs, op.outputs); - }, - new Tensors(grads, size)); + T = op.get_attr("T"), + align_corners = op.get_attr("align_corners"), + half_pixel_centers = op.get_attr("half_pixel_centers") + } + }); } } diff --git a/src/TensorFlowNET.Core/Operations/gen_math_ops.cs b/src/TensorFlowNET.Core/Operations/gen_math_ops.cs index 051f4f6b..b40b3b91 100644 --- a/src/TensorFlowNET.Core/Operations/gen_math_ops.cs +++ b/src/TensorFlowNET.Core/Operations/gen_math_ops.cs @@ -141,29 +141,17 @@ namespace Tensorflow /// A name for the operation (optional). /// A `Tensor`. Has the same type as `input`. public static Tensor mean(Tensor input, Tensor axis, bool keep_dims = false, string name = null) - => tf.Context.RunInAutoMode2( - () => tf.OpDefLib._apply_op_helper("Mean", name, new - { - input, - reduction_indices = axis, - keep_dims = keep_dims - }).output, - () => tf.Runner.TFE_FastPathExecute(tf.Context, tf.Context.DeviceName, - "Mean", name, - null, - input, axis, - "keep_dims", keep_dims).FirstOrDefault(), - (op) => + => tf.Context.RunInAutoMode2("Mean", name, new AutoModeArgs + { + OpInputArgs = new { input, axis }, + OpAttrs = new { keep_dims, reduction_indices = axis }, + GetGradientAttrs = (op) => new { - var attrs = new object[] - { - "T", op.get_attr("T"), - "Tidx", op.get_attr("Tidx"), - "keep_dims", op.get_attr("keep_dims") - }; - tf.Runner.RecordGradient("Mean", op.inputs, attrs, op.outputs); - }, - new Tensors(input, axis)); + T = op.get_attr("T"), + Tidx = op.get_attr("Tidx"), + keep_dims = op.get_attr("keep_dims") + } + }); public static Tensor mean(Tensor[] inputs, Tensor axis, bool keep_dims = false, string name = null) { @@ -356,21 +344,10 @@ namespace Tensorflow /// dy is the corresponding input gradient. /// public static Tensor sigmoid_grad(Tensor y, Tensor dy, string name = "SigmoidGrad") - => tf.Context.RunInAutoMode2( - () => tf.OpDefLib._apply_op_helper("SigmoidGrad", name, new { y, dy }).output, - () => tf.Runner.TFE_FastPathExecute(tf.Context, tf.Context.DeviceName, - "SigmoidGrad", name, - null, - y, dy).FirstOrDefault(), - (op) => - { - var attrs = new object[] - { - "T", op.get_attr("T") - }; - tf.Runner.RecordGradient("SigmoidGrad", op.inputs, attrs, op.outputs); - }, - new Tensors(y, dy)); + => tf.Context.RunInAutoMode2("SigmoidGrad", name, new AutoModeArgs + { + OpInputArgs = new { y, dy } + }); public static Tensor sign(T x, string name = "Sign") { @@ -806,21 +783,10 @@ namespace Tensorflow } public static Tensor sub(Tensor x, Tensor y, string name = null) - => tf.Context.RunInAutoMode2( - () => tf.OpDefLib._apply_op_helper("Sub", name, new { x, y }).output, - () => tf.Runner.TFE_FastPathExecute(tf.Context, tf.Context.DeviceName, - "Sub", name, - null, - x, y).FirstOrDefault(), - (op) => - { - var attrs = new object[] - { - "T", op.get_attr("T") - }; - tf.Runner.RecordGradient("Sub", op.inputs, attrs, op.outputs); - }, - new Tensors(x, y)); + => tf.Context.RunInAutoMode2("Sub", name, new AutoModeArgs + { + OpInputArgs = new { x, y } + }); public static Tensor sub(Tx x, Ty y, string name = null) { diff --git a/src/TensorFlowNET.Core/Operations/math_ops.cs b/src/TensorFlowNET.Core/Operations/math_ops.cs index eabd5cd1..fc8a28d5 100644 --- a/src/TensorFlowNET.Core/Operations/math_ops.cs +++ b/src/TensorFlowNET.Core/Operations/math_ops.cs @@ -45,21 +45,10 @@ namespace Tensorflow => gen_math_ops.add(x, y, name); public static Tensor add_v2(Tensor x, Tensor y, string name = null) - => tf.Context.RunInAutoMode2( - () => tf.OpDefLib._apply_op_helper("AddV2", name, new { x, y }).output, - () => tf.Runner.TFE_FastPathExecute(tf.Context, tf.Context.DeviceName, - "AddV2", name, - null, - x, y).FirstOrDefault(), - (op) => - { - var attrs = new object[] - { - "T", op.get_attr("T") - }; - tf.Runner.RecordGradient("AddV2", op.inputs, attrs, op.outputs); - }, - new Tensors(x, y)); + => tf.Context.RunInAutoMode2("AddV2", name, new AutoModeArgs + { + OpInputArgs = new { x, y } + }); public static Tensor add_v2(Tx x, Ty y, string name = null) => gen_math_ops.add_v2(x, y, name); @@ -272,41 +261,19 @@ namespace Tensorflow /// /// public static Tensor erf(Tensor x, string name = null) - => tf.Context.RunInAutoMode2( - () => tf.OpDefLib._apply_op_helper("Erf", name, new { x }).output, - () => tf.Runner.TFE_FastPathExecute(tf.Context, tf.Context.DeviceName, - "Erf", name, - null, - x).FirstOrDefault(), - (op) => - { - var attrs = new object[] - { - "T", op.get_attr("T") - }; - tf.Runner.RecordGradient("Erf", op.inputs, attrs, op.outputs); - }, - new Tensors(x)); + => tf.Context.RunInAutoMode2("Erf", name, new AutoModeArgs + { + OpInputArgs = new { x } + }); public static Tensor sqrt(Tensor x, string name = null) => gen_math_ops.sqrt(x, name: name); public static Tensor multiply(Tensor x, Tensor y, string name = null) - => tf.Context.RunInAutoMode2( - () => tf.OpDefLib._apply_op_helper("Mul", name, new { x, y }).output, - () => tf.Runner.TFE_FastPathExecute(tf.Context, tf.Context.DeviceName, - "Mul", name, - null, - x, y).FirstOrDefault(), - (op) => - { - var attrs = new object[] - { - "T", op.get_attr("T") - }; - tf.Runner.RecordGradient("Mul", op.inputs, attrs, op.outputs); - }, - new Tensors(x, y)); + => tf.Context.RunInAutoMode2("Mul", name, new AutoModeArgs + { + OpInputArgs = new { x, y } + }); public static Tensor multiply(Tx x, Ty y, string name = null) => gen_math_ops.mul(x, y, name: name);