| @@ -1,42 +0,0 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Text; | |||
| using static Tensorflow.Binding; | |||
| namespace Tensorflow | |||
| { | |||
| class MemoryLeakTesting | |||
| { | |||
| public void WarmUp() | |||
| { | |||
| print(tf.VERSION); | |||
| } | |||
| /// <summary> | |||
| /// | |||
| /// </summary> | |||
| public void TensorCreation() | |||
| { | |||
| int total = 1 * 1000 * 1000; | |||
| for (int i = 0; i < total; i++) | |||
| { | |||
| /*var const1 = new Tensor(new float[,] | |||
| { | |||
| { 3.0f, 1.0f }, | |||
| { 1.0f, 2.0f } | |||
| }); | |||
| const1.Dispose();*/ | |||
| var tensor = new EagerTensorV2(new float[,] | |||
| { | |||
| { 3.0f, 1.0f }, | |||
| { 1.0f, 2.0f } | |||
| }); | |||
| tensor.Dispose(); | |||
| } | |||
| GC.Collect(); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,51 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Diagnostics; | |||
| using System.Text; | |||
| using static Tensorflow.Binding; | |||
| namespace Tensorflow | |||
| { | |||
| public class MemoryMonitor | |||
| { | |||
| public void WarmUp() | |||
| { | |||
| print(tf.VERSION); | |||
| } | |||
| public void Execute(int epoch, int iterate, Action<int> process) | |||
| { | |||
| /*GC.Collect(); | |||
| GC.WaitForPendingFinalizers(); | |||
| GC.Collect();*/ | |||
| print($"{process.Method.Name} started..."); | |||
| for (int i = 0; i < epoch; i++) | |||
| { | |||
| var initialMemory = Process.GetCurrentProcess().PrivateMemorySize64;// GC.GetTotalMemory(true); | |||
| process(iterate); | |||
| var finalMemory = Process.GetCurrentProcess().PrivateMemorySize64; //GC.GetTotalMemory(true); | |||
| print($"Epoch {i}: {Format(finalMemory - initialMemory)}."); | |||
| } | |||
| GC.Collect(); | |||
| GC.WaitForPendingFinalizers(); | |||
| GC.Collect(); | |||
| print($"Total {process.Method.Name} usage {Format(Process.GetCurrentProcess().PrivateMemorySize64)}"); | |||
| } | |||
| private string Format(long usage) | |||
| { | |||
| if (usage < 0) | |||
| return $"-{Format(0 - usage)}"; | |||
| if (usage <= 1024 && usage >= 0) | |||
| return $"{usage} Bytes"; | |||
| else if (usage > 1024 && usage <= 1024 * 1024) | |||
| return $"{usage / 1024} KB"; | |||
| else | |||
| return $"{usage / 1024 / 1024} MB"; | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,55 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Text; | |||
| using static Tensorflow.Binding; | |||
| namespace Tensorflow | |||
| { | |||
| class MemoryTestingCases | |||
| { | |||
| /// <summary> | |||
| /// | |||
| /// </summary> | |||
| public Action<int> Constant | |||
| => (iterate) => | |||
| { | |||
| for (int i = 0; i < iterate; i++) | |||
| { | |||
| var tensor = tf.constant(3112.0f); | |||
| } | |||
| }; | |||
| public Action<int> Variable | |||
| => (iterate) => | |||
| { | |||
| for (int i = 0; i < iterate; i++) | |||
| { | |||
| var tensor = tf.Variable(3112.0f); | |||
| } | |||
| }; | |||
| public Action<int> MathAdd | |||
| => (iterate) => | |||
| { | |||
| var x = tf.constant(3112.0f); | |||
| var y = tf.constant(3112.0f); | |||
| for (int i = 0; i < iterate; i++) | |||
| { | |||
| var z = x + y; | |||
| } | |||
| }; | |||
| public Action<int> Gradient | |||
| => (iterate) => | |||
| { | |||
| for(int i = 0; i< iterate; i++) | |||
| { | |||
| var w = tf.constant(3112.0f); | |||
| using var tape = tf.GradientTape(); | |||
| tape.watch(w); | |||
| var loss = w * w; | |||
| var grad = tape.gradient(loss, w); | |||
| } | |||
| }; | |||
| } | |||
| } | |||
| @@ -7,11 +7,24 @@ namespace Tensorflow | |||
| static void Main(string[] args) | |||
| { | |||
| // boot .net core 10.5M. | |||
| var memoryTest = new MemoryLeakTesting(); | |||
| var mm = new MemoryMonitor(); | |||
| // warm up tensorflow.net 28.5M. | |||
| memoryTest.WarmUp(); | |||
| // 1 million float tensor 34.5M. | |||
| memoryTest.TensorCreation(); | |||
| mm.WarmUp(); | |||
| var cases = new MemoryTestingCases(); | |||
| int batchSize = 1000; | |||
| // 1 million float tensor 58.5M. | |||
| // mm.Execute(10, 100 * batchSize, cases.Constant); | |||
| // 100K float variable 80.5M. | |||
| //mm.Execute(10, 10 * batchSize, cases.Variable); | |||
| // 1 million math add 36.5M. | |||
| // mm.Execute(10, 100 * batchSize, cases.MathAdd); | |||
| // 100K gradient 211M. | |||
| mm.Execute(100, 1 * batchSize, cases.Gradient); | |||
| Console.WriteLine("Finished."); | |||
| Console.ReadLine(); | |||
| @@ -43,7 +43,7 @@ namespace Tensorflow | |||
| /// </summary> | |||
| public partial class c_api | |||
| { | |||
| public const string TensorFlowLibName = "tensorflow"; | |||
| public const string TensorFlowLibName = @"D:\SciSharp\tensorflow-google\bazel-bin\tensorflow\tensorflow.dll"; | |||
| public static string StringPiece(IntPtr handle) | |||
| { | |||
| @@ -7,8 +7,10 @@ namespace Tensorflow.Eager | |||
| public class EagerOperation : Operation | |||
| { | |||
| public int NumInputs; | |||
| public IntPtr[] InputHandles { get; set; } | |||
| public Tensor[] Inputs { get; set; } | |||
| public int NumOutputs; | |||
| public IntPtr[] OutputHandles { get; set; } | |||
| public Tensor[] Outputs { get; set; } | |||
| public int[] SkipInputIndices { get; set; } | |||
| @@ -2,47 +2,66 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Text; | |||
| using static Tensorflow.Binding; | |||
| using Tensorflow.Gradients; | |||
| namespace Tensorflow.Eager | |||
| { | |||
| public partial class EagerTensor : Tensor | |||
| { | |||
| public EagerTensor(IntPtr handle) : base(handle) | |||
| public EagerTensor() : base(IntPtr.Zero) | |||
| { | |||
| EagerTensorHandle = handle; | |||
| tfe_tensor_handle = c_api.EagerTensor_Handle(handle); | |||
| _handle = c_api.TFE_TensorHandleResolve(tfe_tensor_handle, status); | |||
| } | |||
| /*public EagerTensor(int value, string device_name) : base(value) | |||
| { | |||
| tfe_tensor_handle = c_api.TFE_NewTensorHandle(_handle, status); | |||
| EagerTensorHandle = c_api.TFE_EagerTensorFromHandle(tf.context, tfe_tensor_handle); | |||
| EagerTensorHandle = c_api.TFE_NewEagerTensor(); | |||
| // _id = c_api.TFE_EagerTensorId(EagerTensorHandle); | |||
| // print($"new EagerTensorHandle {EagerTensorHandle.ToString("x16")} {Id}"); | |||
| } | |||
| public EagerTensor(long value, string device_name) : base(value) | |||
| public EagerTensor(IntPtr handle) : base(IntPtr.Zero) | |||
| { | |||
| tfe_tensor_handle = c_api.TFE_NewTensorHandle(_handle, status); | |||
| EagerTensorHandle = c_api.TFE_EagerTensorFromHandle(tf.context, tfe_tensor_handle); | |||
| EagerTensorHandle = handle; | |||
| Resolve(); | |||
| // print($"new EagerTensorHandle {EagerTensorHandle.ToString("x16")} {Id}"); | |||
| } | |||
| public EagerTensor(float value, string device_name) : base(value) | |||
| { | |||
| tfe_tensor_handle = c_api.TFE_NewTensorHandle(_handle, status); | |||
| EagerTensorHandle = c_api.TFE_EagerTensorFromHandle(tf.context, tfe_tensor_handle); | |||
| }*/ | |||
| public EagerTensor(string value, string device_name) : base(value) | |||
| { | |||
| EagerTensorHandle = c_api.TFE_NewEagerTensor(); | |||
| tfe_tensor_handle = c_api.TFE_NewTensorHandle(_handle, status); | |||
| EagerTensorHandle = c_api.TFE_EagerTensorFromHandle(tf.context, tfe_tensor_handle); | |||
| c_api.TFE_SetEagerTensorHandle(EagerTensorHandle, tfe_tensor_handle); | |||
| Resolve(); | |||
| // print($"new EagerTensorHandle {EagerTensorHandle.ToString("x16")} {Id}"); | |||
| } | |||
| public EagerTensor(NDArray value, string device_name) : base(value) | |||
| { | |||
| EagerTensorHandle = c_api.TFE_NewEagerTensor(); | |||
| tfe_tensor_handle = c_api.TFE_NewTensorHandle(_handle, status); | |||
| EagerTensorHandle = c_api.TFE_EagerTensorFromHandle(tf.context, tfe_tensor_handle); | |||
| c_api.TFE_SetEagerTensorHandle(EagerTensorHandle, tfe_tensor_handle); | |||
| Resolve(); | |||
| // print($"new EagerTensorHandle {EagerTensorHandle.ToString("x16")} {Id}"); | |||
| } | |||
| public EagerTensor Resolve() | |||
| { | |||
| if (tfe_tensor_handle == IntPtr.Zero) | |||
| tfe_tensor_handle = c_api.TFE_EagerTensorHandle(EagerTensorHandle); | |||
| if (_handle == IntPtr.Zero) | |||
| _handle = c_api.TFE_TensorHandleResolve(tfe_tensor_handle, status); | |||
| _id = c_api.TFE_EagerTensorId(EagerTensorHandle); | |||
| GarbageCollector.Increase(_handle, GCItemType.TensorHandle); | |||
| GarbageCollector.Increase(tfe_tensor_handle, GCItemType.LocalTensorHandle); | |||
| GarbageCollector.Increase(EagerTensorHandle, GCItemType.EagerTensorHandle); | |||
| return this; | |||
| } | |||
| protected override void DisposeUnmanagedResources(IntPtr handle) | |||
| { | |||
| GarbageCollector.Decrease(_handle); | |||
| GarbageCollector.Decrease(tfe_tensor_handle); | |||
| GarbageCollector.Decrease(EagerTensorHandle); | |||
| } | |||
| } | |||
| } | |||
| @@ -13,6 +13,25 @@ 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 static int GetRank(IntPtr handle) | |||
| { | |||
| var tfe_tensor_handle = c_api.TFE_EagerTensorHandle(handle); | |||
| using var status = new Status(); | |||
| return c_api.TFE_TensorHandleNumDims(tfe_tensor_handle, status); | |||
| } | |||
| public static int[] GetDims(IntPtr handle) | |||
| { | |||
| var tfe_tensor_handle = c_api.TFE_EagerTensorHandle(handle); | |||
| using var status = new Status(); | |||
| var dims = new int[c_api.TFE_TensorHandleNumDims(tfe_tensor_handle, status)]; | |||
| for (int i = 0; i < dims.Length; i++) | |||
| dims[i] = c_api.TFE_TensorHandleDim(tfe_tensor_handle, i, status); | |||
| return dims; | |||
| } | |||
| public override string ToString() | |||
| { | |||
| switch (rank) | |||
| @@ -33,18 +33,17 @@ namespace Tensorflow.Eager | |||
| { | |||
| ctx.ensure_initialized(); | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_QuickExecute(ctx, | |||
| var results = Enumerable.Range(0, num_outputs).Select(x => new EagerTensor()).ToArray(); | |||
| Status status = c_api.TFE_QuickExecute(ctx, | |||
| ctx.device_name, | |||
| op_name, | |||
| inputs.Select(x => x.EagerTensorHandle).ToArray(), | |||
| inputs.Length, | |||
| op => wrap_tfe_src.SetOpAttrs(op, attrs), | |||
| status); | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return results.Data().Select(x => new EagerTensor(x)).ToArray(); | |||
| return results.Select(x => x.Resolve()).ToArray(); | |||
| } | |||
| public (TF_DataType, EagerTensor[]) args_to_matching_eager(Context ctx, TF_DataType default_dtype = TF_DataType.DtInvalid, object[] args = null) | |||
| @@ -11,18 +11,28 @@ namespace Tensorflow | |||
| public static extern void TFE_RegisterGradientFunction(gradient_function_callback gradientFunctionCallback, | |||
| delete_backward_function_callback deleteBackwardFunctionCallback); | |||
| /// <summary> | |||
| /// | |||
| /// </summary> | |||
| /// <param name="op_name"></param> | |||
| /// <param name="op_inputs"></param> | |||
| /// <param name="op_outputs"></param> | |||
| /// <param name="num_attrs"></param> | |||
| /// <param name="output_grads">previous node ouput</param> | |||
| /// <param name="skip_input_indices"></param> | |||
| /// <returns></returns> | |||
| [UnmanagedFunctionPointer(CallingConvention.StdCall)] | |||
| public delegate IntPtr gradient_function_callback(string op_name, | |||
| BindingArray op_inputs, | |||
| BindingArray op_outputs, | |||
| IntPtr op_inputs, | |||
| IntPtr op_outputs, | |||
| int num_attrs, | |||
| BindingArray output_grads, | |||
| BindingArray skip_input_indices); | |||
| IntPtr output_grads, | |||
| IntPtr skip_input_indices); | |||
| [UnmanagedFunctionPointer(CallingConvention.StdCall)] | |||
| public delegate void delete_backward_function_callback(string op_name, | |||
| BindingArray op_inputs, | |||
| BindingArray op_outputs); | |||
| IntPtr op_inputs, | |||
| IntPtr op_outputs); | |||
| [DllImport(TensorFlowLibName)] | |||
| public static extern IntPtr TFE_WrapGradientResult(IntPtr[] gradients, int num_gradients); | |||
| @@ -32,7 +42,7 @@ namespace Tensorflow | |||
| [UnmanagedFunctionPointer(CallingConvention.StdCall)] | |||
| public delegate IntPtr VSpace_callback_Ones(long[] shape, int dims, TF_DataType dtype); | |||
| [UnmanagedFunctionPointer(CallingConvention.StdCall)] | |||
| public delegate IntPtr VSpace_callback_AggregateGrads(BindingArray gradients); | |||
| public delegate IntPtr VSpace_callback_AggregateGrads(TF_BindingArray gradients); | |||
| [DllImport(TensorFlowLibName)] | |||
| public static extern void TFE_RegisterVSpace(IntPtr vspace); | |||
| @@ -217,10 +227,16 @@ namespace Tensorflow | |||
| public static extern TFE_TensorHandle TFE_NewTensorHandle(IntPtr t, IntPtr status); | |||
| [DllImport(TensorFlowLibName)] | |||
| public static extern IntPtr EagerTensor_Handle(IntPtr t); | |||
| public static extern IntPtr TFE_EagerTensorHandle(IntPtr t); | |||
| [DllImport(TensorFlowLibName)] | |||
| public static extern IntPtr TFE_EagerTensorFromHandle(IntPtr ctx, IntPtr h); | |||
| public static extern int TFE_EagerTensorId(IntPtr t); | |||
| [DllImport(TensorFlowLibName)] | |||
| public static extern IntPtr TFE_NewEagerTensor(); | |||
| [DllImport(TensorFlowLibName)] | |||
| public static extern void TFE_SetEagerTensorHandle(IntPtr tensor, IntPtr handle); | |||
| /// <summary> | |||
| /// Sets the default execution mode (sync/async). Note that this can be | |||
| @@ -260,6 +276,9 @@ namespace Tensorflow | |||
| [DllImport(TensorFlowLibName)] | |||
| public static extern int TFE_TensorHandleNumDims(IntPtr h, IntPtr status); | |||
| [DllImport(TensorFlowLibName)] | |||
| public static extern int TFE_TensorHandleDim(IntPtr h, int dim, IntPtr status); | |||
| /// <summary> | |||
| /// Returns the device of the operation that produced `h`. If `h` was produced by | |||
| /// a copy, returns the destination device of the copy. Note that the returned | |||
| @@ -304,7 +323,13 @@ namespace Tensorflow | |||
| /// <param name="h">TFE_TensorHandle*</param> | |||
| [DllImport(TensorFlowLibName)] | |||
| public static extern void TFE_DeleteEagerTensor(IntPtr h); | |||
| [DllImport(TensorFlowLibName)] | |||
| public static extern void TF_DeleteBindingArray(IntPtr h); | |||
| [DllImport(TensorFlowLibName)] | |||
| public static extern void TFE_DeleteBindingTensorArray(IntPtr h); | |||
| /// <summary> | |||
| /// Creates a new eager Executor. Nodes in one executor are guaranteed to be | |||
| /// executed in sequence. Assigning nodes to different executors allows executing | |||
| @@ -372,10 +397,11 @@ namespace Tensorflow | |||
| string device_name, | |||
| string op_name, | |||
| string name, | |||
| IntPtr[] args, | |||
| IntPtr[] inputs, | |||
| int input_size, | |||
| TFE_FastPathExecute_SetOpAttrs set_op_attrs, | |||
| IntPtr status); | |||
| IntPtr[] outputs, | |||
| int output_size); | |||
| [UnmanagedFunctionPointer(CallingConvention.StdCall)] | |||
| public delegate void TFE_FastPathExecute_SetOpAttrs(IntPtr op); | |||
| @@ -386,13 +412,8 @@ namespace Tensorflow | |||
| IntPtr[] inputs, | |||
| int input_size, | |||
| TFE_FastPathExecute_SetOpAttrs set_op_attrs, | |||
| IntPtr status); | |||
| [DllImport(TensorFlowLibName)] | |||
| public static extern IntPtr TFE_QuickExecute1( | |||
| string op_name, | |||
| int input_size, | |||
| IntPtr status); | |||
| IntPtr[] outputs, | |||
| int output_size); | |||
| [DllImport(TensorFlowLibName)] | |||
| public static extern IntPtr TFE_TapeSetNew(bool persistent, bool watch_accessed_variables); | |||
| @@ -415,7 +436,7 @@ namespace Tensorflow | |||
| [DllImport(TensorFlowLibName)] | |||
| public static extern IntPtr TFE_TapeGradient(IntPtr tape, | |||
| IntPtr[] target, int target_size, | |||
| IntPtr[] sources, int source_size, | |||
| IntPtr status); | |||
| IntPtr[] sources, int source_size, | |||
| IntPtr[] outputs, int output_size); | |||
| } | |||
| } | |||
| @@ -2,6 +2,7 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Runtime.InteropServices; | |||
| using System.Text; | |||
| using Tensorflow.Eager; | |||
| using static Tensorflow.Binding; | |||
| @@ -21,7 +22,8 @@ namespace Tensorflow.Gradients | |||
| /// </summary> | |||
| public class GradientTape : IDisposable | |||
| { | |||
| bool _recording; | |||
| static bool _recording; | |||
| public static bool Recording => _recording; | |||
| bool _persistent; | |||
| bool _watch_accessed_variables; | |||
| ResourceVariable[] _watched_variables; | |||
| @@ -76,13 +78,13 @@ namespace Tensorflow.Gradients | |||
| _pop_tape(); | |||
| } | |||
| using var status = new Status(); | |||
| var et = c_api.TFE_TapeGradient(_tape, | |||
| var results = new[] { new EagerTensor() }; | |||
| Status status = c_api.TFE_TapeGradient(_tape, | |||
| new [] { (target as EagerTensor).EagerTensorHandle }, 1, | |||
| new [] { (source as EagerTensor).EagerTensorHandle }, 1, | |||
| status); | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return new EagerTensor(et); | |||
| return results[0]; | |||
| } | |||
| public unsafe (Tensor, Tensor) gradient(Tensor target, (ResourceVariable, ResourceVariable) sources) | |||
| @@ -93,8 +95,8 @@ namespace Tensorflow.Gradients | |||
| _pop_tape(); | |||
| } | |||
| using var status = new Status(); | |||
| BindingArray result_handle = c_api.TFE_TapeGradient(_tape, | |||
| var results = new[] { new EagerTensor(), new EagerTensor() }; | |||
| Status status = c_api.TFE_TapeGradient(_tape, | |||
| new IntPtr[] | |||
| { | |||
| target as EagerTensor | |||
| @@ -104,12 +106,9 @@ namespace Tensorflow.Gradients | |||
| (sources.Item1.Handle as EagerTensor).EagerTensorHandle, | |||
| (sources.Item2.Handle as EagerTensor).EagerTensorHandle | |||
| }, 2, | |||
| status); | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| var results = result_handle.Data().Select(x => new EagerTensor(x)).ToArray(); | |||
| if (!_persistent) | |||
| { | |||
| // Keep track of watched variables before setting tape to None | |||
| @@ -0,0 +1,30 @@ | |||
| /***************************************************************************** | |||
| Copyright 2018 The TensorFlow.NET Authors. All Rights Reserved. | |||
| Licensed under the Apache License, Version 2.0 (the "License"); | |||
| you may not use this file except in compliance with the License. | |||
| You may obtain a copy of the License at | |||
| http://www.apache.org/licenses/LICENSE-2.0 | |||
| Unless required by applicable law or agreed to in writing, software | |||
| distributed under the License is distributed on an "AS IS" BASIS, | |||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| See the License for the specific language governing permissions and | |||
| limitations under the License. | |||
| ******************************************************************************/ | |||
| using System; | |||
| namespace Tensorflow.Gradients | |||
| { | |||
| public class RegisterGradientEager : Attribute | |||
| { | |||
| public string Name { get; set; } | |||
| public RegisterGradientEager(string name) | |||
| { | |||
| Name = name; | |||
| } | |||
| } | |||
| } | |||
| @@ -34,7 +34,7 @@ namespace Tensorflow.Gradients | |||
| public unsafe ResourceVariable[] watched_variables() | |||
| { | |||
| BindingArray result = c_api.TFE_TapeWatchedVariables(_handle); | |||
| var variables = result.Data().Select(x => | |||
| var variables = result.Data.Select(x => | |||
| { | |||
| var tensor = c_api.ResourceVariable_Handle(x); | |||
| return new ResourceVariable(x, tensor); | |||
| @@ -0,0 +1,74 @@ | |||
| /***************************************************************************** | |||
| Copyright 2018 The TensorFlow.NET Authors. All Rights Reserved. | |||
| Licensed under the Apache License, Version 2.0 (the "License"); | |||
| you may not use this file except in compliance with the License. | |||
| You may obtain a copy of the License at | |||
| http://www.apache.org/licenses/LICENSE-2.0 | |||
| Unless required by applicable law or agreed to in writing, software | |||
| distributed under the License is distributed on an "AS IS" BASIS, | |||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| See the License for the specific language governing permissions and | |||
| limitations under the License. | |||
| ******************************************************************************/ | |||
| using NumSharp; | |||
| using System; | |||
| using System.Linq; | |||
| using Tensorflow.Eager; | |||
| using Tensorflow.Operations; | |||
| using static Tensorflow.Binding; | |||
| namespace Tensorflow.Gradients | |||
| { | |||
| /// <summary> | |||
| /// Gradients for operators defined in math_ops.py. | |||
| /// </summary> | |||
| [RegisterGradientEager("math_grad")] | |||
| public class math_grad_eager | |||
| { | |||
| [RegisterGradientEager("Mul")] | |||
| public static EagerTensor[] _MulGrad(EagerOperation op, IntPtr[] grads) | |||
| { | |||
| var x = op.InputHandles[0]; | |||
| var y = op.InputHandles[1]; | |||
| var grad = grads[0]; | |||
| if (op.SkipInputIndices.Contains(1) && | |||
| EagerTensor.GetRank(grad) == 0) | |||
| { | |||
| return new EagerTensor[] | |||
| { | |||
| null,//gen_math_ops.mul(grad, math_ops.conj(y)), | |||
| null | |||
| }; | |||
| } | |||
| if (_ShapesFullySpecifiedAndEqual(x, y, grad)) | |||
| { | |||
| return new EagerTensor[] | |||
| { | |||
| gen_math_ops.mul(grad, y), | |||
| gen_math_ops.mul(grad, x) | |||
| }; | |||
| } | |||
| throw new NotImplementedException(""); | |||
| } | |||
| public static bool _ShapesFullySpecifiedAndEqual(IntPtr x, IntPtr y, IntPtr grad) | |||
| { | |||
| var x_shape = EagerTensor.GetDims(x); | |||
| var y_shape = EagerTensor.GetDims(y); | |||
| var grad_shape = EagerTensor.GetDims(grad); | |||
| return x_shape != null && | |||
| y_shape != null && | |||
| Enumerable.SequenceEqual(x_shape, y_shape) && | |||
| Enumerable.SequenceEqual(y_shape, grad_shape) && | |||
| !x_shape.Contains(-1); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,101 @@ | |||
| /***************************************************************************** | |||
| Copyright 2018 The TensorFlow.NET Authors. All Rights Reserved. | |||
| Licensed under the Apache License, Version 2.0 (the "License"); | |||
| you may not use this file except in compliance with the License. | |||
| You may obtain a copy of the License at | |||
| http://www.apache.org/licenses/LICENSE-2.0 | |||
| Unless required by applicable law or agreed to in writing, software | |||
| distributed under the License is distributed on an "AS IS" BASIS, | |||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| See the License for the specific language governing permissions and | |||
| limitations under the License. | |||
| ******************************************************************************/ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Reflection; | |||
| using Tensorflow.Eager; | |||
| using Tensorflow.Gradients; | |||
| namespace Tensorflow | |||
| { | |||
| public partial class ops | |||
| { | |||
| public static Dictionary<string, Func<EagerOperation, IntPtr[], EagerTensor[]>> gradientFunctionsEager = null; | |||
| public static void RegisterFromAssemblyEager() | |||
| { | |||
| if (gradientFunctionsEager == null) | |||
| { | |||
| gradientFunctionsEager = new Dictionary<string, Func<EagerOperation, IntPtr[], EagerTensor[]>>(); | |||
| var gradGroups = Assembly.GetExecutingAssembly() | |||
| .GetTypes() | |||
| .Where(x => x.GetCustomAttribute<RegisterGradientEager>() != null) | |||
| .ToArray(); | |||
| foreach (var g in gradGroups) | |||
| { | |||
| var methods = g.GetMethods() | |||
| .Where(x => x.GetCustomAttribute<RegisterGradientEager>() != null) | |||
| .ToArray(); | |||
| foreach (var m in methods) | |||
| { | |||
| RegisterGradientFunctionEager(m.GetCustomAttribute<RegisterGradientEager>().Name, | |||
| (oper, out_grads) => | |||
| g.InvokeMember(m.Name, | |||
| BindingFlags.InvokeMethod, | |||
| null, | |||
| null, | |||
| args: new object[] { oper, out_grads }) as EagerTensor[] | |||
| ); | |||
| } | |||
| // REGISTER_NO_GRADIENT_OP | |||
| methods = g.GetMethods() | |||
| .Where(x => x.GetCustomAttribute<RegisterNoGradient>() != null) | |||
| .ToArray(); | |||
| foreach (var m in methods) | |||
| RegisterNoGradientFunctionEager(m.GetCustomAttribute<RegisterNoGradient>().Name); | |||
| } | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// Regiter new gradient function | |||
| /// </summary> | |||
| /// <param name="name">operation type</param> | |||
| /// <param name="func">function delegate</param> | |||
| public static void RegisterGradientFunctionEager(string name, Func<EagerOperation, IntPtr[], EagerTensor[]> func) | |||
| { | |||
| RegisterFromAssemblyEager(); | |||
| gradientFunctionsEager[name] = func; | |||
| } | |||
| public static void RegisterNoGradientFunctionEager(string name) | |||
| { | |||
| RegisterFromAssemblyEager(); | |||
| gradientFunctionsEager[name] = null; | |||
| } | |||
| public static Func<EagerOperation, IntPtr[], EagerTensor[]> get_gradient_function_eager(EagerOperation op) | |||
| { | |||
| if (op.inputs == null) return null; | |||
| RegisterFromAssemblyEager(); | |||
| if (!gradientFunctionsEager.ContainsKey(op.type)) | |||
| throw new LookupError($"can't get graident function through get_gradient_function {op.type}"); | |||
| return gradientFunctionsEager[op.type]; | |||
| } | |||
| } | |||
| } | |||
| @@ -15,6 +15,7 @@ | |||
| ******************************************************************************/ | |||
| using System; | |||
| using System.Linq; | |||
| using Tensorflow.Eager; | |||
| using static Tensorflow.Binding; | |||
| @@ -467,14 +468,15 @@ namespace Tensorflow.Operations | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor() }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "Relu", name, new IntPtr[] | |||
| { | |||
| features as EagerTensor, | |||
| }, 1, null, status); | |||
| }, 1, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return new EagerTensor(results[0]); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("Relu", name: name, args: new { features }); | |||
| @@ -485,14 +487,15 @@ namespace Tensorflow.Operations | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor() }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "Tanh", name, new IntPtr[] | |||
| { | |||
| x as EagerTensor, | |||
| }, 1, null, status); | |||
| }, 1, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return new EagerTensor(results[0]); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("Tanh", name: name, args: new { x }); | |||
| @@ -54,15 +54,16 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor() }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "ConcatV2", name, new IntPtr[] | |||
| { | |||
| values as EagerTensor, | |||
| axis as EagerTensor | |||
| }, 2, null, status); | |||
| }, 2, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return new EagerTensor(results[0]); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("ConcatV2", name: name, args: new { values, axis }); | |||
| @@ -161,14 +162,14 @@ namespace Tensorflow | |||
| { | |||
| if(tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| 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, | |||
| op => wrap_tfe_src.SetOpAttrs(op, "axis", axis), | |||
| status); | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return new EagerTensor(results[0]); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("Pack", name: name, args: new { values, axis }); | |||
| @@ -229,14 +230,15 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor() }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "Identity", name, new IntPtr[] | |||
| { | |||
| input as EagerTensor | |||
| }, 1, null, status); | |||
| }, 1, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return new EagerTensor(results[0]); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("Identity", name, new { input }); | |||
| @@ -276,15 +278,16 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor() }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "Fill", name, new IntPtr[] | |||
| { | |||
| dims as EagerTensor, | |||
| value as EagerTensor | |||
| }, 2, null, status); | |||
| }, 2, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return new EagerTensor(results[0]); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("Fill", name, new { dims, value }); | |||
| @@ -302,15 +305,16 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor(), new EagerTensor() }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "BroadcastGradientArgs", name, new IntPtr[] | |||
| { | |||
| s0 as EagerTensor, | |||
| s1 as EagerTensor | |||
| }, 2, null, status); | |||
| }, 2, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return (new EagerTensor(results[0]), new EagerTensor(results[1])); | |||
| return (results[0], results[1]); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("BroadcastGradientArgs", name, new { s0, s1 }); | |||
| @@ -328,15 +332,16 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor() }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "Reshape", name, new IntPtr[] | |||
| { | |||
| tensor as EagerTensor, | |||
| shape as EagerTensor | |||
| }, 2, null, status); | |||
| }, 2, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return new EagerTensor(results[0]); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("Reshape", name, new { tensor, shape }); | |||
| @@ -416,16 +421,16 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor() }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "Shape", name, new IntPtr[] | |||
| { | |||
| input as EagerTensor, | |||
| }, 1, | |||
| op => wrap_tfe_src.SetOpAttrs(op, "out_type", out_type), | |||
| status); | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return new EagerTensor(results[0]); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("Shape", name, new { input, out_type }); | |||
| @@ -475,15 +480,16 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor() }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "Tile", name, new IntPtr[] | |||
| { | |||
| input as EagerTensor, | |||
| multiples as EagerTensor | |||
| }, 2, null, status); | |||
| }, 2, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return new EagerTensor(results[0]); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("Tile", name, new { input, multiples }); | |||
| @@ -519,8 +525,8 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor() }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "StridedSlice", name, new IntPtr[] | |||
| { | |||
| input as EagerTensor, | |||
| @@ -533,10 +539,10 @@ namespace Tensorflow | |||
| "end_mask", end_mask, | |||
| "ellipsis_mask", ellipsis_mask, | |||
| "new_axis_mask", new_axis_mask, | |||
| "shrink_axis_mask", shrink_axis_mask), | |||
| status); | |||
| "shrink_axis_mask", shrink_axis_mask), | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return new EagerTensor(results[0]); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("StridedSlice", name, new | |||
| @@ -16,12 +16,13 @@ | |||
| using System; | |||
| using System.Linq; | |||
| using System.Runtime.InteropServices; | |||
| using Tensorflow.Eager; | |||
| using static Tensorflow.Binding; | |||
| namespace Tensorflow | |||
| { | |||
| public static class gen_math_ops | |||
| public static partial class gen_math_ops | |||
| { | |||
| public static OpDefLibrary _op_def_lib = new OpDefLibrary(); | |||
| public static Execute _execute = new Execute(); | |||
| @@ -43,14 +44,14 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor() }; | |||
| 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, | |||
| status); | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return new EagerTensor(results[0]); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("AddN", name, args: new { inputs }); | |||
| @@ -58,6 +59,18 @@ namespace Tensorflow | |||
| return _op.outputs[0]; | |||
| } | |||
| public static EagerTensor add_n(IntPtr[] inputs, string name = null) | |||
| { | |||
| var results = new[] { new EagerTensor() }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "AddN", name, | |||
| inputs, inputs.Length, | |||
| null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| } | |||
| /// <summary> | |||
| /// Returns the index with the largest value across dimensions of a tensor. | |||
| /// </summary> | |||
| @@ -131,8 +144,8 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor() }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "Mean", name, | |||
| new IntPtr[] | |||
| { | |||
| @@ -140,9 +153,9 @@ namespace Tensorflow | |||
| axis as EagerTensor | |||
| }, 2, | |||
| op => wrap_tfe_src.SetOpAttrs(op, "keep_dims", keep_dims), | |||
| status); | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return new EagerTensor(results[0]); | |||
| return results[0]; | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("Mean", name, args: new { input, reduction_indices = axis, keep_dims = keep_dims }); | |||
| @@ -178,17 +191,17 @@ namespace Tensorflow | |||
| { | |||
| try | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor() }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "Prod", name, new IntPtr[] | |||
| { | |||
| input as EagerTensor, | |||
| axis as EagerTensor | |||
| }, 2, | |||
| op => wrap_tfe_src.SetOpAttrs(op, "keep_dims", keep_dims), | |||
| status); | |||
| op => wrap_tfe_src.SetOpAttrs(op, "keep_dims", keep_dims), | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return new EagerTensor(results[0]); | |||
| return results[0].Resolve(); | |||
| } | |||
| catch (Exception) | |||
| { | |||
| @@ -228,15 +241,16 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor() }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "Add", name, new IntPtr[] | |||
| { | |||
| x as EagerTensor, | |||
| y as EagerTensor | |||
| }, 2, null, status); | |||
| }, 2, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return new EagerTensor(results[0]); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("Add", name, args: new { x, y }); | |||
| @@ -248,15 +262,16 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor() }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "Add", name, new IntPtr[] | |||
| { | |||
| x as EagerTensor, | |||
| y as EagerTensor | |||
| }, 2, null, status); | |||
| }, 2, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return new EagerTensor(results[0]); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("Add", name, args: new { x, y }); | |||
| @@ -269,15 +284,16 @@ namespace Tensorflow | |||
| // forward_compatible(2019, 6, 25): | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor() }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "AddV2", name, new IntPtr[] | |||
| { | |||
| x as EagerTensor, | |||
| y as EagerTensor | |||
| }, 2, null, status); | |||
| }, 2, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return new EagerTensor(results[0]); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("AddV2", name, args: new { x, y }); | |||
| @@ -303,14 +319,15 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor() }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "Sin", name, new IntPtr[] | |||
| { | |||
| x as EagerTensor, | |||
| }, 1, null, status); | |||
| }, 1, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return new EagerTensor(results[0]); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("Sin", name, args: new { x }); | |||
| @@ -336,14 +353,15 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor() }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "Sigmoid", name, new IntPtr[] | |||
| { | |||
| x as EagerTensor, | |||
| }, 1, null, status); | |||
| }, 1, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return new EagerTensor(results[0]); | |||
| return results[0].Resolve(); | |||
| } | |||
| var op = _op_def_lib._apply_op_helper("Sigmoid", name: name, new { x }); | |||
| @@ -428,14 +446,15 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor() }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "Tan", name, new IntPtr[] | |||
| { | |||
| x as EagerTensor, | |||
| }, 1, null, status); | |||
| }, 1, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return new EagerTensor(results[0]); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("Tan", name, args: new { x }); | |||
| @@ -510,15 +529,16 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor() }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "Less", name, new IntPtr[] | |||
| { | |||
| x as EagerTensor, | |||
| y as EagerTensor | |||
| }, 2, null, status); | |||
| }, 2, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return new EagerTensor(results[0]); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("Less", name: name, args: new { x, y }); | |||
| @@ -586,14 +606,15 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor() }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "Square", name, new IntPtr[] | |||
| { | |||
| x as EagerTensor, | |||
| }, 1, null, status); | |||
| }, 1, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return new EagerTensor(results[0]); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("Square", name, args: new { x }); | |||
| @@ -651,14 +672,14 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor() }; | |||
| 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), | |||
| status); | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return new EagerTensor(results[0]); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("Cast", name, args: new { x, DstT, Truncate }); | |||
| @@ -670,14 +691,15 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor() }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "Neg", name, new IntPtr[] | |||
| { | |||
| x as EagerTensor | |||
| }, 2, null, status); | |||
| }, 2, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return new EagerTensor(results[0]); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("Neg", name, args: new { x }); | |||
| @@ -689,14 +711,15 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor() }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "Sqrt", name, new IntPtr[] | |||
| { | |||
| x as EagerTensor, | |||
| }, 1, null, status); | |||
| }, 1, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return new EagerTensor(results[0]); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("Sqrt", name, args: new { x }); | |||
| @@ -708,15 +731,16 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor() }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "Sub", name, new IntPtr[] | |||
| { | |||
| x as EagerTensor, | |||
| y as EagerTensor | |||
| }, 2, null, status); | |||
| }, 2, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return new EagerTensor(results[0]); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("Sub", name, args: new { x, y }); | |||
| @@ -728,15 +752,16 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor() }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "Sub", name, new IntPtr[] | |||
| { | |||
| x as EagerTensor, | |||
| y as EagerTensor | |||
| }, 2, null, status); | |||
| }, 2, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return new EagerTensor(results[0]); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("Sub", name, args: new { x, y }); | |||
| @@ -755,15 +780,16 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor() }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "Equal", name, new IntPtr[] | |||
| { | |||
| x as EagerTensor, | |||
| y as EagerTensor | |||
| }, 2, null, status); | |||
| }, 2, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return new EagerTensor(results[0]); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("Equal", name, args: new { x, y }); | |||
| @@ -783,15 +809,16 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor() }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "NotEqual", name, new IntPtr[] | |||
| { | |||
| x as EagerTensor, | |||
| y as EagerTensor | |||
| }, 2, null, status); | |||
| }, 2, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return new EagerTensor(results[0]); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("NotEqual", name, args: new { x, y }); | |||
| @@ -803,15 +830,16 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor() }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "Atan2", name, new IntPtr[] | |||
| { | |||
| y as EagerTensor, | |||
| x as EagerTensor | |||
| }, 2, null, status); | |||
| }, 2, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return new EagerTensor(results[0]); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("Atan2", name, args: new { y, x }); | |||
| @@ -822,15 +850,16 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor() }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "Mul", name, new IntPtr[] | |||
| { | |||
| x as EagerTensor, | |||
| y as EagerTensor | |||
| }, 2, null, status); | |||
| }, 2, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return new EagerTensor(results[0]); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("Mul", name, args: new { x, y }); | |||
| @@ -842,15 +871,16 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor() }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "Mul", name, new IntPtr[] | |||
| { | |||
| x as EagerTensor, | |||
| y as EagerTensor, | |||
| }, 2, null, status); | |||
| }, 2, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return new EagerTensor(results[0]); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("Mul", name, args: new { x, y }); | |||
| @@ -869,15 +899,16 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor() }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "RealDiv", name, new IntPtr[] | |||
| { | |||
| x as EagerTensor, | |||
| y as EagerTensor | |||
| }, 2, null, status); | |||
| }, 2, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return new EagerTensor(results[0]); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("RealDiv", name, args: new { x, y }); | |||
| @@ -896,15 +927,16 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor() }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "FloorMod", name, new IntPtr[] | |||
| { | |||
| x as EagerTensor, | |||
| y as EagerTensor | |||
| }, 2, null, status); | |||
| }, 2, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return new EagerTensor(results[0]); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("FloorMod", name, args: new { x, y }); | |||
| @@ -916,15 +948,16 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor() }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "FloorDiv", name, new IntPtr[] | |||
| { | |||
| x as EagerTensor, | |||
| y as EagerTensor | |||
| }, 2, null, status); | |||
| }, 2, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return new EagerTensor(results[0]); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("FloorDiv", name, args: new { x, y }); | |||
| @@ -945,8 +978,8 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor() }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "MatMul", name, | |||
| new IntPtr[] | |||
| { | |||
| @@ -955,10 +988,10 @@ namespace Tensorflow | |||
| }, 2, | |||
| op => wrap_tfe_src.SetOpAttrs(op, | |||
| "transpose_a", transpose_a, | |||
| "transpose_b", transpose_b), | |||
| status); | |||
| "transpose_b", transpose_b), | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return new EagerTensor(results[0]); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("MatMul", name, args: new { a, b, transpose_a, transpose_b }); | |||
| @@ -1054,15 +1087,16 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor() }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "Pow", name, new IntPtr[] | |||
| { | |||
| x as EagerTensor, | |||
| y as EagerTensor | |||
| }, 2, null, status); | |||
| }, 2, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return new EagerTensor(results[0]); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("Pow", name, args: new { x, y }); | |||
| @@ -1074,8 +1108,8 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor() }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "Sum", name, | |||
| new IntPtr[] | |||
| { | |||
| @@ -1083,9 +1117,9 @@ namespace Tensorflow | |||
| axis as EagerTensor | |||
| }, 2, | |||
| op => wrap_tfe_src.SetOpAttrs(op, "keep_dims", keep_dims), | |||
| status); | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return new EagerTensor(results[0]); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("Sum", name, args: new { input, reduction_indices = axis, keep_dims }); | |||
| @@ -1128,16 +1162,17 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor() }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "Range", name, new IntPtr[] | |||
| { | |||
| start as EagerTensor, | |||
| limit as EagerTensor, | |||
| delta as EagerTensor | |||
| }, 3, null, status); | |||
| }, 3, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return new EagerTensor(results[0]); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("Range", name, new { start, limit, delta }); | |||
| @@ -0,0 +1,26 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using Tensorflow.Eager; | |||
| using static Tensorflow.Binding; | |||
| namespace Tensorflow | |||
| { | |||
| public static partial class gen_math_ops | |||
| { | |||
| public static EagerTensor mul(IntPtr x, IntPtr y, string name = null) | |||
| { | |||
| var results = new[] { new EagerTensor() }; | |||
| 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); | |||
| status.Check(true); | |||
| return results[0].Resolve(); | |||
| } | |||
| } | |||
| } | |||
| @@ -14,6 +14,7 @@ | |||
| limitations under the License. | |||
| ******************************************************************************/ | |||
| using System; | |||
| using System.Linq; | |||
| using Tensorflow.Eager; | |||
| using static Tensorflow.Binding; | |||
| @@ -41,8 +42,8 @@ namespace Tensorflow | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor() }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "RandomStandardNormal", name, new IntPtr[] | |||
| { | |||
| shape as EagerTensor, | |||
| @@ -50,10 +51,10 @@ namespace Tensorflow | |||
| op => wrap_tfe_src.SetOpAttrs(op, | |||
| "seed", seed, | |||
| "seed2", seed2, | |||
| "dtype", dtype), | |||
| status); | |||
| "dtype", dtype), | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return new EagerTensor(results[0]); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("RandomStandardNormal", | |||
| @@ -29,16 +29,17 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor() }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "AssignSubVariableOp", name, | |||
| new IntPtr[] | |||
| { | |||
| resource as EagerTensor, | |||
| value as EagerTensor | |||
| }, 2, null, status); | |||
| }, 2, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return results[0]; | |||
| return results[0].Resolve(); | |||
| } | |||
| return null; | |||
| @@ -55,16 +56,17 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor() }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "AssignAddVariableOp", name, | |||
| new IntPtr[] | |||
| { | |||
| resource as EagerTensor, | |||
| value as EagerTensor | |||
| }, 2, null, status); | |||
| }, 2, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return results[0]; | |||
| return results[0].Resolve(); | |||
| } | |||
| return null; | |||
| @@ -74,14 +76,15 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| var results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new EagerTensor[0]; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "AssignVariableOp", name, | |||
| new IntPtr[] | |||
| { | |||
| resource as EagerTensor, | |||
| value as EagerTensor | |||
| }, 2, null, status); | |||
| }, 2, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return null; | |||
| } | |||
| @@ -95,13 +98,14 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor() }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "VarIsInitializedOp", name, | |||
| new IntPtr[] { resource as EagerTensor }, | |||
| 1, null, status); | |||
| 1, null, | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return new EagerTensor(results[0]); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("VarIsInitializedOp", name, new { resource }); | |||
| @@ -123,17 +127,17 @@ namespace Tensorflow | |||
| { | |||
| if(tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor() }; | |||
| 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), | |||
| status); | |||
| "shape", shape.dims), | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return new EagerTensor(results[0]); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("VarHandleOp", name, new { | |||
| @@ -157,14 +161,14 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor() }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "ReadVariableOp", name, | |||
| new IntPtr[] { resource as EagerTensor }, 1, | |||
| op => wrap_tfe_src.SetOpAttrs(op, "dtype", dtype), | |||
| status); | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return new EagerTensor(results[0]); | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("ReadVariableOp", name, new | |||
| @@ -42,6 +42,11 @@ namespace Tensorflow | |||
| _handle = TF_NewStatus(); | |||
| } | |||
| public Status(IntPtr handle) | |||
| { | |||
| _handle = handle; | |||
| } | |||
| public void SetStatus(TF_Code code, string msg) | |||
| { | |||
| TF_SetStatus(_handle, code, msg); | |||
| @@ -69,6 +74,9 @@ namespace Tensorflow | |||
| public static implicit operator IntPtr(Status status) | |||
| => status._handle; | |||
| public static implicit operator Status(IntPtr handle) | |||
| => new Status(handle); | |||
| protected override void DisposeUnmanagedResources(IntPtr handle) | |||
| => TF_DeleteStatus(handle); | |||
| @@ -0,0 +1,17 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Text; | |||
| namespace Tensorflow | |||
| { | |||
| public class GCItemCounter | |||
| { | |||
| public GCItemType ItemType { get; set; } | |||
| public int RefCounter { get; set; } | |||
| public DateTime LastUpdateTime { get; set; } | |||
| public IntPtr Handle { get; set; } | |||
| public override string ToString() | |||
| => $"{ItemType} {RefCounter} {LastUpdateTime}"; | |||
| } | |||
| } | |||
| @@ -0,0 +1,13 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Text; | |||
| namespace Tensorflow | |||
| { | |||
| public enum GCItemType | |||
| { | |||
| TensorHandle = 0, | |||
| LocalTensorHandle = 1, | |||
| EagerTensorHandle = 2 | |||
| } | |||
| } | |||
| @@ -0,0 +1,90 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Timers; | |||
| namespace Tensorflow | |||
| { | |||
| public class GarbageCollector | |||
| { | |||
| static Dictionary<IntPtr, GCItemCounter> container = new Dictionary<IntPtr, GCItemCounter>(); | |||
| static Timer timer = null; | |||
| static object locker = new object(); | |||
| public static void Increase(IntPtr handle, GCItemType type) | |||
| { | |||
| if(timer == null) | |||
| { | |||
| timer = new Timer(300); | |||
| // Hook up the Elapsed event for the timer. | |||
| timer.Elapsed += OnTimedEvent; | |||
| timer.AutoReset = true; | |||
| timer.Enabled = true; | |||
| } | |||
| if (container.ContainsKey(handle)) | |||
| { | |||
| container[handle].RefCounter++; | |||
| container[handle].LastUpdateTime = DateTime.Now; | |||
| } | |||
| else | |||
| { | |||
| lock (locker) | |||
| { | |||
| container[handle] = new GCItemCounter | |||
| { | |||
| ItemType = type, | |||
| RefCounter = 1, | |||
| Handle = handle, | |||
| LastUpdateTime = DateTime.Now | |||
| }; | |||
| } | |||
| } | |||
| } | |||
| public static void Decrease(IntPtr handle) | |||
| { | |||
| lock (locker) | |||
| { | |||
| if (container.ContainsKey(handle)) | |||
| container[handle].RefCounter--; | |||
| } | |||
| } | |||
| private static void OnTimedEvent(object source, ElapsedEventArgs e) | |||
| { | |||
| timer.Stop(); | |||
| // dispose before 1 sec | |||
| lock (locker) | |||
| { | |||
| var items = container.Values | |||
| .Where(x => x.RefCounter <= 0 && (DateTime.Now - x.LastUpdateTime).Milliseconds > 300) | |||
| .ToArray(); | |||
| foreach (var item in items) | |||
| { | |||
| item.RefCounter = 0; | |||
| container.Remove(item.Handle); | |||
| switch (item.ItemType) | |||
| { | |||
| case GCItemType.TensorHandle: | |||
| c_api.TF_DeleteTensor(item.Handle); | |||
| break; | |||
| case GCItemType.LocalTensorHandle: | |||
| c_api.TFE_DeleteTensorHandle(item.Handle); | |||
| break; | |||
| case GCItemType.EagerTensorHandle: | |||
| c_api.TFE_DeleteEagerTensor(item.Handle); | |||
| break; | |||
| default: | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| timer.Start(); | |||
| } | |||
| } | |||
| } | |||
| @@ -62,6 +62,7 @@ Please be patient, we're working hard on missing functions, providing full tenso | |||
| <None Remove="Distribute\**" /> | |||
| <None Remove="Models\**" /> | |||
| <None Remove="runtimes\**" /> | |||
| <Compile Remove="Util\BindingArray2.cs" /> | |||
| <None Include="..\..\LICENSE"> | |||
| <Pack>True</Pack> | |||
| <PackagePath></PackagePath> | |||
| @@ -21,7 +21,7 @@ namespace Tensorflow | |||
| public EagerTensorV2(IntPtr handle) | |||
| { | |||
| EagerTensorHandle = handle; | |||
| tfe_tensor_handle = c_api.EagerTensor_Handle(handle); | |||
| tfe_tensor_handle = c_api.TFE_EagerTensorHandle(handle); | |||
| _handle = c_api.TFE_TensorHandleResolve(tfe_tensor_handle, status); | |||
| } | |||
| @@ -43,7 +43,7 @@ namespace Tensorflow | |||
| }, IntPtr.Zero); | |||
| tfe_tensor_handle = c_api.TFE_NewTensorHandle(_handle, status); | |||
| EagerTensorHandle = c_api.TFE_EagerTensorFromHandle(tf.context, tfe_tensor_handle); | |||
| EagerTensorHandle = c_api.TFE_NewEagerTensor(); | |||
| } | |||
| /*public unsafe EagerTensorV2(float[,] value) | |||
| @@ -0,0 +1,31 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Runtime.InteropServices; | |||
| using System.Text; | |||
| namespace Tensorflow | |||
| { | |||
| [StructLayout(LayoutKind.Sequential)] | |||
| public struct TF_BindingArray | |||
| { | |||
| public IntPtr array; | |||
| public int length; | |||
| public static implicit operator TF_BindingArray(IntPtr handle) | |||
| => handle == IntPtr.Zero ? default : Marshal.PtrToStructure<TF_BindingArray>(handle); | |||
| public unsafe IntPtr this[int index] | |||
| => array == IntPtr.Zero ? IntPtr.Zero : *((IntPtr*)array + index); | |||
| public unsafe IntPtr[] Data | |||
| { | |||
| get | |||
| { | |||
| var results = new IntPtr[length]; | |||
| for (int i = 0; i < length; i++) | |||
| results[i] = array == IntPtr.Zero ? IntPtr.Zero : *((IntPtr*)array + i); | |||
| return results; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -171,7 +171,7 @@ namespace Tensorflow | |||
| /// n n-Tensor (you get the idea) | |||
| /// </summary> | |||
| /// <remarks>https://www.tensorflow.org/api_docs/python/tf/rank</remarks> | |||
| public int rank | |||
| public virtual int rank | |||
| { | |||
| get | |||
| { | |||
| @@ -15,6 +15,7 @@ | |||
| ******************************************************************************/ | |||
| using System; | |||
| using System.Linq; | |||
| using Tensorflow.Eager; | |||
| using static Tensorflow.Binding; | |||
| @@ -64,18 +65,18 @@ namespace Tensorflow | |||
| { | |||
| if (tf.context.executing_eagerly()) | |||
| { | |||
| using var status = new Status(); | |||
| BindingArray results = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| var results = new[] { new EagerTensor() }; | |||
| Status status = c_api.TFE_FastPathExecute(tf.context, tf.context.device_name, | |||
| "ResourceApplyGradientDescent", name, new IntPtr[] | |||
| { | |||
| var, | |||
| alpha, | |||
| delta | |||
| }, 3, | |||
| op => wrap_tfe_src.SetOpAttrs(op, "use_locking", use_locking), | |||
| status); | |||
| op => wrap_tfe_src.SetOpAttrs(op, "use_locking", use_locking), | |||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||
| status.Check(true); | |||
| return results[0]; | |||
| return results[0].Resolve(); | |||
| } | |||
| var _op = _op_def_lib._apply_op_helper("ResourceApplyGradientDescent", name, new | |||
| @@ -19,24 +19,32 @@ using System.Runtime.InteropServices; | |||
| namespace Tensorflow | |||
| { | |||
| [StructLayout(LayoutKind.Sequential)] | |||
| public struct BindingArray | |||
| public class BindingArray : DisposableObject | |||
| { | |||
| public IntPtr array; | |||
| public int length; | |||
| TF_BindingArray data; | |||
| public IntPtr Address => data.array; | |||
| public int Length => data.length; | |||
| public BindingArray(IntPtr handle) : base(handle) | |||
| { | |||
| if (_handle != IntPtr.Zero) | |||
| data = Marshal.PtrToStructure<TF_BindingArray>(_handle); | |||
| else | |||
| data = default; | |||
| } | |||
| public static implicit operator BindingArray(IntPtr handle) | |||
| => handle == IntPtr.Zero ? default : Marshal.PtrToStructure<BindingArray>(handle); | |||
| => new BindingArray(handle); | |||
| public unsafe IntPtr this[int index] | |||
| => array == IntPtr.Zero ? IntPtr.Zero : * ((IntPtr*)array + index); | |||
| => data[index]; | |||
| public unsafe IntPtr[] Data | |||
| => data.Data; | |||
| public unsafe IntPtr[] Data() | |||
| protected override void DisposeUnmanagedResources(IntPtr handle) | |||
| { | |||
| var results = new IntPtr[length]; | |||
| for (int i = 0; i < length; i++) | |||
| results[i] = array == IntPtr.Zero ? IntPtr.Zero : * ((IntPtr*)array + i); | |||
| return results; | |||
| c_api.TF_DeleteBindingArray(_handle); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,50 @@ | |||
| /***************************************************************************** | |||
| Copyright 2018 The TensorFlow.NET Authors. All Rights Reserved. | |||
| Licensed under the Apache License, Version 2.0 (the "License"); | |||
| you may not use this file except in compliance with the License. | |||
| You may obtain a copy of the License at | |||
| http://www.apache.org/licenses/LICENSE-2.0 | |||
| Unless required by applicable law or agreed to in writing, software | |||
| distributed under the License is distributed on an "AS IS" BASIS, | |||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| See the License for the specific language governing permissions and | |||
| limitations under the License. | |||
| ******************************************************************************/ | |||
| using System; | |||
| using System.Runtime.InteropServices; | |||
| namespace Tensorflow | |||
| { | |||
| public class BindingTensorArray : DisposableObject | |||
| { | |||
| TF_BindingArray data; | |||
| public IntPtr Address => data.array; | |||
| public int Length => data.length; | |||
| public BindingTensorArray(IntPtr handle) : base(handle) | |||
| { | |||
| if (_handle != IntPtr.Zero) | |||
| data = Marshal.PtrToStructure<TF_BindingArray>(_handle); | |||
| else | |||
| data = default; | |||
| } | |||
| public static implicit operator BindingTensorArray(IntPtr handle) | |||
| => new BindingTensorArray(handle); | |||
| public unsafe IntPtr this[int index] | |||
| => data[index]; | |||
| public unsafe IntPtr[] Data | |||
| => data.Data; | |||
| protected override void DisposeUnmanagedResources(IntPtr handle) | |||
| { | |||
| c_api.TFE_DeleteBindingTensorArray(_handle); | |||
| } | |||
| } | |||
| } | |||
| @@ -14,11 +14,14 @@ | |||
| limitations under the License. | |||
| ******************************************************************************/ | |||
| using NumSharp.Utilities; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Runtime.InteropServices; | |||
| using System.Threading; | |||
| using Tensorflow.Eager; | |||
| using static Tensorflow.Binding; | |||
| namespace Tensorflow | |||
| { | |||
| @@ -38,7 +41,6 @@ namespace Tensorflow | |||
| public Context context = new Context(new ContextOptions(), new Status()); | |||
| public tensorflow() | |||
| { | |||
| _constructThreadingObjects(); | |||
| @@ -53,20 +55,20 @@ namespace Tensorflow | |||
| return ones.EagerTensorHandle; | |||
| }, (gradients) => | |||
| { | |||
| var input_grads = gradients.Data().Select(x => new EagerTensor(x)).ToArray(); | |||
| var input_grads = gradients.Data.Select(x => new EagerTensor(x)).ToArray(); | |||
| var add_n = gen_math_ops.add_n(input_grads) as EagerTensor; | |||
| return add_n.EagerTensorHandle; | |||
| }); | |||
| ops.RegisterFromAssembly(); | |||
| // ops.RegisterFromAssemblyEager(); | |||
| c_api.TFE_RegisterGradientFunction((op_name, op_inputs, op_outputs, num_attrs, output_grads, skip_input_indices) => | |||
| { | |||
| var input_tensors = op_inputs.Data().Select(x => new EagerTensor(x)).ToArray(); | |||
| var output_tensors = op_outputs.Data().Select(x => new EagerTensor(x)).ToArray(); | |||
| var output_grad_tensors = output_grads.Data().Select(x => new EagerTensor(x)).ToArray(); | |||
| var skip_input_indices_param = new int[skip_input_indices.length]; | |||
| for (int i = 0; i < skip_input_indices.length; i++) | |||
| skip_input_indices_param[i] = *((int*)skip_input_indices.array + i); | |||
| 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 skip_input_indices_param = new BindingArray(skip_input_indices).Data.Select(x => *(int*)x).ToArray(); | |||
| var gradients = ops.gradientFunctions[op_name](new EagerOperation | |||
| { | |||
| @@ -10,7 +10,6 @@ namespace TensorFlowNET.UnitTest.Gradient | |||
| [TestClass] | |||
| public class GradientEagerTest : PythonTest | |||
| { | |||
| [Ignore] | |||
| [TestMethod] | |||
| public void ConstantSq() | |||
| { | |||