@@ -2,7 +2,7 @@ | |||||
TensorFlow.NET provides .NET Standard binding for [TensorFlow](https://www.tensorflow.org/). | TensorFlow.NET provides .NET Standard binding for [TensorFlow](https://www.tensorflow.org/). | ||||
[](https://gitter.im/sci-sharp/community) | [](https://gitter.im/sci-sharp/community) | ||||
[](https://ci.appveyor.com/project/Haiping-Chen/tensorflow-net) | |||||
[](https://ci.appveyor.com/project/Haiping-Chen/tensorflow-net) | |||||
[](https://codecov.io/gh/SciSharp/NumSharp) | [](https://codecov.io/gh/SciSharp/NumSharp) | ||||
[](https://www.nuget.org/packages/TensorFlow.NET) | [](https://www.nuget.org/packages/TensorFlow.NET) | ||||
@@ -12,13 +12,13 @@ namespace Tensorflow | |||||
{ | { | ||||
var num_return_outputs = opts.NumReturnOutputs; | var num_return_outputs = opts.NumReturnOutputs; | ||||
var return_outputs = new TF_Output[num_return_outputs]; | var return_outputs = new TF_Output[num_return_outputs]; | ||||
TF_Output* return_output_handle = (TF_Output*)Marshal.AllocHGlobal(Marshal.SizeOf<TF_Output>() * 2); | |||||
int size = Marshal.SizeOf<TF_Output>(); | |||||
TF_Output* return_output_handle = (TF_Output*)Marshal.AllocHGlobal(size * num_return_outputs); | |||||
c_api.TF_GraphImportGraphDefWithReturnOutputs(_handle, graph_def, opts, return_output_handle, num_return_outputs, s); | c_api.TF_GraphImportGraphDefWithReturnOutputs(_handle, graph_def, opts, return_output_handle, num_return_outputs, s); | ||||
for (int i = 0; i < num_return_outputs; i++) | for (int i = 0; i < num_return_outputs; i++) | ||||
{ | { | ||||
var handle = return_output_handle + i * Marshal.SizeOf<TF_Output>(); | |||||
var handle = return_output_handle + i * size; | |||||
return_outputs[i] = new TF_Output((*handle).oper, (*handle).index); | return_outputs[i] = new TF_Output((*handle).oper, (*handle).index); | ||||
} | } | ||||
@@ -140,15 +140,8 @@ namespace Tensorflow | |||||
return ret; | return ret; | ||||
} | } | ||||
public static implicit operator Operation(IntPtr handle) | |||||
{ | |||||
return new Operation(handle); | |||||
} | |||||
public static implicit operator IntPtr(Operation op) | |||||
{ | |||||
return op._handle; | |||||
} | |||||
public static implicit operator Operation(IntPtr handle) => new Operation(handle); | |||||
public static implicit operator IntPtr(Operation op) => op._handle; | |||||
public override bool Equals(object obj) | public override bool Equals(object obj) | ||||
{ | { | ||||
@@ -14,7 +14,7 @@ namespace Tensorflow | |||||
this.index = index; | this.index = index; | ||||
} | } | ||||
public unsafe IntPtr oper; | |||||
public IntPtr oper; | |||||
public int index; | public int index; | ||||
} | } | ||||
} | } |
@@ -28,11 +28,11 @@ namespace Tensorflow | |||||
} | } | ||||
_target = UTF8Encoding.UTF8.GetBytes(target); | _target = UTF8Encoding.UTF8.GetBytes(target); | ||||
var opts = c_api.TF_NewSessionOptions(); | |||||
var status = new Status(); | |||||
_session = c_api.TF_NewSession(_graph, opts, status); | |||||
//var opts = c_api.TF_NewSessionOptions(); | |||||
//var status = new Status(); | |||||
//_session = c_api.TF_NewSession(_graph, opts, status); | |||||
c_api.TF_DeleteSessionOptions(opts); | |||||
//c_api.TF_DeleteSessionOptions(opts); | |||||
} | } | ||||
public void Dispose() | public void Dispose() | ||||
@@ -102,7 +102,7 @@ namespace Tensorflow | |||||
var output_values = fetch_list.Select(x => IntPtr.Zero).ToArray(); | var output_values = fetch_list.Select(x => IntPtr.Zero).ToArray(); | ||||
c_api.TF_SessionRun(_session, | |||||
/*c_api.TF_SessionRun(_session, | |||||
run_options: IntPtr.Zero, | run_options: IntPtr.Zero, | ||||
inputs: feed_dict.Select(f => f.Key).ToArray(), | inputs: feed_dict.Select(f => f.Key).ToArray(), | ||||
input_values: new IntPtr[] { }, | input_values: new IntPtr[] { }, | ||||
@@ -113,7 +113,7 @@ namespace Tensorflow | |||||
target_opers: new IntPtr[] { }, | target_opers: new IntPtr[] { }, | ||||
ntargets: 0, | ntargets: 0, | ||||
run_metadata: IntPtr.Zero, | run_metadata: IntPtr.Zero, | ||||
status: status); | |||||
status: status);*/ | |||||
var result = output_values.Select(x => c_api.TF_TensorData(x)) | var result = output_values.Select(x => c_api.TF_TensorData(x)) | ||||
.Select(x => (object)*(float*)x) | .Select(x => (object)*(float*)x) | ||||
@@ -6,5 +6,19 @@ namespace Tensorflow | |||||
{ | { | ||||
public class Session : BaseSession | public class Session : BaseSession | ||||
{ | { | ||||
private IntPtr _handle; | |||||
public Session(IntPtr handle) | |||||
{ | |||||
_handle = handle; | |||||
} | |||||
public Session(Graph graph, SessionOptions opts, Status s) | |||||
{ | |||||
_handle = c_api.TF_NewSession(graph, opts, s); | |||||
} | |||||
public static implicit operator IntPtr(Session session) => session._handle; | |||||
public static implicit operator Session(IntPtr handle) => new Session(handle); | |||||
} | } | ||||
} | } |
@@ -0,0 +1,31 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Runtime.InteropServices; | |||||
using System.Text; | |||||
namespace Tensorflow | |||||
{ | |||||
public class SessionOptions : IDisposable | |||||
{ | |||||
private IntPtr _handle; | |||||
public unsafe SessionOptions() | |||||
{ | |||||
var opts = c_api.TF_NewSessionOptions(); | |||||
_handle = opts; | |||||
} | |||||
public unsafe SessionOptions(IntPtr handle) | |||||
{ | |||||
_handle = handle; | |||||
} | |||||
public void Dispose() | |||||
{ | |||||
c_api.TF_DeleteSessionOptions(_handle); | |||||
} | |||||
public static implicit operator IntPtr(SessionOptions opts) => opts._handle; | |||||
public static implicit operator SessionOptions(IntPtr handle) => new SessionOptions(handle); | |||||
} | |||||
} |
@@ -0,0 +1,13 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Runtime.InteropServices; | |||||
using System.Text; | |||||
namespace Tensorflow | |||||
{ | |||||
[StructLayout(LayoutKind.Sequential)] | |||||
public struct TF_SessionOptions | |||||
{ | |||||
public IntPtr options; | |||||
} | |||||
} |
@@ -10,7 +10,7 @@ namespace Tensorflow | |||||
/// <summary> | /// <summary> | ||||
/// Destroy an options object. | /// Destroy an options object. | ||||
/// </summary> | /// </summary> | ||||
/// <param name="opts"></param> | |||||
/// <param name="opts">TF_SessionOptions*</param> | |||||
[DllImport(TensorFlowLibName)] | [DllImport(TensorFlowLibName)] | ||||
public static unsafe extern void TF_DeleteSessionOptions(IntPtr opts); | public static unsafe extern void TF_DeleteSessionOptions(IntPtr opts); | ||||
@@ -18,41 +18,63 @@ namespace Tensorflow | |||||
/// Return a new execution session with the associated graph, or NULL on | /// Return a new execution session with the associated graph, or NULL on | ||||
/// error. Does not take ownership of any input parameters. | /// error. Does not take ownership of any input parameters. | ||||
/// </summary> | /// </summary> | ||||
/// <param name="graph"></param> | |||||
/// <param name="opts"></param> | |||||
/// <param name="status"></param> | |||||
/// <returns></returns> | |||||
/// <param name="graph">TF_Graph*</param> | |||||
/// <param name="opts">const TF_SessionOptions*</param> | |||||
/// <param name="status">TF_Status*</param> | |||||
/// <returns>TF_Session*</returns> | |||||
[DllImport(TensorFlowLibName)] | [DllImport(TensorFlowLibName)] | ||||
public static extern IntPtr TF_NewSession(IntPtr graph, IntPtr opts, IntPtr status); | public static extern IntPtr TF_NewSession(IntPtr graph, IntPtr opts, IntPtr status); | ||||
/// <summary> | /// <summary> | ||||
/// Return a new options object. | /// Return a new options object. | ||||
/// </summary> | /// </summary> | ||||
/// <returns></returns> | |||||
/// <returns>TF_SessionOptions*</returns> | |||||
[DllImport(TensorFlowLibName)] | [DllImport(TensorFlowLibName)] | ||||
public static extern IntPtr TF_NewSessionOptions(); | |||||
public static extern unsafe IntPtr TF_NewSessionOptions(); | |||||
/// <summary> | /// <summary> | ||||
/// Run the graph associated with the session starting with the supplied inputs | /// Run the graph associated with the session starting with the supplied inputs | ||||
/// (inputs[0,ninputs-1] with corresponding values in input_values[0,ninputs-1]). | /// (inputs[0,ninputs-1] with corresponding values in input_values[0,ninputs-1]). | ||||
/// | |||||
/// Any NULL and non-NULL value combinations for (`run_options`, | |||||
/// `run_metadata`) are valid. | |||||
/// | |||||
/// - `run_options` may be NULL, in which case it will be ignored; or | |||||
/// non-NULL, in which case it must point to a `TF_Buffer` containing the | |||||
/// serialized representation of a `RunOptions` protocol buffer. | |||||
/// - `run_metadata` may be NULL, in which case it will be ignored; or | |||||
/// non-NULL, in which case it must point to an empty, freshly allocated | |||||
/// `TF_Buffer` that may be updated to contain the serialized representation | |||||
/// of a `RunMetadata` protocol buffer. | |||||
/// | |||||
/// The caller retains ownership of `input_values` (which can be deleted using | |||||
/// TF_DeleteTensor). The caller also retains ownership of `run_options` and/or | |||||
/// `run_metadata` (when not NULL) and should manually call TF_DeleteBuffer on | |||||
/// them. | |||||
/// | |||||
/// On success, the tensors corresponding to outputs[0,noutputs-1] are placed in | |||||
/// output_values[]. Ownership of the elements of output_values[] is transferred | |||||
/// to the caller, which must eventually call TF_DeleteTensor on them. | |||||
/// | |||||
/// On failure, output_values[] contains NULLs. | |||||
/// </summary> | /// </summary> | ||||
/// <param name="session"></param> | |||||
/// <param name="run_options"></param> | |||||
/// <param name="inputs">TF_Output</param> | |||||
/// <param name="input_values">TF_Tensor</param> | |||||
/// <param name="ninputs"></param> | |||||
/// <param name="outputs"></param> | |||||
/// <param name="output_values"></param> | |||||
/// <param name="noutputs"></param> | |||||
/// <param name="target_opers"></param> | |||||
/// <param name="ntargets"></param> | |||||
/// <param name="run_metadata"></param> | |||||
/// <param name="status"></param> | |||||
/// <param name="session">TF_Session*</param> | |||||
/// <param name="run_options">const TF_Buffer*</param> | |||||
/// <param name="inputs">const TF_Output*</param> | |||||
/// <param name="input_values">TF_Tensor* const*</param> | |||||
/// <param name="ninputs">int</param> | |||||
/// <param name="outputs">const TF_Output*</param> | |||||
/// <param name="output_values">TF_Tensor**</param> | |||||
/// <param name="noutputs">int</param> | |||||
/// <param name="target_opers">const TF_Operation* const*</param> | |||||
/// <param name="ntargets">int</param> | |||||
/// <param name="run_metadata">TF_Buffer*</param> | |||||
/// <param name="status">TF_Status*</param> | |||||
[DllImport(TensorFlowLibName)] | [DllImport(TensorFlowLibName)] | ||||
public static extern unsafe void TF_SessionRun(IntPtr session, IntPtr run_options, | |||||
TF_Output[] inputs, IntPtr[] input_values, int ninputs, | |||||
TF_Output[] outputs, IntPtr[] output_values, int noutputs, | |||||
IntPtr[] target_opers, int ntargets, | |||||
public static extern unsafe void TF_SessionRun(IntPtr session, TF_Buffer* run_options, | |||||
IntPtr inputs, IntPtr input_values, int ninputs, | |||||
IntPtr outputs, ref IntPtr output_values, int noutputs, | |||||
IntPtr target_opers, int ntargets, | |||||
IntPtr run_metadata, | IntPtr run_metadata, | ||||
IntPtr status); | IntPtr status); | ||||
} | } | ||||
@@ -0,0 +1,15 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Runtime.InteropServices; | |||||
using System.Text; | |||||
namespace Tensorflow | |||||
{ | |||||
[StructLayout(LayoutKind.Sequential)] | |||||
public struct TF_Tensor | |||||
{ | |||||
public TF_DataType dtype; | |||||
public IntPtr shape; | |||||
public IntPtr buffer; | |||||
} | |||||
} |
@@ -22,12 +22,22 @@ namespace Tensorflow | |||||
public object value; | public object value; | ||||
public int value_index { get; } | public int value_index { get; } | ||||
public TF_DataType dtype { get; } | |||||
public ulong bytesize { get; } | |||||
public ulong dataTypeSize { get;} | |||||
public ulong size => bytesize / dataTypeSize; | |||||
public IntPtr buffer { get; } | |||||
public long[] shape { get; } | |||||
public TF_DataType dtype => _handle == IntPtr.Zero ? TF_DataType.DtInvalid : c_api.TF_TensorType(_handle); | |||||
public ulong bytesize => _handle == IntPtr.Zero ? 0 : c_api.TF_TensorByteSize(_handle); | |||||
public ulong dataTypeSize => _handle == IntPtr.Zero ? 0 : c_api.TF_DataTypeSize(dtype); | |||||
public ulong size => _handle == IntPtr.Zero ? 0 : bytesize / dataTypeSize; | |||||
public IntPtr buffer => _handle == IntPtr.Zero ? IntPtr.Zero : c_api.TF_TensorData(_handle); | |||||
public long[] shape | |||||
{ | |||||
get | |||||
{ | |||||
var dims = new long[rank]; | |||||
for (int i = 0; i < rank; i++) | |||||
shape[i] = c_api.TF_Dim(_handle, i); | |||||
return dims; | |||||
} | |||||
} | |||||
/// <summary> | /// <summary> | ||||
/// number of dimensions | /// number of dimensions | ||||
@@ -37,7 +47,7 @@ namespace Tensorflow | |||||
/// 3 3-Tensor (cube of numbers) | /// 3 3-Tensor (cube of numbers) | ||||
/// n n-Tensor (you get the idea) | /// n n-Tensor (you get the idea) | ||||
/// </summary> | /// </summary> | ||||
public int rank; | |||||
public int rank => _handle == IntPtr.Zero ? 0 : c_api.TF_NumDims(_handle); | |||||
public int NDims => rank; | public int NDims => rank; | ||||
/// <summary> | /// <summary> | ||||
@@ -48,29 +58,12 @@ namespace Tensorflow | |||||
public Tensor(IntPtr handle) | public Tensor(IntPtr handle) | ||||
{ | { | ||||
_handle = handle; | _handle = handle; | ||||
dtype = c_api.TF_TensorType(handle); | |||||
rank = c_api.TF_NumDims(handle); | |||||
bytesize = c_api.TF_TensorByteSize(handle); | |||||
buffer = c_api.TF_TensorData(handle); | |||||
dataTypeSize = c_api.TF_DataTypeSize(dtype); | |||||
shape = new long[rank]; | |||||
for (int i = 0; i < rank; i++) | |||||
shape[i] = c_api.TF_Dim(handle, i); | |||||
} | } | ||||
public Tensor(NDArray nd) | public Tensor(NDArray nd) | ||||
{ | { | ||||
_handle = Allocate(nd); | _handle = Allocate(nd); | ||||
dtype = c_api.TF_TensorType(_handle); | |||||
rank = c_api.TF_NumDims(_handle); | |||||
bytesize = c_api.TF_TensorByteSize(_handle); | |||||
buffer = c_api.TF_TensorData(_handle); | |||||
dataTypeSize = c_api.TF_DataTypeSize(dtype); | |||||
shape = new long[rank]; | |||||
for (int i = 0; i < rank; i++) | |||||
shape[i] = c_api.TF_Dim(_handle, i); | |||||
value = nd.Data(); | |||||
} | } | ||||
private IntPtr Allocate(NDArray nd) | private IntPtr Allocate(NDArray nd) | ||||
@@ -113,7 +106,6 @@ namespace Tensorflow | |||||
{ | { | ||||
this.op = op; | this.op = op; | ||||
this.value_index = value_index; | this.value_index = value_index; | ||||
this.dtype = dtype; | |||||
} | } | ||||
public TF_Output _as_tf_output() | public TF_Output _as_tf_output() | ||||
@@ -146,6 +138,12 @@ namespace Tensorflow | |||||
return data; | return data; | ||||
} | } | ||||
public Tensor MaybeMove() | |||||
{ | |||||
var tensor = c_api.TF_TensorMaybeMove(_handle); | |||||
return tensor; | |||||
} | |||||
public TF_DataType ToTFDataType(Type type) | public TF_DataType ToTFDataType(Type type) | ||||
{ | { | ||||
switch (type.Name) | switch (type.Name) | ||||
@@ -73,6 +73,15 @@ namespace Tensorflow | |||||
[DllImport(TensorFlowLibName)] | [DllImport(TensorFlowLibName)] | ||||
public static extern IntPtr TF_TensorData(IntPtr tensor); | public static extern IntPtr TF_TensorData(IntPtr tensor); | ||||
/// <summary> | |||||
/// Deletes `tensor` and returns a new TF_Tensor with the same content if | |||||
/// possible. Returns nullptr and leaves `tensor` untouched if not. | |||||
/// </summary> | |||||
/// <param name="tensor"></param> | |||||
/// <returns></returns> | |||||
[DllImport(TensorFlowLibName)] | |||||
public static extern IntPtr TF_TensorMaybeMove(IntPtr tensor); | |||||
/// <summary> | /// <summary> | ||||
/// Return the type of a tensor element. | /// Return the type of a tensor element. | ||||
/// </summary> | /// </summary> | ||||
@@ -51,7 +51,7 @@ namespace Tensorflow | |||||
public static Session Session() | public static Session Session() | ||||
{ | { | ||||
return new Session(); | |||||
return (Session)new BaseSession(); | |||||
} | } | ||||
} | } | ||||
} | } |
@@ -0,0 +1,100 @@ | |||||
using NumSharp.Core; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Runtime.InteropServices; | |||||
using System.Text; | |||||
using Tensorflow; | |||||
namespace TensorFlowNET.UnitTest | |||||
{ | |||||
/// <summary> | |||||
/// tensorflow\c\c_test_util.cc | |||||
/// </summary> | |||||
public class CSession | |||||
{ | |||||
private IntPtr session_; | |||||
private List<IntPtr> inputs_ = new List<IntPtr>(); | |||||
private List<IntPtr> input_values_ = new List<IntPtr>(); | |||||
private List<IntPtr> outputs_ = new List<IntPtr>(); | |||||
private List<IntPtr> output_values_ = new List<IntPtr>(); | |||||
private List<IntPtr> targets_ = new List<IntPtr>(); | |||||
public CSession(Graph graph, Status s, bool user_XLA = false) | |||||
{ | |||||
var opts = new SessionOptions(); | |||||
session_ = new Session(graph, opts, s); | |||||
} | |||||
public void SetInputs(Dictionary<IntPtr, IntPtr> inputs) | |||||
{ | |||||
DeleteInputValues(); | |||||
inputs_.Clear(); | |||||
foreach (var input in inputs) | |||||
{ | |||||
var handle = Marshal.AllocHGlobal(Marshal.SizeOf<TF_Output>()); | |||||
Marshal.StructureToPtr(new TF_Output(input.Key, 0), handle, false); | |||||
inputs_.Add(handle); | |||||
input_values_.Add(input.Value); | |||||
} | |||||
} | |||||
private void DeleteInputValues() | |||||
{ | |||||
for (var i = 0; i < input_values_.Count; ++i) | |||||
{ | |||||
//input_values_[i].Dispose(); | |||||
} | |||||
input_values_.Clear(); | |||||
} | |||||
public void SetOutputs(List<IntPtr> outputs) | |||||
{ | |||||
ResetOutputValues(); | |||||
outputs_.Clear(); | |||||
foreach (var output in outputs) | |||||
{ | |||||
var handle = Marshal.AllocHGlobal(Marshal.SizeOf<TF_Output>()); | |||||
Marshal.StructureToPtr(new TF_Output(output, 0), handle, true); | |||||
outputs_.Add(handle); | |||||
handle = Marshal.AllocHGlobal(Marshal.SizeOf<IntPtr>()); | |||||
output_values_.Add(IntPtr.Zero); | |||||
} | |||||
} | |||||
private void ResetOutputValues() | |||||
{ | |||||
for (var i = 0; i < output_values_.Count; ++i) | |||||
{ | |||||
//if (output_values_[i] != IntPtr.Zero) | |||||
//output_values_[i].Dispose(); | |||||
} | |||||
output_values_.Clear(); | |||||
} | |||||
public unsafe void Run(Status s) | |||||
{ | |||||
IntPtr inputs_ptr = inputs_.Count == 0 ? IntPtr.Zero : inputs_[0]; | |||||
IntPtr input_values_ptr = inputs_.Count == 0 ? IntPtr.Zero : input_values_[0]; | |||||
IntPtr outputs_ptr = outputs_.Count == 0 ? IntPtr.Zero : outputs_[0]; | |||||
IntPtr output_values_ptr = output_values_.Count == 0 ? IntPtr.Zero : output_values_[0]; | |||||
IntPtr targets_ptr = IntPtr.Zero; | |||||
c_api.TF_SessionRun(session_, null, inputs_ptr, input_values_ptr, inputs_.Count, | |||||
outputs_ptr, ref output_values_ptr, outputs_.Count, | |||||
targets_ptr, targets_.Count, | |||||
IntPtr.Zero, s); | |||||
s.Check(); | |||||
output_values_[0] = output_values_ptr; | |||||
} | |||||
public IntPtr output_tensor(int i) | |||||
{ | |||||
return output_values_[i]; | |||||
} | |||||
} | |||||
} |
@@ -16,7 +16,7 @@ namespace TensorFlowNET.UnitTest | |||||
/// `TEST(CAPI, Graph)` | /// `TEST(CAPI, Graph)` | ||||
/// </summary> | /// </summary> | ||||
[TestMethod] | [TestMethod] | ||||
public void c_api_Graph() | |||||
public void Graph() | |||||
{ | { | ||||
var s = new Status(); | var s = new Status(); | ||||
var graph = new Graph(); | var graph = new Graph(); | ||||
@@ -205,7 +205,7 @@ namespace TensorFlowNET.UnitTest | |||||
/// `TEST(CAPI, ImportGraphDef)` | /// `TEST(CAPI, ImportGraphDef)` | ||||
/// </summary> | /// </summary> | ||||
[TestMethod] | [TestMethod] | ||||
public void c_api_ImportGraphDef() | |||||
public void ImportGraphDef() | |||||
{ | { | ||||
var s = new Status(); | var s = new Status(); | ||||
var graph = new Graph(); | var graph = new Graph(); | ||||
@@ -362,7 +362,7 @@ namespace TensorFlowNET.UnitTest | |||||
/// `TEST(CAPI, ImportGraphDef_WithReturnOutputs)` | /// `TEST(CAPI, ImportGraphDef_WithReturnOutputs)` | ||||
/// </summary> | /// </summary> | ||||
[TestMethod] | [TestMethod] | ||||
public void c_api_ImportGraphDef_WithReturnOutputs() | |||||
public void ImportGraphDef_WithReturnOutputs() | |||||
{ | { | ||||
var s = new Status(); | var s = new Status(); | ||||
var graph = new Graph(); | var graph = new Graph(); | ||||
@@ -407,5 +407,16 @@ namespace TensorFlowNET.UnitTest | |||||
graph.Dispose(); | graph.Dispose(); | ||||
s.Dispose(); | s.Dispose(); | ||||
} | } | ||||
/// <summary> | |||||
/// `TEST(CAPI, ImportGraphDef_MissingUnusedInputMappings)` | |||||
/// </summary> | |||||
[TestMethod] | |||||
public void ImportGraphDef_MissingUnusedInputMappings() | |||||
{ | |||||
} | |||||
} | } | ||||
} | } |
@@ -15,7 +15,7 @@ namespace TensorFlowNET.UnitTest | |||||
/// `TEST(CAPI, GetAllOpList)` | /// `TEST(CAPI, GetAllOpList)` | ||||
/// </summary> | /// </summary> | ||||
[TestMethod] | [TestMethod] | ||||
public void c_api_GetAllOpList() | |||||
public void GetAllOpList() | |||||
{ | { | ||||
var handle = c_api.TF_GetAllOpList(); | var handle = c_api.TF_GetAllOpList(); | ||||
var buffer = new Buffer(handle); | var buffer = new Buffer(handle); | ||||
@@ -0,0 +1,51 @@ | |||||
using Microsoft.VisualStudio.TestTools.UnitTesting; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Text; | |||||
using Tensorflow; | |||||
namespace TensorFlowNET.UnitTest | |||||
{ | |||||
[TestClass] | |||||
public class SessionTest : CApiTest | |||||
{ | |||||
/// <summary> | |||||
/// tensorflow\c\c_api_test.cc | |||||
/// `TEST(CAPI, Session)` | |||||
/// </summary> | |||||
[TestMethod] | |||||
public void Session() | |||||
{ | |||||
var s = new Status(); | |||||
var graph = new Graph(); | |||||
// Make a placeholder operation. | |||||
var feed = c_test_util.ScalarConst(3, graph, s, "scalar1"); //c_test_util.Placeholder(graph, s); | |||||
// Make a constant operation with the scalar "2". | |||||
var two = c_test_util.ScalarConst(2, graph, s, "scalar2"); | |||||
// Add operation. | |||||
var add = c_test_util.Add(feed, two, graph, s); | |||||
var csession = new CSession(graph, s); | |||||
ASSERT_EQ(TF_Code.TF_OK, s.Code); | |||||
// Run the graph. | |||||
var inputs = new Dictionary<IntPtr, IntPtr>(); | |||||
inputs.Add(feed, c_test_util.Int32Tensor(3)); | |||||
//csession.SetInputs(inputs); | |||||
var outputs = new List<IntPtr> { add }; | |||||
csession.SetOutputs(outputs); | |||||
csession.Run(s); | |||||
Tensor outTensor = csession.output_tensor(0); | |||||
EXPECT_EQ(TF_DataType.TF_INT32, outTensor.dtype); | |||||
EXPECT_EQ(0, outTensor.NDims); | |||||
ASSERT_EQ((ulong)sizeof(uint), outTensor.bytesize); | |||||
var output_contents = outTensor.Data<int>(); | |||||
EXPECT_EQ(3 + 2, output_contents[0]); | |||||
} | |||||
} | |||||
} |
@@ -17,7 +17,7 @@ namespace TensorFlowNET.UnitTest | |||||
/// `TEST(CAPI, AllocateTensor)` | /// `TEST(CAPI, AllocateTensor)` | ||||
/// </summary> | /// </summary> | ||||
[TestMethod] | [TestMethod] | ||||
public void c_api_AllocateTensor() | |||||
public void AllocateTensor() | |||||
{ | { | ||||
ulong num_bytes = 6 * sizeof(float); | ulong num_bytes = 6 * sizeof(float); | ||||
long[] dims = { 2, 3 }; | long[] dims = { 2, 3 }; | ||||
@@ -29,12 +29,26 @@ namespace TensorFlowNET.UnitTest | |||||
t.Dispose(); | t.Dispose(); | ||||
} | } | ||||
/// <summary> | |||||
/// Port from c_api_test.cc | |||||
/// `TEST(CAPI, MaybeMove)` | |||||
/// </summary> | |||||
[TestMethod] | |||||
public void MaybeMove() | |||||
{ | |||||
NDArray nd = np.array(2, 3); | |||||
Tensor t = new Tensor(nd); | |||||
Tensor o = t.MaybeMove(); | |||||
ASSERT_TRUE(o == IntPtr.Zero); // It is unsafe to move memory TF might not own. | |||||
t.Dispose(); | |||||
} | |||||
/// <summary> | /// <summary> | ||||
/// Port from c_api_test.cc | /// Port from c_api_test.cc | ||||
/// `TEST(CAPI, Tensor)` | /// `TEST(CAPI, Tensor)` | ||||
/// </summary> | /// </summary> | ||||
[TestMethod] | [TestMethod] | ||||
public void c_api_Tensor() | |||||
public void Tensor() | |||||
{ | { | ||||
var nd = np.array(1f, 2f, 3f, 4f, 5f, 6f).reshape(2, 3); | var nd = np.array(1f, 2f, 3f, 4f, 5f, 6f).reshape(2, 3); | ||||
@@ -54,7 +68,7 @@ namespace TensorFlowNET.UnitTest | |||||
/// `TEST(CAPI, SetShape)` | /// `TEST(CAPI, SetShape)` | ||||
/// </summary> | /// </summary> | ||||
[TestMethod] | [TestMethod] | ||||
public void c_api_SetShape() | |||||
public void SetShape() | |||||
{ | { | ||||
var s = new Status(); | var s = new Status(); | ||||
var graph = new Graph(); | var graph = new Graph(); | ||||
@@ -236,5 +236,19 @@ namespace TensorFlowNET.UnitTest | |||||
{ | { | ||||
return Const(new Tensor(v), graph, s, name); | return Const(new Tensor(v), graph, s, name); | ||||
} | } | ||||
public static unsafe IntPtr Int32Tensor(int v) | |||||
{ | |||||
bool deallocator_called = false; | |||||
const int num_bytes = sizeof(int); | |||||
var dotHandle = Marshal.AllocHGlobal(num_bytes * 1); | |||||
*(int*)dotHandle = v; | |||||
return c_api.TF_NewTensor(TF_DataType.TF_INT32, new long[0], 0, dotHandle, num_bytes, | |||||
(IntPtr values, IntPtr len, ref bool closure) => | |||||
{ | |||||
// Free the original buffer and set flag | |||||
Marshal.FreeHGlobal(dotHandle); | |||||
}, ref deallocator_called); | |||||
} | |||||
} | } | ||||
} | } |