| @@ -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) | static void Main(string[] args) | ||||
| { | { | ||||
| // boot .net core 10.5M. | // boot .net core 10.5M. | ||||
| var memoryTest = new MemoryLeakTesting(); | |||||
| var mm = new MemoryMonitor(); | |||||
| // warm up tensorflow.net 28.5M. | // 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.WriteLine("Finished."); | ||||
| Console.ReadLine(); | Console.ReadLine(); | ||||
| @@ -43,7 +43,7 @@ namespace Tensorflow | |||||
| /// </summary> | /// </summary> | ||||
| public partial class c_api | 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) | public static string StringPiece(IntPtr handle) | ||||
| { | { | ||||
| @@ -7,8 +7,10 @@ namespace Tensorflow.Eager | |||||
| public class EagerOperation : Operation | public class EagerOperation : Operation | ||||
| { | { | ||||
| public int NumInputs; | public int NumInputs; | ||||
| public IntPtr[] InputHandles { get; set; } | |||||
| public Tensor[] Inputs { get; set; } | public Tensor[] Inputs { get; set; } | ||||
| public int NumOutputs; | public int NumOutputs; | ||||
| public IntPtr[] OutputHandles { get; set; } | |||||
| public Tensor[] Outputs { get; set; } | public Tensor[] Outputs { get; set; } | ||||
| public int[] SkipInputIndices { get; set; } | public int[] SkipInputIndices { get; set; } | ||||
| @@ -2,47 +2,66 @@ | |||||
| using System; | using System; | ||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| using System.Text; | using System.Text; | ||||
| using static Tensorflow.Binding; | |||||
| using Tensorflow.Gradients; | |||||
| namespace Tensorflow.Eager | namespace Tensorflow.Eager | ||||
| { | { | ||||
| public partial class EagerTensor : Tensor | 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) | public EagerTensor(string value, string device_name) : base(value) | ||||
| { | { | ||||
| EagerTensorHandle = c_api.TFE_NewEagerTensor(); | |||||
| tfe_tensor_handle = c_api.TFE_NewTensorHandle(_handle, status); | 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) | public EagerTensor(NDArray value, string device_name) : base(value) | ||||
| { | { | ||||
| EagerTensorHandle = c_api.TFE_NewEagerTensor(); | |||||
| tfe_tensor_handle = c_api.TFE_NewTensorHandle(_handle, status); | 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 IntPtr EagerTensorHandle { get; set; } | ||||
| public override string Device => c_api.StringPiece(c_api.TFE_TensorHandleDeviceName(tfe_tensor_handle, status)); | 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() | public override string ToString() | ||||
| { | { | ||||
| switch (rank) | switch (rank) | ||||
| @@ -33,18 +33,17 @@ namespace Tensorflow.Eager | |||||
| { | { | ||||
| ctx.ensure_initialized(); | 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, | ctx.device_name, | ||||
| op_name, | op_name, | ||||
| inputs.Select(x => x.EagerTensorHandle).ToArray(), | inputs.Select(x => x.EagerTensorHandle).ToArray(), | ||||
| inputs.Length, | inputs.Length, | ||||
| op => wrap_tfe_src.SetOpAttrs(op, attrs), | op => wrap_tfe_src.SetOpAttrs(op, attrs), | ||||
| status); | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | 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) | 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, | public static extern void TFE_RegisterGradientFunction(gradient_function_callback gradientFunctionCallback, | ||||
| delete_backward_function_callback deleteBackwardFunctionCallback); | 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)] | [UnmanagedFunctionPointer(CallingConvention.StdCall)] | ||||
| public delegate IntPtr gradient_function_callback(string op_name, | public delegate IntPtr gradient_function_callback(string op_name, | ||||
| BindingArray op_inputs, | |||||
| BindingArray op_outputs, | |||||
| IntPtr op_inputs, | |||||
| IntPtr op_outputs, | |||||
| int num_attrs, | int num_attrs, | ||||
| BindingArray output_grads, | |||||
| BindingArray skip_input_indices); | |||||
| IntPtr output_grads, | |||||
| IntPtr skip_input_indices); | |||||
| [UnmanagedFunctionPointer(CallingConvention.StdCall)] | [UnmanagedFunctionPointer(CallingConvention.StdCall)] | ||||
| public delegate void delete_backward_function_callback(string op_name, | public delegate void delete_backward_function_callback(string op_name, | ||||
| BindingArray op_inputs, | |||||
| BindingArray op_outputs); | |||||
| IntPtr op_inputs, | |||||
| IntPtr op_outputs); | |||||
| [DllImport(TensorFlowLibName)] | [DllImport(TensorFlowLibName)] | ||||
| public static extern IntPtr TFE_WrapGradientResult(IntPtr[] gradients, int num_gradients); | public static extern IntPtr TFE_WrapGradientResult(IntPtr[] gradients, int num_gradients); | ||||
| @@ -32,7 +42,7 @@ namespace Tensorflow | |||||
| [UnmanagedFunctionPointer(CallingConvention.StdCall)] | [UnmanagedFunctionPointer(CallingConvention.StdCall)] | ||||
| public delegate IntPtr VSpace_callback_Ones(long[] shape, int dims, TF_DataType dtype); | public delegate IntPtr VSpace_callback_Ones(long[] shape, int dims, TF_DataType dtype); | ||||
| [UnmanagedFunctionPointer(CallingConvention.StdCall)] | [UnmanagedFunctionPointer(CallingConvention.StdCall)] | ||||
| public delegate IntPtr VSpace_callback_AggregateGrads(BindingArray gradients); | |||||
| public delegate IntPtr VSpace_callback_AggregateGrads(TF_BindingArray gradients); | |||||
| [DllImport(TensorFlowLibName)] | [DllImport(TensorFlowLibName)] | ||||
| public static extern void TFE_RegisterVSpace(IntPtr vspace); | 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); | public static extern TFE_TensorHandle TFE_NewTensorHandle(IntPtr t, IntPtr status); | ||||
| [DllImport(TensorFlowLibName)] | [DllImport(TensorFlowLibName)] | ||||
| public static extern IntPtr EagerTensor_Handle(IntPtr t); | |||||
| public static extern IntPtr TFE_EagerTensorHandle(IntPtr t); | |||||
| [DllImport(TensorFlowLibName)] | [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> | /// <summary> | ||||
| /// Sets the default execution mode (sync/async). Note that this can be | /// Sets the default execution mode (sync/async). Note that this can be | ||||
| @@ -260,6 +276,9 @@ namespace Tensorflow | |||||
| [DllImport(TensorFlowLibName)] | [DllImport(TensorFlowLibName)] | ||||
| public static extern int TFE_TensorHandleNumDims(IntPtr h, IntPtr status); | 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> | /// <summary> | ||||
| /// Returns the device of the operation that produced `h`. If `h` was produced by | /// 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 | /// 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> | /// <param name="h">TFE_TensorHandle*</param> | ||||
| [DllImport(TensorFlowLibName)] | [DllImport(TensorFlowLibName)] | ||||
| public static extern void TFE_DeleteEagerTensor(IntPtr h); | 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> | /// <summary> | ||||
| /// Creates a new eager Executor. Nodes in one executor are guaranteed to be | /// Creates a new eager Executor. Nodes in one executor are guaranteed to be | ||||
| /// executed in sequence. Assigning nodes to different executors allows executing | /// executed in sequence. Assigning nodes to different executors allows executing | ||||
| @@ -372,10 +397,11 @@ namespace Tensorflow | |||||
| string device_name, | string device_name, | ||||
| string op_name, | string op_name, | ||||
| string name, | string name, | ||||
| IntPtr[] args, | |||||
| IntPtr[] inputs, | |||||
| int input_size, | int input_size, | ||||
| TFE_FastPathExecute_SetOpAttrs set_op_attrs, | TFE_FastPathExecute_SetOpAttrs set_op_attrs, | ||||
| IntPtr status); | |||||
| IntPtr[] outputs, | |||||
| int output_size); | |||||
| [UnmanagedFunctionPointer(CallingConvention.StdCall)] | [UnmanagedFunctionPointer(CallingConvention.StdCall)] | ||||
| public delegate void TFE_FastPathExecute_SetOpAttrs(IntPtr op); | public delegate void TFE_FastPathExecute_SetOpAttrs(IntPtr op); | ||||
| @@ -386,13 +412,8 @@ namespace Tensorflow | |||||
| IntPtr[] inputs, | IntPtr[] inputs, | ||||
| int input_size, | int input_size, | ||||
| TFE_FastPathExecute_SetOpAttrs set_op_attrs, | 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)] | [DllImport(TensorFlowLibName)] | ||||
| public static extern IntPtr TFE_TapeSetNew(bool persistent, bool watch_accessed_variables); | public static extern IntPtr TFE_TapeSetNew(bool persistent, bool watch_accessed_variables); | ||||
| @@ -415,7 +436,7 @@ namespace Tensorflow | |||||
| [DllImport(TensorFlowLibName)] | [DllImport(TensorFlowLibName)] | ||||
| public static extern IntPtr TFE_TapeGradient(IntPtr tape, | public static extern IntPtr TFE_TapeGradient(IntPtr tape, | ||||
| IntPtr[] target, int target_size, | 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; | ||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||
| using System.Linq; | using System.Linq; | ||||
| using System.Runtime.InteropServices; | |||||
| using System.Text; | using System.Text; | ||||
| using Tensorflow.Eager; | using Tensorflow.Eager; | ||||
| using static Tensorflow.Binding; | using static Tensorflow.Binding; | ||||
| @@ -21,7 +22,8 @@ namespace Tensorflow.Gradients | |||||
| /// </summary> | /// </summary> | ||||
| public class GradientTape : IDisposable | public class GradientTape : IDisposable | ||||
| { | { | ||||
| bool _recording; | |||||
| static bool _recording; | |||||
| public static bool Recording => _recording; | |||||
| bool _persistent; | bool _persistent; | ||||
| bool _watch_accessed_variables; | bool _watch_accessed_variables; | ||||
| ResourceVariable[] _watched_variables; | ResourceVariable[] _watched_variables; | ||||
| @@ -76,13 +78,13 @@ namespace Tensorflow.Gradients | |||||
| _pop_tape(); | _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 [] { (target as EagerTensor).EagerTensorHandle }, 1, | ||||
| new [] { (source as EagerTensor).EagerTensorHandle }, 1, | new [] { (source as EagerTensor).EagerTensorHandle }, 1, | ||||
| status); | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | status.Check(true); | ||||
| return new EagerTensor(et); | |||||
| return results[0]; | |||||
| } | } | ||||
| public unsafe (Tensor, Tensor) gradient(Tensor target, (ResourceVariable, ResourceVariable) sources) | public unsafe (Tensor, Tensor) gradient(Tensor target, (ResourceVariable, ResourceVariable) sources) | ||||
| @@ -93,8 +95,8 @@ namespace Tensorflow.Gradients | |||||
| _pop_tape(); | _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[] | new IntPtr[] | ||||
| { | { | ||||
| target as EagerTensor | target as EagerTensor | ||||
| @@ -104,12 +106,9 @@ namespace Tensorflow.Gradients | |||||
| (sources.Item1.Handle as EagerTensor).EagerTensorHandle, | (sources.Item1.Handle as EagerTensor).EagerTensorHandle, | ||||
| (sources.Item2.Handle as EagerTensor).EagerTensorHandle | (sources.Item2.Handle as EagerTensor).EagerTensorHandle | ||||
| }, 2, | }, 2, | ||||
| status); | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | status.Check(true); | ||||
| var results = result_handle.Data().Select(x => new EagerTensor(x)).ToArray(); | |||||
| if (!_persistent) | if (!_persistent) | ||||
| { | { | ||||
| // Keep track of watched variables before setting tape to None | // 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() | public unsafe ResourceVariable[] watched_variables() | ||||
| { | { | ||||
| BindingArray result = c_api.TFE_TapeWatchedVariables(_handle); | 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); | var tensor = c_api.ResourceVariable_Handle(x); | ||||
| return new ResourceVariable(x, tensor); | 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; | ||||
| using System.Linq; | |||||
| using Tensorflow.Eager; | using Tensorflow.Eager; | ||||
| using static Tensorflow.Binding; | using static Tensorflow.Binding; | ||||
| @@ -467,14 +468,15 @@ namespace Tensorflow.Operations | |||||
| { | { | ||||
| if (tf.context.executing_eagerly()) | 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[] | "Relu", name, new IntPtr[] | ||||
| { | { | ||||
| features as EagerTensor, | features as EagerTensor, | ||||
| }, 1, null, status); | |||||
| }, 1, null, | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | 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 }); | 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()) | 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[] | "Tanh", name, new IntPtr[] | ||||
| { | { | ||||
| x as EagerTensor, | x as EagerTensor, | ||||
| }, 1, null, status); | |||||
| }, 1, null, | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | 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 }); | 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()) | 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[] | "ConcatV2", name, new IntPtr[] | ||||
| { | { | ||||
| values as EagerTensor, | values as EagerTensor, | ||||
| axis as EagerTensor | axis as EagerTensor | ||||
| }, 2, null, status); | |||||
| }, 2, null, | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | 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 }); | 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()) | 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, | "Pack", name, | ||||
| values.Select(x => (x as EagerTensor).EagerTensorHandle).ToArray(), values.Length, | values.Select(x => (x as EagerTensor).EagerTensorHandle).ToArray(), values.Length, | ||||
| op => wrap_tfe_src.SetOpAttrs(op, "axis", axis), | op => wrap_tfe_src.SetOpAttrs(op, "axis", axis), | ||||
| status); | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | 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 }); | 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()) | 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[] | "Identity", name, new IntPtr[] | ||||
| { | { | ||||
| input as EagerTensor | input as EagerTensor | ||||
| }, 1, null, status); | |||||
| }, 1, null, | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | status.Check(true); | ||||
| return new EagerTensor(results[0]); | |||||
| return results[0].Resolve(); | |||||
| } | } | ||||
| var _op = _op_def_lib._apply_op_helper("Identity", name, new { input }); | var _op = _op_def_lib._apply_op_helper("Identity", name, new { input }); | ||||
| @@ -276,15 +278,16 @@ namespace Tensorflow | |||||
| { | { | ||||
| if (tf.context.executing_eagerly()) | 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[] | "Fill", name, new IntPtr[] | ||||
| { | { | ||||
| dims as EagerTensor, | dims as EagerTensor, | ||||
| value as EagerTensor | value as EagerTensor | ||||
| }, 2, null, status); | |||||
| }, 2, null, | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | 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 }); | var _op = _op_def_lib._apply_op_helper("Fill", name, new { dims, value }); | ||||
| @@ -302,15 +305,16 @@ namespace Tensorflow | |||||
| { | { | ||||
| if (tf.context.executing_eagerly()) | 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[] | "BroadcastGradientArgs", name, new IntPtr[] | ||||
| { | { | ||||
| s0 as EagerTensor, | s0 as EagerTensor, | ||||
| s1 as EagerTensor | s1 as EagerTensor | ||||
| }, 2, null, status); | |||||
| }, 2, null, | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | 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 }); | var _op = _op_def_lib._apply_op_helper("BroadcastGradientArgs", name, new { s0, s1 }); | ||||
| @@ -328,15 +332,16 @@ namespace Tensorflow | |||||
| { | { | ||||
| if (tf.context.executing_eagerly()) | 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[] | "Reshape", name, new IntPtr[] | ||||
| { | { | ||||
| tensor as EagerTensor, | tensor as EagerTensor, | ||||
| shape as EagerTensor | shape as EagerTensor | ||||
| }, 2, null, status); | |||||
| }, 2, null, | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | 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 }); | var _op = _op_def_lib._apply_op_helper("Reshape", name, new { tensor, shape }); | ||||
| @@ -416,16 +421,16 @@ namespace Tensorflow | |||||
| { | { | ||||
| if (tf.context.executing_eagerly()) | 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[] | "Shape", name, new IntPtr[] | ||||
| { | { | ||||
| input as EagerTensor, | input as EagerTensor, | ||||
| }, 1, | }, 1, | ||||
| op => wrap_tfe_src.SetOpAttrs(op, "out_type", out_type), | op => wrap_tfe_src.SetOpAttrs(op, "out_type", out_type), | ||||
| status); | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | 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 }); | 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()) | 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[] | "Tile", name, new IntPtr[] | ||||
| { | { | ||||
| input as EagerTensor, | input as EagerTensor, | ||||
| multiples as EagerTensor | multiples as EagerTensor | ||||
| }, 2, null, status); | |||||
| }, 2, null, | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | 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 }); | var _op = _op_def_lib._apply_op_helper("Tile", name, new { input, multiples }); | ||||
| @@ -519,8 +525,8 @@ namespace Tensorflow | |||||
| { | { | ||||
| if (tf.context.executing_eagerly()) | 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[] | "StridedSlice", name, new IntPtr[] | ||||
| { | { | ||||
| input as EagerTensor, | input as EagerTensor, | ||||
| @@ -533,10 +539,10 @@ namespace Tensorflow | |||||
| "end_mask", end_mask, | "end_mask", end_mask, | ||||
| "ellipsis_mask", ellipsis_mask, | "ellipsis_mask", ellipsis_mask, | ||||
| "new_axis_mask", new_axis_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); | status.Check(true); | ||||
| return new EagerTensor(results[0]); | |||||
| return results[0].Resolve(); | |||||
| } | } | ||||
| var _op = _op_def_lib._apply_op_helper("StridedSlice", name, new | var _op = _op_def_lib._apply_op_helper("StridedSlice", name, new | ||||
| @@ -16,12 +16,13 @@ | |||||
| using System; | using System; | ||||
| using System.Linq; | using System.Linq; | ||||
| using System.Runtime.InteropServices; | |||||
| using Tensorflow.Eager; | using Tensorflow.Eager; | ||||
| using static Tensorflow.Binding; | using static Tensorflow.Binding; | ||||
| namespace Tensorflow | 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 OpDefLibrary _op_def_lib = new OpDefLibrary(); | ||||
| public static Execute _execute = new Execute(); | public static Execute _execute = new Execute(); | ||||
| @@ -43,14 +44,14 @@ namespace Tensorflow | |||||
| { | { | ||||
| if (tf.context.executing_eagerly()) | 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, | "AddN", name, | ||||
| inputs.Select(x => (x as EagerTensor).EagerTensorHandle).ToArray(), inputs.Length, | inputs.Select(x => (x as EagerTensor).EagerTensorHandle).ToArray(), inputs.Length, | ||||
| null, | null, | ||||
| status); | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | 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 }); | var _op = _op_def_lib._apply_op_helper("AddN", name, args: new { inputs }); | ||||
| @@ -58,6 +59,18 @@ namespace Tensorflow | |||||
| return _op.outputs[0]; | 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> | /// <summary> | ||||
| /// Returns the index with the largest value across dimensions of a tensor. | /// Returns the index with the largest value across dimensions of a tensor. | ||||
| /// </summary> | /// </summary> | ||||
| @@ -131,8 +144,8 @@ namespace Tensorflow | |||||
| { | { | ||||
| if (tf.context.executing_eagerly()) | 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, | "Mean", name, | ||||
| new IntPtr[] | new IntPtr[] | ||||
| { | { | ||||
| @@ -140,9 +153,9 @@ namespace Tensorflow | |||||
| axis as EagerTensor | axis as EagerTensor | ||||
| }, 2, | }, 2, | ||||
| op => wrap_tfe_src.SetOpAttrs(op, "keep_dims", keep_dims), | op => wrap_tfe_src.SetOpAttrs(op, "keep_dims", keep_dims), | ||||
| status); | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | 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 }); | 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 | 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[] | "Prod", name, new IntPtr[] | ||||
| { | { | ||||
| input as EagerTensor, | input as EagerTensor, | ||||
| axis as EagerTensor | axis as EagerTensor | ||||
| }, 2, | }, 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); | status.Check(true); | ||||
| return new EagerTensor(results[0]); | |||||
| return results[0].Resolve(); | |||||
| } | } | ||||
| catch (Exception) | catch (Exception) | ||||
| { | { | ||||
| @@ -228,15 +241,16 @@ namespace Tensorflow | |||||
| { | { | ||||
| if (tf.context.executing_eagerly()) | 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[] | "Add", name, new IntPtr[] | ||||
| { | { | ||||
| x as EagerTensor, | x as EagerTensor, | ||||
| y as EagerTensor | y as EagerTensor | ||||
| }, 2, null, status); | |||||
| }, 2, null, | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | 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 }); | 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()) | 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[] | "Add", name, new IntPtr[] | ||||
| { | { | ||||
| x as EagerTensor, | x as EagerTensor, | ||||
| y as EagerTensor | y as EagerTensor | ||||
| }, 2, null, status); | |||||
| }, 2, null, | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | 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 }); | 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): | // forward_compatible(2019, 6, 25): | ||||
| if (tf.context.executing_eagerly()) | 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[] | "AddV2", name, new IntPtr[] | ||||
| { | { | ||||
| x as EagerTensor, | x as EagerTensor, | ||||
| y as EagerTensor | y as EagerTensor | ||||
| }, 2, null, status); | |||||
| }, 2, null, | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | 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 }); | 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()) | 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[] | "Sin", name, new IntPtr[] | ||||
| { | { | ||||
| x as EagerTensor, | x as EagerTensor, | ||||
| }, 1, null, status); | |||||
| }, 1, null, | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | 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 }); | var _op = _op_def_lib._apply_op_helper("Sin", name, args: new { x }); | ||||
| @@ -336,14 +353,15 @@ namespace Tensorflow | |||||
| { | { | ||||
| if (tf.context.executing_eagerly()) | 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[] | "Sigmoid", name, new IntPtr[] | ||||
| { | { | ||||
| x as EagerTensor, | x as EagerTensor, | ||||
| }, 1, null, status); | |||||
| }, 1, null, | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | 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 }); | var op = _op_def_lib._apply_op_helper("Sigmoid", name: name, new { x }); | ||||
| @@ -428,14 +446,15 @@ namespace Tensorflow | |||||
| { | { | ||||
| if (tf.context.executing_eagerly()) | 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[] | "Tan", name, new IntPtr[] | ||||
| { | { | ||||
| x as EagerTensor, | x as EagerTensor, | ||||
| }, 1, null, status); | |||||
| }, 1, null, | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | 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 }); | var _op = _op_def_lib._apply_op_helper("Tan", name, args: new { x }); | ||||
| @@ -510,15 +529,16 @@ namespace Tensorflow | |||||
| { | { | ||||
| if (tf.context.executing_eagerly()) | 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[] | "Less", name, new IntPtr[] | ||||
| { | { | ||||
| x as EagerTensor, | x as EagerTensor, | ||||
| y as EagerTensor | y as EagerTensor | ||||
| }, 2, null, status); | |||||
| }, 2, null, | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | 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 }); | 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()) | 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[] | "Square", name, new IntPtr[] | ||||
| { | { | ||||
| x as EagerTensor, | x as EagerTensor, | ||||
| }, 1, null, status); | |||||
| }, 1, null, | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | 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 }); | var _op = _op_def_lib._apply_op_helper("Square", name, args: new { x }); | ||||
| @@ -651,14 +672,14 @@ namespace Tensorflow | |||||
| { | { | ||||
| if (tf.context.executing_eagerly()) | 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, | "Cast", name, | ||||
| new IntPtr[] { x as EagerTensor }, 1, | new IntPtr[] { x as EagerTensor }, 1, | ||||
| op => wrap_tfe_src.SetOpAttrs(op, "DstT", DstT, "Truncate", Truncate), | op => wrap_tfe_src.SetOpAttrs(op, "DstT", DstT, "Truncate", Truncate), | ||||
| status); | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | 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 }); | 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()) | 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[] | "Neg", name, new IntPtr[] | ||||
| { | { | ||||
| x as EagerTensor | x as EagerTensor | ||||
| }, 2, null, status); | |||||
| }, 2, null, | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | 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 }); | var _op = _op_def_lib._apply_op_helper("Neg", name, args: new { x }); | ||||
| @@ -689,14 +711,15 @@ namespace Tensorflow | |||||
| { | { | ||||
| if (tf.context.executing_eagerly()) | 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[] | "Sqrt", name, new IntPtr[] | ||||
| { | { | ||||
| x as EagerTensor, | x as EagerTensor, | ||||
| }, 1, null, status); | |||||
| }, 1, null, | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | 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 }); | var _op = _op_def_lib._apply_op_helper("Sqrt", name, args: new { x }); | ||||
| @@ -708,15 +731,16 @@ namespace Tensorflow | |||||
| { | { | ||||
| if (tf.context.executing_eagerly()) | 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[] | "Sub", name, new IntPtr[] | ||||
| { | { | ||||
| x as EagerTensor, | x as EagerTensor, | ||||
| y as EagerTensor | y as EagerTensor | ||||
| }, 2, null, status); | |||||
| }, 2, null, | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | 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 }); | 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()) | 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[] | "Sub", name, new IntPtr[] | ||||
| { | { | ||||
| x as EagerTensor, | x as EagerTensor, | ||||
| y as EagerTensor | y as EagerTensor | ||||
| }, 2, null, status); | |||||
| }, 2, null, | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | 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 }); | 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()) | 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[] | "Equal", name, new IntPtr[] | ||||
| { | { | ||||
| x as EagerTensor, | x as EagerTensor, | ||||
| y as EagerTensor | y as EagerTensor | ||||
| }, 2, null, status); | |||||
| }, 2, null, | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | 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 }); | 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()) | 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[] | "NotEqual", name, new IntPtr[] | ||||
| { | { | ||||
| x as EagerTensor, | x as EagerTensor, | ||||
| y as EagerTensor | y as EagerTensor | ||||
| }, 2, null, status); | |||||
| }, 2, null, | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | 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 }); | 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()) | 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[] | "Atan2", name, new IntPtr[] | ||||
| { | { | ||||
| y as EagerTensor, | y as EagerTensor, | ||||
| x as EagerTensor | x as EagerTensor | ||||
| }, 2, null, status); | |||||
| }, 2, null, | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | 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 }); | 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()) | 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[] | "Mul", name, new IntPtr[] | ||||
| { | { | ||||
| x as EagerTensor, | x as EagerTensor, | ||||
| y as EagerTensor | y as EagerTensor | ||||
| }, 2, null, status); | |||||
| }, 2, null, | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | 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 }); | 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()) | 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[] | "Mul", name, new IntPtr[] | ||||
| { | { | ||||
| x as EagerTensor, | x as EagerTensor, | ||||
| y as EagerTensor, | y as EagerTensor, | ||||
| }, 2, null, status); | |||||
| }, 2, null, | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | 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 }); | 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()) | 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[] | "RealDiv", name, new IntPtr[] | ||||
| { | { | ||||
| x as EagerTensor, | x as EagerTensor, | ||||
| y as EagerTensor | y as EagerTensor | ||||
| }, 2, null, status); | |||||
| }, 2, null, | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | 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 }); | 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()) | 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[] | "FloorMod", name, new IntPtr[] | ||||
| { | { | ||||
| x as EagerTensor, | x as EagerTensor, | ||||
| y as EagerTensor | y as EagerTensor | ||||
| }, 2, null, status); | |||||
| }, 2, null, | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | 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 }); | 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()) | 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[] | "FloorDiv", name, new IntPtr[] | ||||
| { | { | ||||
| x as EagerTensor, | x as EagerTensor, | ||||
| y as EagerTensor | y as EagerTensor | ||||
| }, 2, null, status); | |||||
| }, 2, null, | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | 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 }); | 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()) | 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, | "MatMul", name, | ||||
| new IntPtr[] | new IntPtr[] | ||||
| { | { | ||||
| @@ -955,10 +988,10 @@ namespace Tensorflow | |||||
| }, 2, | }, 2, | ||||
| op => wrap_tfe_src.SetOpAttrs(op, | op => wrap_tfe_src.SetOpAttrs(op, | ||||
| "transpose_a", transpose_a, | "transpose_a", transpose_a, | ||||
| "transpose_b", transpose_b), | |||||
| status); | |||||
| "transpose_b", transpose_b), | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | 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 }); | 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()) | 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[] | "Pow", name, new IntPtr[] | ||||
| { | { | ||||
| x as EagerTensor, | x as EagerTensor, | ||||
| y as EagerTensor | y as EagerTensor | ||||
| }, 2, null, status); | |||||
| }, 2, null, | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | 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 }); | 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()) | 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, | "Sum", name, | ||||
| new IntPtr[] | new IntPtr[] | ||||
| { | { | ||||
| @@ -1083,9 +1117,9 @@ namespace Tensorflow | |||||
| axis as EagerTensor | axis as EagerTensor | ||||
| }, 2, | }, 2, | ||||
| op => wrap_tfe_src.SetOpAttrs(op, "keep_dims", keep_dims), | op => wrap_tfe_src.SetOpAttrs(op, "keep_dims", keep_dims), | ||||
| status); | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | 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 }); | 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()) | 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[] | "Range", name, new IntPtr[] | ||||
| { | { | ||||
| start as EagerTensor, | start as EagerTensor, | ||||
| limit as EagerTensor, | limit as EagerTensor, | ||||
| delta as EagerTensor | delta as EagerTensor | ||||
| }, 3, null, status); | |||||
| }, 3, null, | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | 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 }); | 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. | limitations under the License. | ||||
| ******************************************************************************/ | ******************************************************************************/ | ||||
| using System; | using System; | ||||
| using System.Linq; | |||||
| using Tensorflow.Eager; | using Tensorflow.Eager; | ||||
| using static Tensorflow.Binding; | using static Tensorflow.Binding; | ||||
| @@ -41,8 +42,8 @@ namespace Tensorflow | |||||
| if (tf.context.executing_eagerly()) | 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[] | "RandomStandardNormal", name, new IntPtr[] | ||||
| { | { | ||||
| shape as EagerTensor, | shape as EagerTensor, | ||||
| @@ -50,10 +51,10 @@ namespace Tensorflow | |||||
| op => wrap_tfe_src.SetOpAttrs(op, | op => wrap_tfe_src.SetOpAttrs(op, | ||||
| "seed", seed, | "seed", seed, | ||||
| "seed2", seed2, | "seed2", seed2, | ||||
| "dtype", dtype), | |||||
| status); | |||||
| "dtype", dtype), | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | status.Check(true); | ||||
| return new EagerTensor(results[0]); | |||||
| return results[0].Resolve(); | |||||
| } | } | ||||
| var _op = _op_def_lib._apply_op_helper("RandomStandardNormal", | var _op = _op_def_lib._apply_op_helper("RandomStandardNormal", | ||||
| @@ -29,16 +29,17 @@ namespace Tensorflow | |||||
| { | { | ||||
| if (tf.context.executing_eagerly()) | 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, | "AssignSubVariableOp", name, | ||||
| new IntPtr[] | new IntPtr[] | ||||
| { | { | ||||
| resource as EagerTensor, | resource as EagerTensor, | ||||
| value as EagerTensor | value as EagerTensor | ||||
| }, 2, null, status); | |||||
| }, 2, null, | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | status.Check(true); | ||||
| return results[0]; | |||||
| return results[0].Resolve(); | |||||
| } | } | ||||
| return null; | return null; | ||||
| @@ -55,16 +56,17 @@ namespace Tensorflow | |||||
| { | { | ||||
| if (tf.context.executing_eagerly()) | 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, | "AssignAddVariableOp", name, | ||||
| new IntPtr[] | new IntPtr[] | ||||
| { | { | ||||
| resource as EagerTensor, | resource as EagerTensor, | ||||
| value as EagerTensor | value as EagerTensor | ||||
| }, 2, null, status); | |||||
| }, 2, null, | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | status.Check(true); | ||||
| return results[0]; | |||||
| return results[0].Resolve(); | |||||
| } | } | ||||
| return null; | return null; | ||||
| @@ -74,14 +76,15 @@ namespace Tensorflow | |||||
| { | { | ||||
| if (tf.context.executing_eagerly()) | 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, | "AssignVariableOp", name, | ||||
| new IntPtr[] | new IntPtr[] | ||||
| { | { | ||||
| resource as EagerTensor, | resource as EagerTensor, | ||||
| value as EagerTensor | value as EagerTensor | ||||
| }, 2, null, status); | |||||
| }, 2, null, | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | status.Check(true); | ||||
| return null; | return null; | ||||
| } | } | ||||
| @@ -95,13 +98,14 @@ namespace Tensorflow | |||||
| { | { | ||||
| if (tf.context.executing_eagerly()) | 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, | "VarIsInitializedOp", name, | ||||
| new IntPtr[] { resource as EagerTensor }, | new IntPtr[] { resource as EagerTensor }, | ||||
| 1, null, status); | |||||
| 1, null, | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | status.Check(true); | ||||
| return new EagerTensor(results[0]); | |||||
| return results[0].Resolve(); | |||||
| } | } | ||||
| var _op = _op_def_lib._apply_op_helper("VarIsInitializedOp", name, new { resource }); | var _op = _op_def_lib._apply_op_helper("VarIsInitializedOp", name, new { resource }); | ||||
| @@ -123,17 +127,17 @@ namespace Tensorflow | |||||
| { | { | ||||
| if(tf.context.executing_eagerly()) | 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, | "VarHandleOp", name, null, 0, | ||||
| op => wrap_tfe_src.SetOpAttrs(op, | op => wrap_tfe_src.SetOpAttrs(op, | ||||
| "container", container, | "container", container, | ||||
| "shared_name", shared_name, | "shared_name", shared_name, | ||||
| "dtype", dtype, | "dtype", dtype, | ||||
| "shape", shape.dims), | |||||
| status); | |||||
| "shape", shape.dims), | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | status.Check(true); | ||||
| return new EagerTensor(results[0]); | |||||
| return results[0].Resolve(); | |||||
| } | } | ||||
| var _op = _op_def_lib._apply_op_helper("VarHandleOp", name, new { | var _op = _op_def_lib._apply_op_helper("VarHandleOp", name, new { | ||||
| @@ -157,14 +161,14 @@ namespace Tensorflow | |||||
| { | { | ||||
| if (tf.context.executing_eagerly()) | 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, | "ReadVariableOp", name, | ||||
| new IntPtr[] { resource as EagerTensor }, 1, | new IntPtr[] { resource as EagerTensor }, 1, | ||||
| op => wrap_tfe_src.SetOpAttrs(op, "dtype", dtype), | op => wrap_tfe_src.SetOpAttrs(op, "dtype", dtype), | ||||
| status); | |||||
| results.Select(x => x.EagerTensorHandle).ToArray(), results.Length); | |||||
| status.Check(true); | status.Check(true); | ||||
| return new EagerTensor(results[0]); | |||||
| return results[0].Resolve(); | |||||
| } | } | ||||
| var _op = _op_def_lib._apply_op_helper("ReadVariableOp", name, new | var _op = _op_def_lib._apply_op_helper("ReadVariableOp", name, new | ||||
| @@ -42,6 +42,11 @@ namespace Tensorflow | |||||
| _handle = TF_NewStatus(); | _handle = TF_NewStatus(); | ||||
| } | } | ||||
| public Status(IntPtr handle) | |||||
| { | |||||
| _handle = handle; | |||||
| } | |||||
| public void SetStatus(TF_Code code, string msg) | public void SetStatus(TF_Code code, string msg) | ||||
| { | { | ||||
| TF_SetStatus(_handle, code, msg); | TF_SetStatus(_handle, code, msg); | ||||
| @@ -69,6 +74,9 @@ namespace Tensorflow | |||||
| public static implicit operator IntPtr(Status status) | public static implicit operator IntPtr(Status status) | ||||
| => status._handle; | => status._handle; | ||||
| public static implicit operator Status(IntPtr handle) | |||||
| => new Status(handle); | |||||
| protected override void DisposeUnmanagedResources(IntPtr handle) | protected override void DisposeUnmanagedResources(IntPtr handle) | ||||
| => TF_DeleteStatus(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="Distribute\**" /> | ||||
| <None Remove="Models\**" /> | <None Remove="Models\**" /> | ||||
| <None Remove="runtimes\**" /> | <None Remove="runtimes\**" /> | ||||
| <Compile Remove="Util\BindingArray2.cs" /> | |||||
| <None Include="..\..\LICENSE"> | <None Include="..\..\LICENSE"> | ||||
| <Pack>True</Pack> | <Pack>True</Pack> | ||||
| <PackagePath></PackagePath> | <PackagePath></PackagePath> | ||||
| @@ -21,7 +21,7 @@ namespace Tensorflow | |||||
| public EagerTensorV2(IntPtr handle) | public EagerTensorV2(IntPtr handle) | ||||
| { | { | ||||
| EagerTensorHandle = 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); | _handle = c_api.TFE_TensorHandleResolve(tfe_tensor_handle, status); | ||||
| } | } | ||||
| @@ -43,7 +43,7 @@ namespace Tensorflow | |||||
| }, IntPtr.Zero); | }, IntPtr.Zero); | ||||
| tfe_tensor_handle = c_api.TFE_NewTensorHandle(_handle, status); | 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) | /*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) | /// n n-Tensor (you get the idea) | ||||
| /// </summary> | /// </summary> | ||||
| /// <remarks>https://www.tensorflow.org/api_docs/python/tf/rank</remarks> | /// <remarks>https://www.tensorflow.org/api_docs/python/tf/rank</remarks> | ||||
| public int rank | |||||
| public virtual int rank | |||||
| { | { | ||||
| get | get | ||||
| { | { | ||||
| @@ -15,6 +15,7 @@ | |||||
| ******************************************************************************/ | ******************************************************************************/ | ||||
| using System; | using System; | ||||
| using System.Linq; | |||||
| using Tensorflow.Eager; | using Tensorflow.Eager; | ||||
| using static Tensorflow.Binding; | using static Tensorflow.Binding; | ||||
| @@ -64,18 +65,18 @@ namespace Tensorflow | |||||
| { | { | ||||
| if (tf.context.executing_eagerly()) | 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[] | "ResourceApplyGradientDescent", name, new IntPtr[] | ||||
| { | { | ||||
| var, | var, | ||||
| alpha, | alpha, | ||||
| delta | delta | ||||
| }, 3, | }, 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); | status.Check(true); | ||||
| return results[0]; | |||||
| return results[0].Resolve(); | |||||
| } | } | ||||
| var _op = _op_def_lib._apply_op_helper("ResourceApplyGradientDescent", name, new | var _op = _op_def_lib._apply_op_helper("ResourceApplyGradientDescent", name, new | ||||
| @@ -19,24 +19,32 @@ using System.Runtime.InteropServices; | |||||
| namespace Tensorflow | 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) | public static implicit operator BindingArray(IntPtr handle) | ||||
| => handle == IntPtr.Zero ? default : Marshal.PtrToStructure<BindingArray>(handle); | |||||
| => new BindingArray(handle); | |||||
| public unsafe IntPtr this[int index] | 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. | limitations under the License. | ||||
| ******************************************************************************/ | ******************************************************************************/ | ||||
| using NumSharp.Utilities; | |||||
| using System; | using System; | ||||
| using System.Collections.Generic; | |||||
| using System.Linq; | using System.Linq; | ||||
| using System.Runtime.InteropServices; | using System.Runtime.InteropServices; | ||||
| using System.Threading; | using System.Threading; | ||||
| using Tensorflow.Eager; | using Tensorflow.Eager; | ||||
| using static Tensorflow.Binding; | |||||
| namespace Tensorflow | namespace Tensorflow | ||||
| { | { | ||||
| @@ -38,7 +41,6 @@ namespace Tensorflow | |||||
| public Context context = new Context(new ContextOptions(), new Status()); | public Context context = new Context(new ContextOptions(), new Status()); | ||||
| public tensorflow() | public tensorflow() | ||||
| { | { | ||||
| _constructThreadingObjects(); | _constructThreadingObjects(); | ||||
| @@ -53,20 +55,20 @@ namespace Tensorflow | |||||
| return ones.EagerTensorHandle; | return ones.EagerTensorHandle; | ||||
| }, (gradients) => | }, (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; | var add_n = gen_math_ops.add_n(input_grads) as EagerTensor; | ||||
| return add_n.EagerTensorHandle; | return add_n.EagerTensorHandle; | ||||
| }); | }); | ||||
| ops.RegisterFromAssembly(); | ops.RegisterFromAssembly(); | ||||
| // ops.RegisterFromAssemblyEager(); | |||||
| c_api.TFE_RegisterGradientFunction((op_name, op_inputs, op_outputs, num_attrs, output_grads, skip_input_indices) => | 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 | var gradients = ops.gradientFunctions[op_name](new EagerOperation | ||||
| { | { | ||||
| @@ -10,7 +10,6 @@ namespace TensorFlowNET.UnitTest.Gradient | |||||
| [TestClass] | [TestClass] | ||||
| public class GradientEagerTest : PythonTest | public class GradientEagerTest : PythonTest | ||||
| { | { | ||||
| [Ignore] | |||||
| [TestMethod] | [TestMethod] | ||||
| public void ConstantSq() | public void ConstantSq() | ||||
| { | { | ||||