@@ -1,5 +1,6 @@ | |||
using System; | |||
using System.Runtime.InteropServices; | |||
using TFE_Executor = System.IntPtr; | |||
namespace Tensorflow | |||
{ | |||
@@ -196,5 +197,55 @@ namespace Tensorflow | |||
/// <param name="h">TFE_TensorHandle*</param> | |||
[DllImport(TensorFlowLibName)] | |||
public static extern void TFE_DeleteTensorHandle(IntPtr h); | |||
/// <summary> | |||
/// Creates a new eager Executor. Nodes in one executor are guaranteed to be | |||
/// executed in sequence. Assigning nodes to different executors allows executing | |||
/// nodes in parallel. | |||
/// </summary> | |||
/// <param name="is_async"></param> | |||
/// <returns>TFE_Executor*</returns> | |||
[DllImport(TensorFlowLibName)] | |||
public static extern IntPtr TFE_NewExecutor(bool is_async); | |||
/// <summary> | |||
/// Deletes the eager Executor without waiting for enqueued nodes. Please call | |||
/// TFE_ExecutorWaitForAllPendingNodes before calling this API if you want to | |||
/// make sure all nodes are finished. | |||
/// </summary> | |||
/// <param name="e">TFE_Executor*</param> | |||
[DllImport(TensorFlowLibName)] | |||
public static extern void TFE_DeleteExecutor(IntPtr executor); | |||
/// <summary> | |||
/// Causes the calling thread to block till all ops dispatched in this executor | |||
/// have been executed. Note that "execution" here refers to kernel execution / | |||
/// scheduling of copies, etc. Similar to sync execution, it doesn't guarantee | |||
/// that lower level device queues (like GPU streams) have been flushed. | |||
/// | |||
/// This call may not block for execution of ops enqueued concurrently with this | |||
/// call. | |||
/// </summary> | |||
/// <param name="executor">TFE_Executor*</param> | |||
/// <param name="status">TF_Status*</param> | |||
[DllImport(TensorFlowLibName)] | |||
public static extern void TFE_ExecutorWaitForAllPendingNodes(TFE_Executor executor, IntPtr status); | |||
/// <summary> | |||
/// Sets a custom Executor for current thread. All nodes created by this thread | |||
/// will be added to this Executor. It will override current executor. | |||
/// </summary> | |||
/// <param name="ctx"></param> | |||
/// <param name="executor"></param> | |||
[DllImport(TensorFlowLibName)] | |||
public static extern void TFE_ContextSetExecutorForThread(IntPtr ctx, TFE_Executor executor); | |||
/// <summary> | |||
/// Returns the Executor for current thread. | |||
/// </summary> | |||
/// <param name="ctx"></param> | |||
/// <returns>TFE_Executor*</returns> | |||
[DllImport(TensorFlowLibName)] | |||
public static extern TFE_Executor TFE_ContextGetExecutorForThread(IntPtr ctx); | |||
} | |||
} |
@@ -100,6 +100,15 @@ namespace TensorFlowNET.UnitTest | |||
protected void TFE_DeleteOp(IntPtr op) | |||
=> c_api.TFE_DeleteOp(op); | |||
protected void TFE_DeleteExecutor(IntPtr executor) | |||
=> c_api.TFE_DeleteExecutor(executor); | |||
protected IntPtr TFE_ContextGetExecutorForThread(IntPtr ctx) | |||
=> c_api.TFE_ContextGetExecutorForThread(ctx); | |||
protected void TFE_ExecutorWaitForAllPendingNodes(IntPtr executor, IntPtr status) | |||
=> c_api.TFE_ExecutorWaitForAllPendingNodes(executor, status); | |||
protected IntPtr TFE_TensorHandleResolve(IntPtr h, IntPtr status) | |||
=> c_api.TFE_TensorHandleResolve(h, status); | |||
@@ -127,6 +136,9 @@ namespace TensorFlowNET.UnitTest | |||
protected IntPtr TFE_TensorHandleCopyToDevice(IntPtr h, IntPtr ctx, string device_name, IntPtr status) | |||
=> c_api.TFE_TensorHandleCopyToDevice(h, ctx, device_name, status); | |||
protected void TFE_OpSetDevice(IntPtr op, string device_name, IntPtr status) | |||
=> c_api.TFE_OpSetDevice(op, device_name, status); | |||
protected unsafe void memcpy(void * src, IntPtr dst, ulong size) | |||
{ | |||
Buffer.MemoryCopy(src, dst.ToPointer(), size, size); | |||
@@ -36,8 +36,36 @@ namespace TensorFlowNET.UnitTest.Eager | |||
var hgpu = TFE_TensorHandleCopyToDevice(hcpu, ctx, gpu_device_name, status); | |||
ASSERT_TRUE(TF_GetCode(status) == TF_OK, TF_Message(status)); | |||
// shape_op = ShapeOp(ctx, hgpu); | |||
var shape_op = ShapeOp(ctx, hgpu); | |||
TFE_OpSetDevice(shape_op, gpu_device_name, status); | |||
ASSERT_TRUE(TF_GetCode(status) == TF_OK, TF_Message(status)); | |||
var retvals = new IntPtr[1]; | |||
int num_retvals = 1; | |||
c_api.TFE_Execute(shape_op, retvals, ref num_retvals, status); | |||
ASSERT_TRUE(TF_GetCode(status) == TF_OK, TF_Message(status)); | |||
// .device of shape is GPU since the op is executed on GPU | |||
device_name = TFE_TensorHandleDeviceName(retvals[0], status); | |||
ASSERT_EQ(TF_OK, TF_GetCode(status), TF_Message(status)); | |||
ASSERT_TRUE(device_name.Contains("GPU:0")); | |||
// .backing_device of shape is CPU since the tensor is backed by CPU | |||
backing_device_name = TFE_TensorHandleBackingDeviceName(retvals[0], status); | |||
ASSERT_EQ(TF_OK, TF_GetCode(status), TF_Message(status)); | |||
ASSERT_TRUE(backing_device_name.Contains("CPU:0")); | |||
TFE_DeleteOp(shape_op); | |||
TFE_DeleteTensorHandle(retvals[0]); | |||
TFE_DeleteTensorHandle(hgpu); | |||
} | |||
TFE_DeleteTensorHandle(hcpu); | |||
// not export api | |||
/*var executor = TFE_ContextGetExecutorForThread(ctx); | |||
TFE_ExecutorWaitForAllPendingNodes(executor, status); | |||
ASSERT_EQ(TF_OK, TF_GetCode(status), TF_Message(status)); | |||
TFE_DeleteExecutor(executor);*/ | |||
TFE_DeleteContext(ctx); | |||
} | |||
} | |||
} |
@@ -1,8 +1,6 @@ | |||
using Microsoft.VisualStudio.TestTools.UnitTesting; | |||
using System; | |||
using Tensorflow; | |||
using Tensorflow.Eager; | |||
using Buffer = System.Buffer; | |||
namespace TensorFlowNET.UnitTest.Eager | |||
{ | |||
@@ -67,5 +65,19 @@ namespace TensorFlowNET.UnitTest.Eager | |||
TF_DeleteDeviceList(devices); | |||
return false; | |||
} | |||
IntPtr ShapeOp(IntPtr ctx, IntPtr a) | |||
{ | |||
var status = TF_NewStatus(); | |||
var op = TFE_NewOp(ctx, "Shape", 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)); | |||
TF_DeleteStatus(status); | |||
TFE_OpSetAttrType(op, "T", TFE_TensorHandleDataType(a)); | |||
return op; | |||
} | |||
} | |||
} |
@@ -33,7 +33,7 @@ | |||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" /> | |||
<PackageReference Include="MSTest.TestAdapter" Version="2.1.0" /> | |||
<PackageReference Include="MSTest.TestFramework" Version="2.1.0" /> | |||
<PackageReference Include="SciSharp.TensorFlow.Redist-Windows-GPU" Version="1.15.1" /> | |||
<PackageReference Include="SciSharp.TensorFlow.Redist" Version="1.15.1" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||