@@ -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() | ||||
{ | { | ||||