| @@ -0,0 +1,13 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Text; | |||
| namespace Tensorflow | |||
| { | |||
| public class AutoModeArgs | |||
| { | |||
| public Func<Operation, object> GetGradientAttrs { get; set; } | |||
| public object OpInputArgs { get; set; } | |||
| public object OpAttrs { get; set; } | |||
| } | |||
| } | |||
| @@ -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<Tensors> graphAction, | |||
| Func<Tensors> eagerAction, | |||
| Action<Operation> 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<Tensor> graphAction = () => | |||
| { | |||
| foreach (var attr in attrDict) | |||
| inputArgs[attr.Key] = attr.Value; | |||
| return tf.OpDefLib._apply_op_helper(OpType, Name, inputArgs).output; | |||
| }; | |||
| Func<Tensor> 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<string, object> attrs; | |||
| if (args.GetGradientAttrs == null) | |||
| { | |||
| attrs = new Dictionary<string, object>(); | |||
| attrs["T"] = op.get_attr<TF_DataType>("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; | |||
| } | |||
| } | |||
| @@ -18,6 +18,21 @@ namespace Tensorflow.Eager | |||
| int kFastPathExecuteInputStartIndex = 0; | |||
| UnorderedMap<Context, SafeOpHandle> thread_local_eager_operation_map = new UnorderedMap<Context, SafeOpHandle>(); | |||
| public Tensor[] TFE_FastPathExecute2(Context ctx, | |||
| string device_name, | |||
| string opName, | |||
| string name, | |||
| Action callbacks, | |||
| object[] inputArgs, | |||
| object[] attrs) | |||
| { | |||
| var args = new List<object>(); | |||
| 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, | |||
| @@ -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, | |||
| @@ -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<TF_DataType>("T"), | |||
| "Index", op.get_attr<TF_DataType>("Index"), | |||
| "begin_mask", op.get_attr<long>("begin_mask"), | |||
| "end_mask", op.get_attr<long>("end_mask"), | |||
| "ellipsis_mask", op.get_attr<long>("ellipsis_mask"), | |||
| "new_axis_mask", op.get_attr<long>("new_axis_mask"), | |||
| "shrink_axis_mask", op.get_attr<long>("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<TF_DataType>("T"), | |||
| Index = op.get_attr<TF_DataType>("Index"), | |||
| begin_mask = op.get_attr<long>("begin_mask"), | |||
| end_mask = op.get_attr<long>("end_mask"), | |||
| ellipsis_mask = op.get_attr<long>("ellipsis_mask"), | |||
| new_axis_mask = op.get_attr<long>("new_axis_mask"), | |||
| shrink_axis_mask = op.get_attr<long>("shrink_axis_mask") | |||
| } | |||
| }); | |||
| /// <summary> | |||
| /// 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<TF_DataType>("T"), | |||
| "Index", op.get_attr<int>("Index") | |||
| }; | |||
| tf.Runner.RecordGradient("Slice", op.inputs, attrs, op.outputs); | |||
| }, | |||
| new Tensors(input, begin, size)); | |||
| T = op.get_attr<TF_DataType>("T"), | |||
| Index = op.get_attr<int>("Index") | |||
| } | |||
| }); | |||
| public static Tensor stack(object values, int axis = 0, string name = "stack") | |||
| { | |||
| @@ -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<TF_DataType>("T"), | |||
| "align_corners", op.get_attr<bool>("align_corners"), | |||
| "half_pixel_centers", op.get_attr<bool>("half_pixel_centers") | |||
| }; | |||
| tf.Runner.RecordGradient("ResizeNearestNeighborGrad", op.inputs, attrs, op.outputs); | |||
| }, | |||
| new Tensors(grads, size)); | |||
| T = op.get_attr<TF_DataType>("T"), | |||
| align_corners = op.get_attr<bool>("align_corners"), | |||
| half_pixel_centers = op.get_attr<bool>("half_pixel_centers") | |||
| } | |||
| }); | |||
| } | |||
| } | |||
| @@ -141,29 +141,17 @@ namespace Tensorflow | |||
| /// <param name="name"> A name for the operation (optional).</param> | |||
| /// <returns> A `Tensor`. Has the same type as `input`.</returns> | |||
| 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<TF_DataType>("T"), | |||
| "Tidx", op.get_attr<TF_DataType>("Tidx"), | |||
| "keep_dims", op.get_attr<bool>("keep_dims") | |||
| }; | |||
| tf.Runner.RecordGradient("Mean", op.inputs, attrs, op.outputs); | |||
| }, | |||
| new Tensors(input, axis)); | |||
| T = op.get_attr<TF_DataType>("T"), | |||
| Tidx = op.get_attr<TF_DataType>("Tidx"), | |||
| keep_dims = op.get_attr<bool>("keep_dims") | |||
| } | |||
| }); | |||
| public static Tensor mean(Tensor[] inputs, Tensor axis, bool keep_dims = false, string name = null) | |||
| { | |||
| @@ -356,21 +344,10 @@ namespace Tensorflow | |||
| /// <c>dy</c> is the corresponding input gradient. | |||
| /// </remarks> | |||
| 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<TF_DataType>("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>(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<TF_DataType>("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, Ty>(Tx x, Ty y, string name = null) | |||
| { | |||
| @@ -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<TF_DataType>("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, Ty>(Tx x, Ty y, string name = null) | |||
| => gen_math_ops.add_v2(x, y, name); | |||
| @@ -272,41 +261,19 @@ namespace Tensorflow | |||
| /// <param name="name"></param> | |||
| /// <returns></returns> | |||
| 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<TF_DataType>("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<TF_DataType>("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, Ty>(Tx x, Ty y, string name = null) | |||
| => gen_math_ops.mul(x, y, name: name); | |||