diff --git a/src/TensorFlowNET.Core/APIs/tf.array.cs b/src/TensorFlowNET.Core/APIs/tf.array.cs index 3dbb9954..59689bc5 100644 --- a/src/TensorFlowNET.Core/APIs/tf.array.cs +++ b/src/TensorFlowNET.Core/APIs/tf.array.cs @@ -217,7 +217,7 @@ namespace Tensorflow Tensor off_value = null, TF_DataType dtype = TF_DataType.DtInvalid, int axis = -1, - string name = null) => array_ops.one_hot(indices, depth, dtype: dtype, axis: axis, name: name); + string name = null) => array_ops.one_hot(indices, ops.convert_to_tensor(depth), dtype: dtype, axis: axis, name: name); /// /// Pads a tensor diff --git a/src/TensorFlowNET.Core/APIs/tf.math.cs b/src/TensorFlowNET.Core/APIs/tf.math.cs index 4ad70420..f960e14c 100644 --- a/src/TensorFlowNET.Core/APIs/tf.math.cs +++ b/src/TensorFlowNET.Core/APIs/tf.math.cs @@ -21,6 +21,13 @@ namespace Tensorflow { public partial class tensorflow { + public MathApi math { get; } = new MathApi(); + public class MathApi + { + public Tensor log(Tensor x, string name = null) + => gen_math_ops.log(x, name); + } + public Tensor abs(Tensor x, string name = null) => math_ops.abs(x, name); @@ -254,7 +261,7 @@ namespace Tensorflow /// Any values less than clip_value_min are set to clip_value_min. Any values /// greater than clip_value_max are set to clip_value_max. /// - public Tensor clip_by_value (Tensor t, Tensor clip_value_min, Tensor clip_value_max, string name = "ClipByValue") + public Tensor clip_by_value(Tensor t, T1 clip_value_min, T2 clip_value_max, string name = "ClipByValue") => clip_ops.clip_by_value(t, clip_value_min, clip_value_max, name); public Tensor sub(Tx a, Ty b, string name = null) diff --git a/src/TensorFlowNET.Core/APIs/tf.nn.cs b/src/TensorFlowNET.Core/APIs/tf.nn.cs index 19afce1d..3f756502 100644 --- a/src/TensorFlowNET.Core/APIs/tf.nn.cs +++ b/src/TensorFlowNET.Core/APIs/tf.nn.cs @@ -14,6 +14,7 @@ limitations under the License. ******************************************************************************/ +using System; using Tensorflow.Operations; using Tensorflow.Operations.Activation; using static Tensorflow.Binding; @@ -182,7 +183,13 @@ namespace Tensorflow => nn_impl.sigmoid_cross_entropy_with_logits(labels: labels, logits: logits, name: name); public Tensor softmax(Tensor logits, int axis = -1, string name = null) - => gen_nn_ops.softmax(logits, name); + { + if (axis == -1) + return gen_nn_ops.softmax(logits, name); + else + throw new NotImplementedException(""); + } + /// /// Computes sparse softmax cross entropy between `logits` and `labels`. diff --git a/src/TensorFlowNET.Core/Eager/EagerOperation.cs b/src/TensorFlowNET.Core/Eager/EagerOperation.cs index 8e216e77..88bcc796 100644 --- a/src/TensorFlowNET.Core/Eager/EagerOperation.cs +++ b/src/TensorFlowNET.Core/Eager/EagerOperation.cs @@ -18,7 +18,7 @@ namespace Tensorflow.Eager public Tensor[] Outputs { get; set; } public BindingArray SkipInputIndicesArray { get; set; } public unsafe int[] SkipInputIndices => SkipInputIndicesArray.Data.Select(x => *(int*) x).ToArray(); - public BindingArray AttrsArray { get; set; } + public string[] AttrsArray { get; set; } public EagerOperation() : base(IntPtr.Zero) { @@ -70,14 +70,11 @@ namespace Tensorflow.Eager return value; } - public bool get_attr_bool(string attr_name) + public bool get_attr_bool(string attr_name) { - for (int i = 0; i < AttrsArray.Data.Length; i = i + 2) - { - // var a = *(char*)AttrsArray.Data[i]; - if (op_dict[Name].Attr[i].Name == attr_name) - return (int)AttrsArray.Data[i + 1] == 1; - } + for (int i = 0; i < AttrsArray.Length; i = i + 2) + if (AttrsArray[i] == attr_name) + return AttrsArray[i + 1] == "1"; throw new ValueError($"Can't find attr: {attr_name}"); } diff --git a/src/TensorFlowNET.Core/Eager/EagerTensor.Creation.cs b/src/TensorFlowNET.Core/Eager/EagerTensor.Creation.cs index 062391c1..d6fd7fd6 100644 --- a/src/TensorFlowNET.Core/Eager/EagerTensor.Creation.cs +++ b/src/TensorFlowNET.Core/Eager/EagerTensor.Creation.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Text; +using System.Threading; using static Tensorflow.Binding; namespace Tensorflow.Eager @@ -49,6 +50,10 @@ namespace Tensorflow.Eager print($"new TensorHandle {Id} {tfe_tensor_handle.ToString("x16")}"); print($"new EagerTensor {Id} {EagerTensorHandle.ToString("x16")}");*/ + if (tfe_tensor_handle == IntPtr.Zero && _id == 0) + { + } + GarbageCollector.Increase(_handle, GCItemType.TensorHandle); GarbageCollector.Increase(tfe_tensor_handle, GCItemType.LocalTensorHandle); GarbageCollector.Increase(EagerTensorHandle, GCItemType.EagerTensorHandle); @@ -56,6 +61,9 @@ namespace Tensorflow.Eager return this; } + public override IntPtr ToPointer() + => EagerTensorHandle; + protected override void DisposeUnmanagedResources(IntPtr handle) { GarbageCollector.Decrease(_handle); diff --git a/src/TensorFlowNET.Core/Eager/EagerTensor.cs b/src/TensorFlowNET.Core/Eager/EagerTensor.cs index db756140..7a88a602 100644 --- a/src/TensorFlowNET.Core/Eager/EagerTensor.cs +++ b/src/TensorFlowNET.Core/Eager/EagerTensor.cs @@ -13,7 +13,7 @@ namespace Tensorflow.Eager public IntPtr EagerTensorHandle { get; set; } public override string Device => c_api.StringPiece(c_api.TFE_TensorHandleDeviceName(tfe_tensor_handle, status)); - // public override int rank => c_api.TFE_TensorHandleNumDims(tfe_tensor_handle, status); + public override int rank => c_api.TFE_TensorHandleNumDims(tfe_tensor_handle, status); public static int GetRank(IntPtr handle) { diff --git a/src/TensorFlowNET.Core/Eager/c_api.eager.cs b/src/TensorFlowNET.Core/Eager/c_api.eager.cs index 9344410c..9971dd97 100644 --- a/src/TensorFlowNET.Core/Eager/c_api.eager.cs +++ b/src/TensorFlowNET.Core/Eager/c_api.eager.cs @@ -25,7 +25,7 @@ namespace Tensorflow public delegate IntPtr gradient_function_callback(string op_name, IntPtr op_inputs, IntPtr op_outputs, - IntPtr attrs_handle, + string attrs_string, IntPtr output_grads, IntPtr skip_input_indices); @@ -402,6 +402,7 @@ namespace Tensorflow string name, IntPtr[] inputs, int input_size, + string attrs_string, TFE_FastPathExecute_SetOpAttrs set_op_attrs, IntPtr[] outputs, int output_size); 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 12ccd56d..c5a0df60 100644 --- a/src/TensorFlowNET.Core/Eager/wrap_tfe_src.TFE_FastPathExecute.cs +++ b/src/TensorFlowNET.Core/Eager/wrap_tfe_src.TFE_FastPathExecute.cs @@ -31,6 +31,37 @@ namespace Tensorflow.Eager } } + public static string SetOpAttrs2(params object[] attrs) + { + string attr_string = string.Empty; + for(int i = 0; i < attrs.Length; i = i + 2) + { + object key = attrs[i]; + object value = attrs[i + 1]; + + switch (value) + { + case TF_DataType dtype: + value = (int)dtype; + break; + case bool bVal: + value = bVal ? 1 : 0; + break; + case int[] shape: + value = shape.Length == 0 ? "null" : string.Join(" ", shape); + break; + default: + break; + } + + attr_string += string.IsNullOrEmpty(attr_string) ? + $"{key},{value}" : + $",{key},{value}"; + } + + return attr_string; + } + /// /// 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 diff --git a/src/TensorFlowNET.Core/Gradients/GradientTape.cs b/src/TensorFlowNET.Core/Gradients/GradientTape.cs index 917951e9..7fbb0cb9 100644 --- a/src/TensorFlowNET.Core/Gradients/GradientTape.cs +++ b/src/TensorFlowNET.Core/Gradients/GradientTape.cs @@ -3,6 +3,7 @@ using NumSharp.Utilities; using System; using System.Collections.Generic; using System.Linq; +using System.Reflection; using System.Runtime.InteropServices; using System.Text; using Tensorflow.Eager; @@ -79,15 +80,26 @@ namespace Tensorflow.Gradients _pop_tape(); } - var results = new[] { new EagerTensor() }; + var results = EagerTensorPass.Create(); + var targets = EagerTensorPass.From(target); + var sources = EagerTensorPass.From(source); + Status status = c_api.TFE_TapeGradient(_tape, - new[] { (target as EagerTensor).EagerTensorHandle }, 1, - new[] { (source as EagerTensor).EagerTensorHandle }, 1, - results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); + targets.Points, targets.Length, + sources.Points, sources.Length, + results.Points, results.Length); status.Check(true); + return results[0].Resolve(); } + public Tensor gradient(Tensor target, ResourceVariable source) + { + var results = gradient(target as EagerTensor, new[] { source }); + + return results[0]; + } + public (Tensor, Tensor) gradient(Tensor target, (ResourceVariable, ResourceVariable) sources) { var results = gradient(target as EagerTensor, new[] { sources.Item1, sources.Item2 }); @@ -103,14 +115,14 @@ namespace Tensorflow.Gradients _pop_tape(); } - var results = sources.Select(x => new EagerTensor()).ToArray(); + var results = EagerTensorPass.Create(sources.Length); + var target_inputs = EagerTensorPass.From(target); + var source_inputs = EagerTensorPass.From(sources.Select(x => x.Handle).ToArray()); + Status status = c_api.TFE_TapeGradient(_tape, - new IntPtr[] - { - target.EagerTensorHandle - }, 1, - sources.Select(x => (x.Handle as EagerTensor).EagerTensorHandle).ToArray(), sources.Length, - results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); + target_inputs.Points, target_inputs.Length, + source_inputs.Points, source_inputs.Length, + results.Points, results.Length); status.Check(true); if (!_persistent) @@ -120,13 +132,15 @@ namespace Tensorflow.Gradients _tape = null; } - return results.Select(x => x.Resolve()).ToArray(); + return results.Items.Select(x => x.Resolve()).ToArray(); } public void Dispose() { if (_recording) _pop_tape(); + + tf.tensorMgr.Reset(); } } } diff --git a/src/TensorFlowNET.Core/Gradients/math_grad.cs b/src/TensorFlowNET.Core/Gradients/math_grad.cs index eb44f1da..4e5a5e85 100644 --- a/src/TensorFlowNET.Core/Gradients/math_grad.cs +++ b/src/TensorFlowNET.Core/Gradients/math_grad.cs @@ -310,23 +310,26 @@ namespace Tensorflow.Gradients var input_shape = op.inputs[0]._shape_tuple(); var output_shape = op.outputs[0]._shape_tuple(); + Tensor result, factor_tensor; if(input_shape != null && output_shape != null) { var input_size = np.prod(input_shape); var output_size = np.prod(output_shape); var factor = (int)input_size / Math.Max((int)output_size, 1); - var factor_tensor = constant_op.constant((int)input_size, dtype: sum_grad.dtype); - return new Tensor[] { math_ops.truediv(sum_grad, math_ops.cast(factor_tensor, sum_grad.dtype)), null }; + factor_tensor = constant_op.constant(factor, dtype: sum_grad.dtype); } else { var input_shape_tensor = array_ops.shape(op.inputs[0]); var output_shape_tensor = array_ops.shape(op.outputs[0]); var factor = _safe_shape_div(math_ops.reduce_prod(input_shape_tensor), math_ops.reduce_prod(output_shape_tensor)); - - return new Tensor[] { math_ops.truediv(sum_grad, math_ops.cast(factor, sum_grad.dtype)), null }; + throw new NotImplementedException(""); + factor_tensor = null; } + + result = math_ops.truediv(sum_grad, math_ops.cast(factor_tensor, sum_grad.dtype)); + return new Tensor[] { result, null }; } /// @@ -513,20 +516,23 @@ namespace Tensorflow.Gradients input_shape = array_ops.shape(op.inputs[0]); return new Tensor[] { gen_array_ops.tile(grad, input_shape), null }; } - else + else if (!input_0_shape.Contains(-1) && !tf.context.executing_eagerly()) { - + throw new NotImplementedException(""); } } } input_shape = array_ops.shape(op.inputs[0]); - ops.colocate_with(input_shape); - var output_shape_kept_dims = math_ops.reduced_shape(input_shape, op.inputs[1]); - var tile_scaling = _safe_shape_div(input_shape, output_shape_kept_dims); - grad = gen_array_ops.reshape(grad, output_shape_kept_dims); + if (!op.get_attr("keep_dims")) + { + ops.colocate_with(input_shape); + var output_shape_kept_dims = math_ops.reduced_shape(input_shape, op.inputs[1]); + // var tile_scaling = _safe_shape_div(input_shape, output_shape_kept_dims); + grad = gen_array_ops.reshape(grad, output_shape_kept_dims); + } - return new Tensor[] { gen_array_ops.tile(grad, tile_scaling), null }; + return new Tensor[] { gen_array_ops.broadcast_to(grad, input_shape), null }; } [RegisterGradient("RealDiv")] diff --git a/src/TensorFlowNET.Core/Graphs/Graph.Control.cs b/src/TensorFlowNET.Core/Graphs/Graph.Control.cs index 81c13827..b119745c 100644 --- a/src/TensorFlowNET.Core/Graphs/Graph.Control.cs +++ b/src/TensorFlowNET.Core/Graphs/Graph.Control.cs @@ -17,6 +17,7 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; +using Tensorflow.Eager; using Tensorflow.Operations; using static Tensorflow.Binding; @@ -81,6 +82,9 @@ namespace Tensorflow /// public _ControlDependenciesController control_dependencies(object[] control_inputs) { + if (tf.context.executing_eagerly()) + return new _ControlDependenciesController(this, null); + if (control_inputs == null) return new _ControlDependenciesController(this, null); diff --git a/src/TensorFlowNET.Core/Graphs/NullContextmanager.cs b/src/TensorFlowNET.Core/Graphs/NullContextmanager.cs new file mode 100644 index 00000000..a8b57ea3 --- /dev/null +++ b/src/TensorFlowNET.Core/Graphs/NullContextmanager.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tensorflow +{ + public class NullContextmanager : ITensorFlowObject + { + public void __init__() + { + throw new NotImplementedException(); + } + + public void __enter__() + { + throw new NotImplementedException(); + } + + public void __del__() + { + throw new NotImplementedException(); + } + + public void __exit__() + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + } +} diff --git a/src/TensorFlowNET.Core/Operations/NnOps/gen_nn_ops.cs b/src/TensorFlowNET.Core/Operations/NnOps/gen_nn_ops.cs index b7c3b392..47641d4d 100644 --- a/src/TensorFlowNET.Core/Operations/NnOps/gen_nn_ops.cs +++ b/src/TensorFlowNET.Core/Operations/NnOps/gen_nn_ops.cs @@ -373,6 +373,19 @@ namespace Tensorflow.Operations public static Tensor relu_grad(Tensor gradients, Tensor features, string name = null) { + if (tf.context.executing_eagerly()) + { + var results = EagerTensorPass.Create(); + var inputs = EagerTensorPass.From(gradients, features); + Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, + "ReluGrad", name, + inputs.Points, inputs.Length, + null, null, + results.Points, results.Length); + status.Check(true); + return results[0].Resolve(); + } + var _op = _op_def_lib._apply_op_helper("ReluGrad", name: name, args: new { gradients, @@ -396,6 +409,19 @@ namespace Tensorflow.Operations public static Tensor softmax(Tensor logits, string name = null) { + if (tf.context.executing_eagerly()) + { + var results = EagerTensorPass.Create(); + var inputs = EagerTensorPass.From(logits); + Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, + "Softmax", name, + inputs.Points, inputs.Length, + null, null, + results.Points, results.Length); + status.Check(true); + return results[0].Resolve(); + } + var _op = _op_def_lib._apply_op_helper("Softmax", name: name, args: new { logits @@ -473,7 +499,8 @@ namespace Tensorflow.Operations "Relu", name, new IntPtr[] { features as EagerTensor, - }, 1, null, + }, 1, + null, null, results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); status.Check(true); return results[0].Resolve(); @@ -492,7 +519,8 @@ namespace Tensorflow.Operations "Tanh", name, new IntPtr[] { x as EagerTensor, - }, 1, null, + }, 1, + null, null, results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); status.Check(true); return results[0].Resolve(); diff --git a/src/TensorFlowNET.Core/Operations/array_ops.cs b/src/TensorFlowNET.Core/Operations/array_ops.cs index 3a69eda5..23c6febb 100644 --- a/src/TensorFlowNET.Core/Operations/array_ops.cs +++ b/src/TensorFlowNET.Core/Operations/array_ops.cs @@ -349,7 +349,7 @@ namespace Tensorflow return fill(shape_tensor, ones, name: name); }); - public static Tensor one_hot(Tensor indices, int depth, + public static Tensor one_hot(Tensor indices, Tensor depth, Tensor on_value = null, Tensor off_value = null, TF_DataType dtype = TF_DataType.DtInvalid, diff --git a/src/TensorFlowNET.Core/Operations/clip_ops.cs b/src/TensorFlowNET.Core/Operations/clip_ops.cs index 701664f4..018949c0 100644 --- a/src/TensorFlowNET.Core/Operations/clip_ops.cs +++ b/src/TensorFlowNET.Core/Operations/clip_ops.cs @@ -25,7 +25,7 @@ namespace Tensorflow { public class clip_ops { - public static Tensor clip_by_value(Tensor t, Tensor clip_value_min, Tensor clip_value_max, string name = null) + public static Tensor clip_by_value(Tensor t, T1 clip_value_min, T2 clip_value_max, string name = null) { return tf_with(ops.name_scope(name, "clip_by_value", new { t, clip_value_min, clip_value_max }), delegate { diff --git a/src/TensorFlowNET.Core/Operations/gen_array_ops.cs b/src/TensorFlowNET.Core/Operations/gen_array_ops.cs index da6d2a37..6e17b5ae 100644 --- a/src/TensorFlowNET.Core/Operations/gen_array_ops.cs +++ b/src/TensorFlowNET.Core/Operations/gen_array_ops.cs @@ -21,6 +21,7 @@ using static Tensorflow.Binding; using Tensorflow.Eager; using System.Linq; using static Tensorflow.Binding; +using System.Security.Cryptography.X509Certificates; namespace Tensorflow { @@ -60,7 +61,8 @@ namespace Tensorflow { values as EagerTensor, axis as EagerTensor - }, 2, null, + }, 2, + null, null, results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); status.Check(true); return results[0].Resolve(); @@ -165,7 +167,8 @@ namespace Tensorflow var results = new[] { new EagerTensor() }; Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, "Pack", name, - values.Select(x => (x as EagerTensor).EagerTensorHandle).ToArray(), values.Length, + values.Select(x => (x as EagerTensor).EagerTensorHandle).ToArray(), values.Length, + wrap_tfe_src.SetOpAttrs2("axis", axis), op => wrap_tfe_src.SetOpAttrs(op, "axis", axis), results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); status.Check(true); @@ -235,7 +238,8 @@ namespace Tensorflow "Identity", name, new IntPtr[] { input as EagerTensor - }, 1, null, + }, 1, + null, null, results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); status.Check(true); return results[0].Resolve(); @@ -278,15 +282,16 @@ namespace Tensorflow { if (tf.context.executing_eagerly()) { - var results = new[] { new EagerTensor() }; + var results = EagerTensorPass.Create(); + var inputs = EagerTensorPass.From(dims, value); + Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, - "Fill", name, new IntPtr[] - { - dims as EagerTensor, - value as EagerTensor - }, 2, null, - results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); + "Fill", name, + inputs.Points, inputs.Length, + null, null, + results.Points, results.Length); status.Check(true); + return results[0].Resolve(); } @@ -311,7 +316,8 @@ namespace Tensorflow { s0 as EagerTensor, s1 as EagerTensor - }, 2, null, + }, 2, + null, null, results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); status.Check(true); return (results[0].Resolve(), results[1].Resolve()); @@ -338,7 +344,8 @@ namespace Tensorflow { tensor as EagerTensor, shape as EagerTensor - }, 2, null, + }, 2, + null, null, results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); status.Check(true); return results[0].Resolve(); @@ -381,13 +388,30 @@ namespace Tensorflow return _op.output; } - public static Tensor one_hot(Tensor indices, int depth, + public static Tensor one_hot(Tensor indices, Tensor depth, Tensor on_value = null, Tensor off_value = null, TF_DataType dtype = TF_DataType.DtInvalid, int axis = -1, string name = null) { + if (tf.context.executing_eagerly()) + { + var results = EagerTensorPass.Create(); + var inputs = EagerTensorPass.From(indices, depth, on_value, off_value); + var attrs = new object[] { "axis", axis }; + + Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, + "OneHot", name, + inputs.Points, inputs.Length, + wrap_tfe_src.SetOpAttrs2(attrs), + op => wrap_tfe_src.SetOpAttrs(op, attrs), + results.Points, results.Length); + status.Check(true); + + return results[0].Resolve(); + } + var _op = _op_def_lib._apply_op_helper("OneHot", name, new { indices, depth, on_value, off_value, axis }); return _op.outputs[0]; } @@ -407,6 +431,21 @@ namespace Tensorflow public static Tensor select(Tensor condition, Tx t, Ty e, string name = null) { + if (tf.context.executing_eagerly()) + { + var results = EagerTensorPass.Create(); + var inputs = EagerTensorPass.From(condition, t, e); + + Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, + "SelectV2", name, + inputs.Points, inputs.Length, + null, null, + results.Points, results.Length); + status.Check(true); + + return results[0].Resolve(); + } + var _op = _op_def_lib._apply_op_helper("Select", name, new { condition, t, e }); return _op.outputs[0]; } @@ -427,6 +466,7 @@ namespace Tensorflow { input as EagerTensor, }, 1, + wrap_tfe_src.SetOpAttrs2("out_type", out_type), op => wrap_tfe_src.SetOpAttrs(op, "out_type", out_type), results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); status.Check(true); @@ -486,7 +526,8 @@ namespace Tensorflow { input as EagerTensor, multiples as EagerTensor - }, 2, null, + }, 2, + null, null, results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); status.Check(true); return results[0].Resolve(); @@ -526,6 +567,14 @@ namespace Tensorflow if (tf.context.executing_eagerly()) { var results = new[] { new EagerTensor() }; + var attrs = new object[] + { + "begin_mask", begin_mask, + "end_mask", end_mask, + "ellipsis_mask", ellipsis_mask, + "new_axis_mask", new_axis_mask, + "shrink_axis_mask", shrink_axis_mask + }; Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, "StridedSlice", name, new IntPtr[] { @@ -534,12 +583,8 @@ namespace Tensorflow end as EagerTensor, strides as EagerTensor, }, 4, - op => wrap_tfe_src.SetOpAttrs(op, - "begin_mask", begin_mask, - "end_mask", end_mask, - "ellipsis_mask", ellipsis_mask, - "new_axis_mask", new_axis_mask, - "shrink_axis_mask", shrink_axis_mask), + wrap_tfe_src.SetOpAttrs2(attrs), + op => wrap_tfe_src.SetOpAttrs(op, attrs), results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); status.Check(true); return results[0].Resolve(); @@ -653,8 +698,8 @@ namespace Tensorflow { input as EagerTensor }, 1, - op => wrap_tfe_src.SetOpAttrs(op, - "squeeze_dims", axis), + wrap_tfe_src.SetOpAttrs2("squeeze_dims", axis), + op => wrap_tfe_src.SetOpAttrs(op, "squeeze_dims", axis), results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); status.Check(true); return results[0].Resolve(); @@ -689,8 +734,22 @@ namespace Tensorflow /// /// /// - public static Tensor broadcast_to(Tensor input, int[] shape, string name = null) + public static Tensor broadcast_to(Tensor input, T shape, string name = null) { + if (tf.context.executing_eagerly()) + { + var results = EagerTensorPass.Create(); + var inputs = EagerTensorPass.From(input, shape); + + Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, + "BroadcastTo", name, + inputs.Points, inputs.Length, + null, null, + results.Points, results.Length); + status.Check(true); + return results[0].Resolve(); + } + var _op = _op_def_lib._apply_op_helper("BroadcastTo", name, args: new { input, shape, name }); return _op.outputs[0]; diff --git a/src/TensorFlowNET.Core/Operations/gen_math_ops.cs b/src/TensorFlowNET.Core/Operations/gen_math_ops.cs index 21d8065d..dadd897e 100644 --- a/src/TensorFlowNET.Core/Operations/gen_math_ops.cs +++ b/src/TensorFlowNET.Core/Operations/gen_math_ops.cs @@ -48,7 +48,7 @@ namespace Tensorflow Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, "AddN", name, inputs.Select(x => (x as EagerTensor).EagerTensorHandle).ToArray(), inputs.Length, - null, + null, null, results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); status.Check(true); return results[0].Resolve(); @@ -65,7 +65,7 @@ namespace Tensorflow Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, "AddN", name, inputs, inputs.Length, - null, + null, null, results, results.Length); status.Check(true); return results[0]; @@ -80,7 +80,23 @@ namespace Tensorflow /// /// public static Tensor arg_max(Tensor input, int dimension, TF_DataType output_type = TF_DataType.TF_INT64, string name = null) - => _op_def_lib._apply_op_helper("ArgMax", name, args: new { input, dimension, output_type }).outputs[0]; + { + if (tf.context.executing_eagerly()) + { + var results = EagerTensorPass.Create(); + var inputs = EagerTensorPass.From(input, dimension); + Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, + "ArgMax", name, + inputs.Points, inputs.Length, + wrap_tfe_src.SetOpAttrs2("output_type", output_type), + op => wrap_tfe_src.SetOpAttrs(op, "output_type", output_type), + results.Points, results.Length); + status.Check(true); + return results[0].Resolve(); + } + + return _op_def_lib._apply_op_helper("ArgMax", name, args: new { input, dimension, output_type }).output; + } /// /// Returns the index with the smallest value across dimensions of a tensor. @@ -152,6 +168,7 @@ namespace Tensorflow input as EagerTensor, axis as EagerTensor }, 2, + wrap_tfe_src.SetOpAttrs2("keep_dims", keep_dims), op => wrap_tfe_src.SetOpAttrs(op, "keep_dims", keep_dims), results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); status.Check(true); @@ -198,6 +215,7 @@ namespace Tensorflow input as EagerTensor, axis as EagerTensor }, 2, + wrap_tfe_src.SetOpAttrs2("keep_dims", keep_dims), op => wrap_tfe_src.SetOpAttrs(op, "keep_dims", keep_dims), results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); status.Check(true); @@ -247,7 +265,8 @@ namespace Tensorflow { x as EagerTensor, y as EagerTensor - }, 2, null, + }, 2, + null, null, results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); status.Check(true); return results[0].Resolve(); @@ -268,7 +287,8 @@ namespace Tensorflow { x as EagerTensor, y as EagerTensor - }, 2, null, + }, 2, + null, null, results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); status.Check(true); return results[0].Resolve(); @@ -290,7 +310,8 @@ namespace Tensorflow { x as EagerTensor, y as EagerTensor - }, 2, null, + }, 2, + null, null, results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); status.Check(true); return results[0].Resolve(); @@ -324,7 +345,8 @@ namespace Tensorflow "Sin", name, new IntPtr[] { x as EagerTensor, - }, 1, null, + }, 1, + null, null, results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); status.Check(true); return results[0].Resolve(); @@ -358,7 +380,8 @@ namespace Tensorflow "Sigmoid", name, new IntPtr[] { x as EagerTensor, - }, 1, null, + }, 1, + null, null, results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); status.Check(true); return results[0].Resolve(); @@ -451,7 +474,8 @@ namespace Tensorflow "Tan", name, new IntPtr[] { x as EagerTensor, - }, 1, null, + }, 1, + null, null, results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); status.Check(true); return results[0].Resolve(); @@ -471,7 +495,8 @@ namespace Tensorflow "Tanh", name, new IntPtr[] { x as EagerTensor, - }, 1, null, + }, 1, + null, null, results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); status.Check(true); return results[0].Resolve(); @@ -499,7 +524,8 @@ namespace Tensorflow { y as EagerTensor, dy as EagerTensor - }, 2, null, + }, 2, + null, null, results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); status.Check(true); return results[0].Resolve(); @@ -550,6 +576,21 @@ namespace Tensorflow public static Tensor greater_equal(Tx x, Ty y, string name = null) { + if (tf.context.executing_eagerly()) + { + var results = EagerTensorPass.Create(); + var inputs = EagerTensorPass.From(x, y); + + Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, + "GreaterEqual", name, + inputs.Points, inputs.Length, + null, null, + results.Points, results.Length); + status.Check(true); + + return results[0].Resolve(); + } + var _op = _op_def_lib._apply_op_helper("GreaterEqual", name: name, args: new { x, y }); return _op.outputs[0]; @@ -559,14 +600,13 @@ namespace Tensorflow { if (tf.context.executing_eagerly()) { - var results = new[] { new EagerTensor() }; + var results = EagerTensorPass.Create(); + var inputs = EagerTensorPass.From(x, y); Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, - "Less", name, new IntPtr[] - { - x as EagerTensor, - y as EagerTensor - }, 2, null, - results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); + "Less", name, + inputs.Points, inputs.Length, + null, null, + results.Points, results.Length); status.Check(true); return results[0].Resolve(); } @@ -578,6 +618,19 @@ namespace Tensorflow public static Tensor less_equal(Tx x, Ty y, string name = null) { + if (tf.context.executing_eagerly()) + { + var results = EagerTensorPass.Create(); + var inputs = EagerTensorPass.From(x, y); + Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, + "LessEqual", name, + inputs.Points, inputs.Length, + null, null, + results.Points, results.Length); + status.Check(true); + return results[0].Resolve(); + } + var _op = _op_def_lib._apply_op_helper("LessEqual", name: name, args: new { x, y }); return _op.outputs[0]; @@ -641,7 +694,8 @@ namespace Tensorflow "Square", name, new IntPtr[] { x as EagerTensor, - }, 1, null, + }, 1, + null, null, results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); status.Check(true); return results[0].Resolve(); @@ -693,6 +747,21 @@ namespace Tensorflow /// A `Tensor`. Has the same type as `x`. public static Tensor log(Tensor x, string name = null) { + if (tf.context.executing_eagerly()) + { + var results = EagerTensorPass.Create(); + var inputs = EagerTensorPass.From(x); + + Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, + "Log", name, + inputs.Points, inputs.Length, + null, null, + results.Points, results.Length); + status.Check(true); + + return results[0].Resolve(); + } + var _op = _op_def_lib._apply_op_helper("Log", name, args: new { x }); return _op.outputs[0]; @@ -703,12 +772,20 @@ namespace Tensorflow if (tf.context.executing_eagerly()) { var results = new[] { new EagerTensor() }; + var attrs = new object[] + { + "DstT", DstT, + "Truncate", Truncate + }; + Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, "Cast", name, new IntPtr[] { x as EagerTensor }, 1, - op => wrap_tfe_src.SetOpAttrs(op, "DstT", DstT, "Truncate", Truncate), + wrap_tfe_src.SetOpAttrs2(attrs), + op => wrap_tfe_src.SetOpAttrs(op, attrs), results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); status.Check(true); + return results[0].Resolve(); } @@ -721,14 +798,16 @@ namespace Tensorflow { if (tf.context.executing_eagerly()) { - var results = new[] { new EagerTensor() }; + var results = EagerTensorPass.Create(); + var inputs = EagerTensorPass.From(x); + Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, - "Neg", name, new IntPtr[] - { - x as EagerTensor - }, 2, null, - results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); + "Neg", name, + inputs.Points, inputs.Length, + null, null, + results.Points, results.Length); status.Check(true); + return results[0].Resolve(); } @@ -746,7 +825,8 @@ namespace Tensorflow "Sqrt", name, new IntPtr[] { x as EagerTensor, - }, 1, null, + }, 1, + null, null, results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); status.Check(true); return results[0].Resolve(); @@ -767,7 +847,8 @@ namespace Tensorflow { x as EagerTensor, y as EagerTensor - }, 2, null, + }, 2, + null, null, results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); status.Check(true); return results[0].Resolve(); @@ -788,7 +869,8 @@ namespace Tensorflow { x as EagerTensor, y as EagerTensor - }, 2, null, + }, 2, + null, null, results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); status.Check(true); return results[0].Resolve(); @@ -816,7 +898,8 @@ namespace Tensorflow { x as EagerTensor, y as EagerTensor - }, 2, null, + }, 2, + null, null, results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); status.Check(true); return results[0].Resolve(); @@ -845,7 +928,8 @@ namespace Tensorflow { x as EagerTensor, y as EagerTensor - }, 2, null, + }, 2, + null, null, results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); status.Check(true); return results[0].Resolve(); @@ -866,7 +950,8 @@ namespace Tensorflow { y as EagerTensor, x as EagerTensor - }, 2, null, + }, 2, + null, null, results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); status.Check(true); return results[0].Resolve(); @@ -886,7 +971,8 @@ namespace Tensorflow { x as EagerTensor, y as EagerTensor - }, 2, null, + }, 2, + null, null, results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); status.Check(true); return results[0].Resolve(); @@ -907,7 +993,8 @@ namespace Tensorflow { x as EagerTensor, y as EagerTensor, - }, 2, null, + }, 2, + null, null, results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); status.Check(true); return results[0].Resolve(); @@ -935,7 +1022,8 @@ namespace Tensorflow { x as EagerTensor, y as EagerTensor - }, 2, null, + }, 2, + null, null, results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); status.Check(true); return results[0].Resolve(); @@ -948,6 +1036,21 @@ namespace Tensorflow public static Tensor reciprocal(Tensor x, string name = null) { + if (tf.context.executing_eagerly()) + { + var results = EagerTensorPass.Create(); + var inputs = EagerTensorPass.From(x); + + Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, + "Reciprocal", name, + inputs.Points, inputs.Length, + null, null, + results.Points, results.Length); + status.Check(true); + + return results[0].Resolve(); + } + var _op = _op_def_lib._apply_op_helper("Reciprocal", name, args: new { x }); return _op.outputs[0]; @@ -963,7 +1066,8 @@ namespace Tensorflow { x as EagerTensor, y as EagerTensor - }, 2, null, + }, 2, + null, null, results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); status.Check(true); return results[0].Resolve(); @@ -984,7 +1088,8 @@ namespace Tensorflow { x as EagerTensor, y as EagerTensor - }, 2, null, + }, 2, + null, null, results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); status.Check(true); return results[0].Resolve(); @@ -1008,18 +1113,19 @@ namespace Tensorflow { if (tf.context.executing_eagerly()) { - var results = new[] { new EagerTensor() }; + var results = EagerTensorPass.Create(); + var inputs = EagerTensorPass.From(a, b); + var attrs = new object[] + { + "transpose_a", transpose_a, + "transpose_b", transpose_b + }; Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, "MatMul", name, - new IntPtr[] - { - a as EagerTensor, - b as EagerTensor - }, 2, - op => wrap_tfe_src.SetOpAttrs(op, - "transpose_a", transpose_a, - "transpose_b", transpose_b), - results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); + inputs.Points, inputs.Length, + wrap_tfe_src.SetOpAttrs2(attrs), + op => wrap_tfe_src.SetOpAttrs(op, attrs), + results.Points, results.Length); status.Check(true); return results[0].Resolve(); } @@ -1073,6 +1179,21 @@ namespace Tensorflow /// public static Tensor maximum(T1 x, T2 y, string name = null) { + if (tf.context.executing_eagerly()) + { + var results = EagerTensorPass.Create(); + var inputs = EagerTensorPass.From(x, y); + + Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, + "Maximum", name, + inputs.Points, inputs.Length, + null, null, + results.Points, results.Length); + status.Check(true); + + return results[0].Resolve(); + } + var _op = _op_def_lib._apply_op_helper("Maximum", name, args: new { x, y }); return _op.outputs[0]; @@ -1080,6 +1201,21 @@ namespace Tensorflow public static Tensor minimum(T1 x, T2 y, string name = null) { + if (tf.context.executing_eagerly()) + { + var results = EagerTensorPass.Create(); + var inputs = EagerTensorPass.From(x, y); + + Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, + "Minimum", name, + inputs.Points, inputs.Length, + null, null, + results.Points, results.Length); + status.Check(true); + + return results[0].Resolve(); + } + var _op = _op_def_lib._apply_op_helper("Minimum", name, args: new { x, y }); return _op.outputs[0]; @@ -1123,7 +1259,8 @@ namespace Tensorflow { x as EagerTensor, y as EagerTensor - }, 2, null, + }, 2, + null, null, results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); status.Check(true); return results[0].Resolve(); @@ -1138,17 +1275,18 @@ namespace Tensorflow { if (tf.context.executing_eagerly()) { - var results = new[] { new EagerTensor() }; + var results = EagerTensorPass.Create(); + var inputs = EagerTensorPass.From(input, axis); + var attrs = new object[] { "keep_dims", keep_dims }; + Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, "Sum", name, - new IntPtr[] - { - input as EagerTensor, - axis as EagerTensor - }, 2, - op => wrap_tfe_src.SetOpAttrs(op, "keep_dims", keep_dims), - results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); + inputs.Points, inputs.Length, + wrap_tfe_src.SetOpAttrs2(attrs), + op => wrap_tfe_src.SetOpAttrs(op, attrs), + results.Points, results.Length); status.Check(true); + return results[0].Resolve(); } @@ -1199,7 +1337,8 @@ namespace Tensorflow start as EagerTensor, limit as EagerTensor, delta as EagerTensor - }, 3, null, + }, 3, + null, null, results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); status.Check(true); return results[0].Resolve(); diff --git a/src/TensorFlowNET.Core/Operations/gen_math_ops.eager.cs b/src/TensorFlowNET.Core/Operations/gen_math_ops.eager.cs index 80655943..973acfa5 100644 --- a/src/TensorFlowNET.Core/Operations/gen_math_ops.eager.cs +++ b/src/TensorFlowNET.Core/Operations/gen_math_ops.eager.cs @@ -11,14 +11,15 @@ namespace Tensorflow { public static EagerTensor mul(IntPtr x, IntPtr y, string name = null) { - var results = new[] { new EagerTensor() }; + var results = EagerTensorPass.Create(); Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, "Mul", name, new IntPtr[] { x, y, - }, 2, null, - results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); + }, 2, + null, null, + results.Points, results.Length); status.Check(true); return results[0].Resolve(); } diff --git a/src/TensorFlowNET.Core/Operations/gen_random_ops.cs b/src/TensorFlowNET.Core/Operations/gen_random_ops.cs index cf6a46bf..c04c9a0e 100644 --- a/src/TensorFlowNET.Core/Operations/gen_random_ops.cs +++ b/src/TensorFlowNET.Core/Operations/gen_random_ops.cs @@ -42,17 +42,20 @@ namespace Tensorflow if (tf.context.executing_eagerly()) { - var results = new[] { new EagerTensor() }; + var results = EagerTensorPass.Create(); + var attrs = new object[] + { + "seed", seed, + "seed2", seed2, + "dtype", dtype + }; + var inputs = EagerTensorPass.From(shape); Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, - "RandomStandardNormal", name, new IntPtr[] - { - shape as EagerTensor, - }, 1, - op => wrap_tfe_src.SetOpAttrs(op, - "seed", seed, - "seed2", seed2, - "dtype", dtype), - results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); + "RandomStandardNormal", name, + inputs.Points, inputs.Length, + wrap_tfe_src.SetOpAttrs2(attrs), + op => wrap_tfe_src.SetOpAttrs(op, attrs), + results.Points, results.Length); status.Check(true); return results[0].Resolve(); } @@ -148,17 +151,20 @@ namespace Tensorflow if (tf.context.executing_eagerly()) { - var results = new[] { new EagerTensor() }; + var results = EagerTensorPass.Create(); + var inputs = EagerTensorPass.From(shape); + var attrs = new object[] + { + "seed", seed, + "seed2", seed2, + "dtype", dtype + }; Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, - "TruncatedNormal", name, new IntPtr[] - { - shape as EagerTensor, - }, 1, - op => wrap_tfe_src.SetOpAttrs(op, - "seed", seed, - "seed2", seed2, - "dtype", dtype), - results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); + "TruncatedNormal", name, + inputs.Points, inputs.Length, + wrap_tfe_src.SetOpAttrs2(attrs), + op => wrap_tfe_src.SetOpAttrs(op, attrs), + results.Points, results.Length); status.Check(true); return results[0].Resolve(); } diff --git a/src/TensorFlowNET.Core/Operations/gen_resource_variable_ops.cs b/src/TensorFlowNET.Core/Operations/gen_resource_variable_ops.cs index cccf05bc..686d8917 100644 --- a/src/TensorFlowNET.Core/Operations/gen_resource_variable_ops.cs +++ b/src/TensorFlowNET.Core/Operations/gen_resource_variable_ops.cs @@ -29,15 +29,13 @@ namespace Tensorflow { if (tf.context.executing_eagerly()) { - var results = new[] { new EagerTensor() }; + var results = EagerTensorPass.Create(); + var inputs = EagerTensorPass.From(resource, value); Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, "AssignSubVariableOp", name, - new IntPtr[] - { - resource as EagerTensor, - value as EagerTensor - }, 2, null, - results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); + inputs.Points, inputs.Length, + null, null, + results.Points, results.Length); status.Check(true); return results[0].Resolve(); } @@ -56,13 +54,11 @@ namespace Tensorflow { if (tf.context.executing_eagerly()) { + var inputs = EagerTensorPass.From(resource, value); Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, "AssignAddVariableOp", name, - new IntPtr[] - { - resource as EagerTensor, - value as EagerTensor - }, 2, null, + inputs.Points, inputs.Length, + null, null, null, 0); status.Check(true); return null; @@ -75,13 +71,11 @@ namespace Tensorflow { if (tf.context.executing_eagerly()) { + var inputs = EagerTensorPass.From(resource, value); Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, "AssignVariableOp", name, - new IntPtr[] - { - resource as EagerTensor, - value as EagerTensor - }, 2, null, + inputs.Points, inputs.Length, + null, null, null, 0); status.Check(true); return null; @@ -100,7 +94,8 @@ namespace Tensorflow Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, "VarIsInitializedOp", name, new IntPtr[] { resource as EagerTensor }, - 1, null, + 1, + null, null, results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); status.Check(true); return results[0].Resolve(); @@ -125,15 +120,19 @@ namespace Tensorflow { if(tf.context.executing_eagerly()) { - var results = new[] { new EagerTensor() }; + var results = EagerTensorPass.Create(); + var attrs = new object[] + { + "container", container, + "shared_name", shared_name, + "dtype", dtype, + "shape", shape.dims + }; Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, "VarHandleOp", name, null, 0, - op => wrap_tfe_src.SetOpAttrs(op, - "container", container, - "shared_name", shared_name, - "dtype", dtype, - "shape", shape.dims), - results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); + wrap_tfe_src.SetOpAttrs2(attrs), + op => wrap_tfe_src.SetOpAttrs(op, attrs), + results.Points, results.Length); status.Check(true); return results[0].Resolve(); } @@ -163,6 +162,7 @@ namespace Tensorflow Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, "ReadVariableOp", name, new IntPtr[] { resource as EagerTensor }, 1, + wrap_tfe_src.SetOpAttrs2("dtype", dtype), op => wrap_tfe_src.SetOpAttrs(op, "dtype", dtype), results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); status.Check(true); diff --git a/src/TensorFlowNET.Core/Operations/math_ops.cs b/src/TensorFlowNET.Core/Operations/math_ops.cs index a58c90ec..37e749ec 100644 --- a/src/TensorFlowNET.Core/Operations/math_ops.cs +++ b/src/TensorFlowNET.Core/Operations/math_ops.cs @@ -348,6 +348,14 @@ namespace Tensorflow /// A 1-D Tensor, the output shape as if keepdims were set to True. public static Tensor reduced_shape(Tensor input_shape, Tensor axes) { + if(tf.context.executing_eagerly()) + { + var input_shape_val = input_shape.numpy(); + var axes_val = (int)axes.numpy(); + input_shape_val[axes_val] = 1; + return tf.constant(input_shape_val); + } + input_shape = to_int32(input_shape); axes = to_int32(axes); @@ -522,7 +530,8 @@ namespace Tensorflow public static Tensor reduce_sum(Tensor input_tensor, int axis, bool keepdims = false, string name = null) { - var m = gen_math_ops._sum(input_tensor, axis, keep_dims: keepdims, name: name); + var dims = _ReductionDims(input_tensor, axis); + var m = gen_math_ops._sum(input_tensor, dims, keep_dims: keepdims, name: name); return _may_reduce_to_scalar(keepdims, axis, m); } diff --git a/src/TensorFlowNET.Core/System/GarbageCollector.cs b/src/TensorFlowNET.Core/System/GarbageCollector.cs index 32c78d29..1ecb4f4f 100644 --- a/src/TensorFlowNET.Core/System/GarbageCollector.cs +++ b/src/TensorFlowNET.Core/System/GarbageCollector.cs @@ -54,8 +54,11 @@ namespace Tensorflow public static void Decrease(IntPtr handle) { - if (handle != IntPtr.Zero && container.ContainsKey(handle)) - container[handle].RefCounter--; + lock (locker) + { + if (handle != IntPtr.Zero && container.ContainsKey(handle)) + container[handle].RefCounter--; + } } private static void Recycle() @@ -64,7 +67,7 @@ namespace Tensorflow lock (locker) { var items = container.Values - .Where(x => x.RefCounter <= 0 && (DateTime.Now - x.LastUpdateTime).TotalMilliseconds > 100) + .Where(x => x.RefCounter <= 0 && (DateTime.Now - x.LastUpdateTime).TotalMilliseconds > 300) .ToArray(); foreach (var item in items) @@ -74,15 +77,15 @@ namespace Tensorflow switch (item.ItemType) { case GCItemType.TensorHandle: - // print($"c_api.TF_DeleteTensor({item.Handle.ToString("x16")})"); + //print($"c_api.TF_DeleteTensor({item.Handle.ToString("x16")})"); c_api.TF_DeleteTensor(item.Handle); break; case GCItemType.LocalTensorHandle: - // print($"c_api.TFE_DeleteTensorHandle({item.Handle.ToString("x16")})"); + //print($"c_api.TFE_DeleteTensorHandle({item.Handle.ToString("x16")})"); c_api.TFE_DeleteTensorHandle(item.Handle); break; case GCItemType.EagerTensorHandle: - // print($"c_api.TFE_DeleteEagerTensor({item.Handle.ToString("x16")})"); + //print($"c_api.TFE_DeleteEagerTensor({item.Handle.ToString("x16")})"); c_api.TFE_DeleteEagerTensor(item.Handle); break; default: diff --git a/src/TensorFlowNET.Core/Tensors/Tensor.cs b/src/TensorFlowNET.Core/Tensors/Tensor.cs index 89fb00d1..ef6eeee2 100644 --- a/src/TensorFlowNET.Core/Tensors/Tensor.cs +++ b/src/TensorFlowNET.Core/Tensors/Tensor.cs @@ -38,7 +38,8 @@ namespace Tensorflow _TensorLike, ITensorOrTensorArray, IPackable, - ICanBeFlattened + ICanBeFlattened, + IPointerInputs { protected int _id; private readonly Operation _op; @@ -280,6 +281,10 @@ namespace Tensorflow } else throw new InvalidOperationException($"Tensor.AllocationHandle is not null ({AllocationHandle}) but AllocationType is not matched to a C# allocation type ({AllocationType})."); } + + public virtual IntPtr ToPointer() + => _handle; + public bool IsDisposed => _disposed; // public int tensor_int_val { get; set; } diff --git a/src/TensorFlowNET.Core/Tensors/dtypes.cs b/src/TensorFlowNET.Core/Tensors/dtypes.cs index d9be6b99..6a9adcf3 100644 --- a/src/TensorFlowNET.Core/Tensors/dtypes.cs +++ b/src/TensorFlowNET.Core/Tensors/dtypes.cs @@ -199,6 +199,7 @@ namespace Tensorflow => type switch { TF_DataType.TF_STRING => "string", + TF_DataType.TF_UINT8 => "uint8", TF_DataType.TF_INT32 => "int32", TF_DataType.TF_FLOAT => "float32", TF_DataType.TF_BOOL => "bool", diff --git a/src/TensorFlowNET.Core/Training/gen_training_ops.cs b/src/TensorFlowNET.Core/Training/gen_training_ops.cs index 3a8af24e..2665cf47 100644 --- a/src/TensorFlowNET.Core/Training/gen_training_ops.cs +++ b/src/TensorFlowNET.Core/Training/gen_training_ops.cs @@ -72,6 +72,7 @@ namespace Tensorflow alpha, delta }, 3, + wrap_tfe_src.SetOpAttrs2("use_locking", use_locking), op => wrap_tfe_src.SetOpAttrs(op, "use_locking", use_locking), null, 0); status.Check(true); diff --git a/src/TensorFlowNET.Core/Util/EagerTensorPass.cs b/src/TensorFlowNET.Core/Util/EagerTensorPass.cs new file mode 100644 index 00000000..5b0bbde8 --- /dev/null +++ b/src/TensorFlowNET.Core/Util/EagerTensorPass.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Tensorflow.Eager; + +namespace Tensorflow +{ + public class EagerTensorPass : PointerInputs + { + public EagerTensorPass(params EagerTensor[] tensors) + { + data = tensors; + } + + public static EagerTensorPass Create(int count = 1) + => new EagerTensorPass(Enumerable.Range(0, count).Select(x => new EagerTensor()).ToArray()); + + public static EagerTensorPass From(params object[] objects) + => new EagerTensorPass(objects.Select(x => ops.convert_to_tensor(x) as EagerTensor).ToArray()); + } +} diff --git a/src/TensorFlowNET.Core/Util/IPointerInputs.cs b/src/TensorFlowNET.Core/Util/IPointerInputs.cs new file mode 100644 index 00000000..e0cdd0d3 --- /dev/null +++ b/src/TensorFlowNET.Core/Util/IPointerInputs.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tensorflow +{ + public interface IPointerInputs + { + public IntPtr ToPointer(); + } +} diff --git a/src/TensorFlowNET.Core/Util/PointerInputs.cs b/src/TensorFlowNET.Core/Util/PointerInputs.cs new file mode 100644 index 00000000..64d638a2 --- /dev/null +++ b/src/TensorFlowNET.Core/Util/PointerInputs.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Linq; + +namespace Tensorflow +{ + public abstract class PointerInputs + where T : IPointerInputs, new() + { + protected T[] data; + public int Length + => data.Length; + + public IntPtr[] Points + => data.Select(x => x.ToPointer()).ToArray(); + + public PointerInputs(params T[] data) + => this.data = data; + + public T this[int idx] + => data[idx]; + + public T[] Items + => data; + + public static implicit operator IntPtr[](PointerInputs inputs) + => inputs.data.Select(x => x.ToPointer()).ToArray(); + } +} diff --git a/src/TensorFlowNET.Core/Util/TensorManager.cs b/src/TensorFlowNET.Core/Util/TensorManager.cs new file mode 100644 index 00000000..6a3e518a --- /dev/null +++ b/src/TensorFlowNET.Core/Util/TensorManager.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Tensorflow.Eager; + +namespace Tensorflow +{ + public class TensorManager + { + Dictionary tensors; + public TensorManager() + { + tensors = new Dictionary(); + } + + public EagerTensor GetTensor(IntPtr handle) + { + if (tensors.ContainsKey(handle)) + return tensors[handle]; + + //return new EagerTensor(handle); + tensors[handle] = new EagerTensor(handle); + return tensors[handle]; + } + + public void Reset() + { + tensors.Clear(); + } + } +} diff --git a/src/TensorFlowNET.Core/Variables/BaseResourceVariable.cs b/src/TensorFlowNET.Core/Variables/BaseResourceVariable.cs index ac0eda44..12089b78 100644 --- a/src/TensorFlowNET.Core/Variables/BaseResourceVariable.cs +++ b/src/TensorFlowNET.Core/Variables/BaseResourceVariable.cs @@ -54,7 +54,7 @@ namespace Tensorflow public BaseResourceVariable(IntPtr handle, IntPtr tensor) { _handle = handle; - this.handle = new EagerTensor(tensor); + this.handle = tf.tensorMgr.GetTensor(tensor); } public void __init__(bool trainable = true, diff --git a/src/TensorFlowNET.Core/ops.name_scope.cs b/src/TensorFlowNET.Core/ops.name_scope.cs index 0d48cb3a..d3d78a45 100644 --- a/src/TensorFlowNET.Core/ops.name_scope.cs +++ b/src/TensorFlowNET.Core/ops.name_scope.cs @@ -15,6 +15,7 @@ ******************************************************************************/ using System.Collections.Generic; +using System.Diagnostics; using Tensorflow.Eager; using static Tensorflow.Binding; @@ -96,15 +97,18 @@ namespace Tensorflow get_default_graph()._name_stack = old_scope_name; } + [DebuggerNonUserCode] public void __exit__() { } + [DebuggerNonUserCode] public void __init__() { } + [DebuggerNonUserCode] public void __del__() { diff --git a/src/TensorFlowNET.Core/tensorflow.cs b/src/TensorFlowNET.Core/tensorflow.cs index 001d4e83..b5780917 100644 --- a/src/TensorFlowNET.Core/tensorflow.cs +++ b/src/TensorFlowNET.Core/tensorflow.cs @@ -40,11 +40,12 @@ namespace Tensorflow public TF_DataType @string = TF_DataType.TF_STRING; public Context context = new Context(new ContextOptions(), new Status()); - + public TensorManager tensorMgr; public tensorflow() { _constructThreadingObjects(); InitGradientEnvironment(); + tensorMgr = new TensorManager(); } private void InitGradientEnvironment() @@ -64,16 +65,18 @@ namespace Tensorflow ops.RegisterFromAssembly(); // ops.RegisterFromAssemblyEager(); - c_api.TFE_RegisterGradientFunction((op_name, op_inputs, op_outputs, attrs_handle, output_grads, skip_input_indices) => + c_api.TFE_RegisterGradientFunction((op_name, op_inputs, op_outputs, attrs_string, output_grads, skip_input_indices) => { /*var input_tensors = new BindingArray(op_inputs); var output_tensors = new BindingArray(op_outputs); var output_grad_tensors = new BindingArray(output_grads);*/ - var input_tensors = new BindingTensorArray(op_inputs).Data.Select(x => new EagerTensor(x)).ToArray(); - var output_tensors = new BindingTensorArray(op_outputs).Data.Select(x => new EagerTensor(x)).ToArray(); - var output_grad_tensors = new BindingTensorArray(output_grads).Data.Select(x => new EagerTensor(x)).ToArray(); + var input_tensors = new BindingTensorArray(op_inputs) + .Data.Select(x => tf.tensorMgr.GetTensor(x)).ToArray(); + var output_tensors = new BindingTensorArray(op_outputs) + .Data.Select(x => tf.tensorMgr.GetTensor(x)).ToArray(); + var output_grad_tensors = new BindingTensorArray(output_grads) + .Data.Select(x => tf.tensorMgr.GetTensor(x)).ToArray(); var skip_input_indices_param = new BindingArray(skip_input_indices); - var attrs = new BindingArray(attrs_handle);//.Data.Select(x => *(int*)x).ToArray(); var gradients = ops.gradientFunctions[op_name](new EagerOperation { @@ -85,7 +88,7 @@ namespace Tensorflow Outputs = output_tensors, // OutputHandles = output_tensors.Data, SkipInputIndicesArray = skip_input_indices_param, - AttrsArray = attrs + AttrsArray = attrs_string.Split(',') }, output_grad_tensors); var gradients_handles = gradients.Select(x => x == null ? IntPtr.Zero : (x as EagerTensor).EagerTensorHandle).ToArray();