@@ -123,13 +123,13 @@ namespace Tensorflow | |||||
public static extern IntPtr TFE_NewTensorHandle(IntPtr t, IntPtr status); | public static extern IntPtr TFE_NewTensorHandle(IntPtr t, IntPtr status); | ||||
/// <summary> | /// <summary> | ||||
/// | |||||
/// Sets the default execution mode (sync/async). Note that this can be | |||||
/// overridden per thread using TFE_ContextSetExecutorForThread. | |||||
/// </summary> | /// </summary> | ||||
/// <param name="t"></param> | |||||
/// <param name="status"></param> | |||||
/// <returns></returns> | |||||
/// <param name="opts">TFE_ContextOptions*</param> | |||||
/// <param name="enable">unsigned char</param> | |||||
[DllImport(TensorFlowLibName)] | [DllImport(TensorFlowLibName)] | ||||
public static extern IntPtr TFE_DeleteTensorHandle(IntPtr t, IntPtr status); | |||||
public static extern void TFE_ContextOptionsSetAsync(IntPtr opts, byte enable); | |||||
/// <summary> | /// <summary> | ||||
/// | /// | ||||
@@ -1,6 +1,7 @@ | |||||
using Microsoft.VisualStudio.TestTools.UnitTesting; | using Microsoft.VisualStudio.TestTools.UnitTesting; | ||||
using System; | using System; | ||||
using Tensorflow; | using Tensorflow; | ||||
using Buffer = System.Buffer; | |||||
namespace TensorFlowNET.UnitTest | namespace TensorFlowNET.UnitTest | ||||
{ | { | ||||
@@ -48,6 +49,9 @@ namespace TensorFlowNET.UnitTest | |||||
protected void TF_SetAttrBool(OperationDescription desc, string attrName, bool value) | protected void TF_SetAttrBool(OperationDescription desc, string attrName, bool value) | ||||
=> c_api.TF_SetAttrBool(desc, attrName, value); | => c_api.TF_SetAttrBool(desc, attrName, value); | ||||
protected TF_DataType TFE_TensorHandleDataType(IntPtr h) | |||||
=> c_api.TFE_TensorHandleDataType(h); | |||||
protected TF_Code TF_GetCode(Status s) | protected TF_Code TF_GetCode(Status s) | ||||
=> s.Code; | => s.Code; | ||||
@@ -56,5 +60,80 @@ namespace TensorFlowNET.UnitTest | |||||
protected string TF_Message(IntPtr s) | protected string TF_Message(IntPtr s) | ||||
=> c_api.StringPiece(c_api.TF_Message(s)); | => c_api.StringPiece(c_api.TF_Message(s)); | ||||
protected IntPtr TF_NewStatus() | |||||
=> c_api.TF_NewStatus(); | |||||
protected void TF_DeleteStatus(IntPtr s) | |||||
=> c_api.TF_DeleteStatus(s); | |||||
protected IntPtr TF_TensorData(IntPtr t) | |||||
=> c_api.TF_TensorData(t); | |||||
protected ulong TF_TensorByteSize(IntPtr t) | |||||
=> c_api.TF_TensorByteSize(t); | |||||
protected void TFE_OpAddInput(IntPtr op, IntPtr h, IntPtr status) | |||||
=> c_api.TFE_OpAddInput(op, h, status); | |||||
protected void TFE_OpSetAttrType(IntPtr op, string attr_name, TF_DataType value) | |||||
=> c_api.TFE_OpSetAttrType(op, attr_name, value); | |||||
protected IntPtr TFE_NewOp(IntPtr ctx, string op_or_function_name, IntPtr status) | |||||
=> c_api.TFE_NewOp(ctx, op_or_function_name, status); | |||||
protected IntPtr TFE_NewContextOptions() | |||||
=> c_api.TFE_NewContextOptions(); | |||||
protected void TFE_DeleteContext(IntPtr t) | |||||
=> c_api.TFE_DeleteContext(t); | |||||
protected IntPtr TFE_NewContext(IntPtr opts, IntPtr status) | |||||
=> c_api.TFE_NewContext(opts, status); | |||||
protected void TFE_DeleteContextOptions(IntPtr opts) | |||||
=> c_api.TFE_DeleteContextOptions(opts); | |||||
protected void TFE_DeleteTensorHandle(IntPtr h) | |||||
=> c_api.TFE_DeleteTensorHandle(h); | |||||
protected void TFE_DeleteOp(IntPtr op) | |||||
=> c_api.TFE_DeleteOp(op); | |||||
protected IntPtr TFE_TensorHandleResolve(IntPtr h, IntPtr status) | |||||
=> c_api.TFE_TensorHandleResolve(h, status); | |||||
protected unsafe void memcpy(void * src, IntPtr dst, ulong size) | |||||
{ | |||||
Buffer.MemoryCopy(src, dst.ToPointer(), size, size); | |||||
} | |||||
protected unsafe void memcpy<T>(T[] src, IntPtr dst, ulong size) | |||||
where T : unmanaged | |||||
{ | |||||
fixed (void* p = &src[0]) | |||||
Buffer.MemoryCopy(p, dst.ToPointer(), size, size); | |||||
} | |||||
protected unsafe void memcpy<T>(T[] src, IntPtr dst, long size) | |||||
where T : unmanaged | |||||
{ | |||||
fixed (void* p = &src[0]) | |||||
Buffer.MemoryCopy(p, dst.ToPointer(), size, size); | |||||
} | |||||
protected unsafe void memcpy<T>(IntPtr src, T[] dst, ulong size) | |||||
where T : unmanaged | |||||
{ | |||||
fixed (void* p = &dst[0]) | |||||
Buffer.MemoryCopy(src.ToPointer(), p, size, size); | |||||
} | |||||
protected unsafe void memcpy<T>(IntPtr src, T[] dst, long size) | |||||
where T: unmanaged | |||||
{ | |||||
fixed (void* p = &dst[0]) | |||||
Buffer.MemoryCopy(src.ToPointer(), p, size, size); | |||||
} | |||||
} | } | ||||
} | } |
@@ -0,0 +1,56 @@ | |||||
using Microsoft.VisualStudio.TestTools.UnitTesting; | |||||
using System; | |||||
using Tensorflow; | |||||
using Tensorflow.Eager; | |||||
using Buffer = System.Buffer; | |||||
namespace TensorFlowNET.UnitTest.Eager | |||||
{ | |||||
public partial class CApiEagerTest | |||||
{ | |||||
/// <summary> | |||||
/// TEST(CAPI, Execute_MatMul_CPU) | |||||
/// </summary> | |||||
[TestMethod] | |||||
public unsafe void Execute_MatMul_CPU() | |||||
{ | |||||
Execute_MatMul_CPU(false); | |||||
} | |||||
unsafe void Execute_MatMul_CPU(bool async) | |||||
{ | |||||
var status = TF_NewStatus(); | |||||
var opts = TFE_NewContextOptions(); | |||||
c_api.TFE_ContextOptionsSetAsync(opts, Convert.ToByte(async)); | |||||
var ctx = TFE_NewContext(opts, status); | |||||
CHECK_EQ(TF_OK, TF_GetCode(status), TF_Message(status)); | |||||
TFE_DeleteContextOptions(opts); | |||||
var m = TestMatrixTensorHandle(); | |||||
var matmul = MatMulOp(ctx, m, m); | |||||
var retvals = new IntPtr[] { IntPtr.Zero, IntPtr.Zero }; | |||||
int num_retvals = 2; | |||||
c_api.TFE_Execute(matmul, retvals, ref num_retvals, status); | |||||
EXPECT_EQ(1, num_retvals); | |||||
EXPECT_EQ(TF_OK, TF_GetCode(status), TF_Message(status)); | |||||
TFE_DeleteOp(matmul); | |||||
TFE_DeleteTensorHandle(m); | |||||
var t = TFE_TensorHandleResolve(retvals[0], status); | |||||
ASSERT_EQ(TF_OK, TF_GetCode(status), TF_Message(status)); | |||||
TFE_DeleteTensorHandle(retvals[0]); | |||||
TFE_DeleteContext(ctx); | |||||
ASSERT_EQ(TF_OK, TF_GetCode(status), TF_Message(status)); | |||||
var product = new float[4]; | |||||
EXPECT_EQ(product.Length * sizeof(float), (int)TF_TensorByteSize(t)); | |||||
memcpy(TF_TensorData(t), product, TF_TensorByteSize(t)); | |||||
c_api.TF_DeleteTensor(t); | |||||
EXPECT_EQ(7f, product[0]); | |||||
EXPECT_EQ(10f, product[1]); | |||||
EXPECT_EQ(15f, product[2]); | |||||
EXPECT_EQ(22f, product[3]); | |||||
TF_DeleteStatus(status); | |||||
} | |||||
} | |||||
} |
@@ -22,10 +22,7 @@ namespace TensorFlowNET.UnitTest.Eager | |||||
ASSERT_EQ(16ul, c_api.TF_TensorByteSize(t)); | ASSERT_EQ(16ul, c_api.TF_TensorByteSize(t)); | ||||
var data = new float[] { 0f, 0f, 0f, 0f }; | var data = new float[] { 0f, 0f, 0f, 0f }; | ||||
fixed (void* src = &data[0]) | |||||
{ | |||||
Buffer.MemoryCopy((void*)c_api.TF_TensorData(t), src, data.Length * sizeof(float), (long)c_api.TF_TensorByteSize(t)); | |||||
} | |||||
memcpy(c_api.TF_TensorData(t), data, data.Length * sizeof(float)); | |||||
EXPECT_EQ(1.0f, data[0]); | EXPECT_EQ(1.0f, data[0]); | ||||
EXPECT_EQ(2.0f, data[1]); | EXPECT_EQ(2.0f, data[1]); | ||||
@@ -12,15 +12,12 @@ namespace TensorFlowNET.UnitTest.Eager | |||||
[TestClass] | [TestClass] | ||||
public partial class CApiEagerTest : CApiTest | public partial class CApiEagerTest : CApiTest | ||||
{ | { | ||||
unsafe IntPtr TestMatrixTensorHandle() | |||||
IntPtr TestMatrixTensorHandle() | |||||
{ | { | ||||
var dims = new long[] { 2, 2 }; | var dims = new long[] { 2, 2 }; | ||||
var data = new float[] { 1.0f, 2.0f, 3.0f, 4.0f }; | var data = new float[] { 1.0f, 2.0f, 3.0f, 4.0f }; | ||||
var t = c_api.TF_AllocateTensor(TF_FLOAT, dims, dims.Length, (ulong)data.Length * sizeof(float)); | var t = c_api.TF_AllocateTensor(TF_FLOAT, dims, dims.Length, (ulong)data.Length * sizeof(float)); | ||||
fixed(void *src = &data[0]) | |||||
{ | |||||
Buffer.MemoryCopy(src, (void*)c_api.TF_TensorData(t), (long)c_api.TF_TensorByteSize(t), data.Length * sizeof(float)); | |||||
} | |||||
memcpy(data, c_api.TF_TensorData(t), data.Length * sizeof(float)); | |||||
var status = c_api.TF_NewStatus(); | var status = c_api.TF_NewStatus(); | ||||
var th = c_api.TFE_NewTensorHandle(t, status); | var th = c_api.TFE_NewTensorHandle(t, status); | ||||
@@ -29,5 +26,21 @@ namespace TensorFlowNET.UnitTest.Eager | |||||
c_api.TF_DeleteStatus(status); | c_api.TF_DeleteStatus(status); | ||||
return th; | return th; | ||||
} | } | ||||
IntPtr MatMulOp(IntPtr ctx, IntPtr a, IntPtr b) | |||||
{ | |||||
var status = TF_NewStatus(); | |||||
var op = TFE_NewOp(ctx, "MatMul", status); | |||||
CHECK_EQ(TF_OK, TF_GetCode(status), TF_Message(status)); | |||||
TFE_OpAddInput(op, a, status); | |||||
CHECK_EQ(TF_OK, TF_GetCode(status), TF_Message(status)); | |||||
TFE_OpAddInput(op, b, status); | |||||
CHECK_EQ(TF_OK, TF_GetCode(status), TF_Message(status)); | |||||
TF_DeleteStatus(status); | |||||
TFE_OpSetAttrType(op, "T", TFE_TensorHandleDataType(a)); | |||||
return op; | |||||
} | |||||
} | } | ||||
} | } |