Skip to content

Performance optimization, refactoring and revamping. #366

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 58 commits into from
Aug 28, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
891346e
Refactored DisposableObject
Nucs Aug 21, 2019
35295f8
Added different build directory for TensorflowNET.Examples.GPU
Nucs Aug 21, 2019
c876be4
_FetchHandler: Switched to NPTypeCode
Nucs Aug 21, 2019
1992bb0
gfile.cs, Walk(...): Handle case when directory top doesn't exist.
Nucs Aug 21, 2019
d60c36f
Tensor.Creation: Perf-opted when creating tensor from NDArray of string
Nucs Aug 21, 2019
4be99ec
Graph.cs: refactor and added docs
Nucs Aug 21, 2019
533f8fd
Tensor.Creation.cs: perf-ops
Nucs Aug 21, 2019
4ba71e2
Tensor.Explicit.cs: perf-ops
Nucs Aug 21, 2019
cfc3926
Copied globals.regen from NumSharp
Nucs Aug 21, 2019
2129dbd
Tensor perf-ops and cleanup, Revamped dtypes.cs, some renames.
Nucs Aug 21, 2019
766fa6f
Tensor: Added guards for explicit casts.
Nucs Aug 21, 2019
4cf817e
Tensor: Added explicit cast to string
Nucs Aug 21, 2019
52955b3
Tensor.ToArray<T>(): Added support for cases when tensor is scalar.
Nucs Aug 21, 2019
f375e1c
Tensor.BufferToArray(): Fixed to use long instead of int.
Nucs Aug 21, 2019
290d0dd
TensorShape: Revamped and documented.
Nucs Aug 21, 2019
35360e9
BaseSession: Added Session.run(ITensorOrOperation fetche, params Feed…
Nucs Aug 21, 2019
38f27f1
Tensor: renamed _dtype to _override_dtype
Nucs Aug 21, 2019
605a05e
Fixed unit tests
Nucs Aug 21, 2019
667a566
Tensor.Operations: Reverted commit
Nucs Aug 21, 2019
a5bdd99
DisposableObject: sorted internal_dispose to properly handle Dispose(…
Nucs Aug 21, 2019
2c01153
Tensor.DisposeUnmanagedResources: Nullify _handle after delete.
Nucs Aug 21, 2019
44adad6
TensorShape.this[...]: fixed guard check.
Nucs Aug 21, 2019
672c923
DisposableObject #362
Oceania2018 Aug 22, 2019
93d7e9a
DisposableObject: Revamped based on VS unmanaged resource pattern.
Nucs Aug 22, 2019
21199b0
Added TensorflowException as base class to all exceptions.
Nucs Aug 22, 2019
71c592c
DisposableObject: Added CheckDisposed()
Nucs Aug 22, 2019
07453f6
ScopedTFImportGraphDefOptions: removed unnecessary deconstructor
Nucs Aug 22, 2019
76a9729
DefaultGraphStack: Revamped
Nucs Aug 22, 2019
d208f31
tensor_util.cs: minor perf-op
Nucs Aug 22, 2019
cbf8945
Tensor.Creation: uncommented `Marshal.FreeHGlobal(dataPtr);`
Nucs Aug 22, 2019
6772e19
globals.regen: fixed and added more arrays
Nucs Aug 22, 2019
1f297ea
Merge branch 'master' into perf-ops-2
Nucs Aug 22, 2019
a7dd34d
Revamped Context and ContextOptions
Nucs Aug 22, 2019
916ebc5
BaseSession: Heavy perf-ops in sess.run logic-flow.
Nucs Aug 22, 2019
f433c32
DefaultGraphStack: Perf-ops
Nucs Aug 25, 2019
729d8e9
Added benchmark for struct casting
Nucs Aug 25, 2019
5cf4543
TensorflowNET.UnitTest: Signed and added InternalVisibleTo in Core pr…
Nucs Aug 25, 2019
821ac13
TensorflowNET.Benchmarks: Removed InProcessToolchain from benchmarking.
Nucs Aug 25, 2019
b5d1021
BaseSession.run: revamped validate and process feed_dict.
Nucs Aug 27, 2019
fb7f4d4
FeedItem: Added deconstructor
Nucs Aug 27, 2019
47e80cd
Status: Changed exception of Check(bool) to TensorflowException
Nucs Aug 27, 2019
a53d6cc
Tensor.Creation: changed deallocatiors to readonly private
Nucs Aug 27, 2019
1e791f6
Tensor: Changed eval(Session session, FeedItem[] feed_dict = null) to…
Nucs Aug 27, 2019
3fecaf0
Tensor: Fixed redundant check and assignment in DisposeUnmanagedResou…
Nucs Aug 27, 2019
4e7308d
Tensor: revamp of IsDisposed
Nucs Aug 27, 2019
a979859
Create UnmanagedExtensions.cs
Nucs Aug 27, 2019
4a9a2c6
Tensor.ToArray<T>: Minor change
Nucs Aug 27, 2019
bd18f5d
Removed all use-cases of Marshal.PtrToStructure in favor of unsafe ptrs.
Nucs Aug 27, 2019
7e46d4f
CSession: Revmoed Dispose of Input and Ouput values in DeleteInputVal…
Nucs Aug 27, 2019
9d6525e
Buffer: Revamped and all perf-optted all use-cases.
Nucs Aug 27, 2019
3a42d80
Tensor.StringData: Changed to public.
Nucs Aug 27, 2019
f1bc50e
Reverted: DefaultGraphStack: Perf-ops
Nucs Aug 28, 2019
33286b9
RetainImageClassifier.cs: Fixed download url
Nucs Aug 28, 2019
8347f61
RetrainImageClassifier.cs: Changed cache_bottlenecks to use Parallel.For
Nucs Aug 28, 2019
70aafa7
ObjectDetection: Fixed download url
Nucs Aug 28, 2019
c0969be
Tensor.Creation: Minor bug fix
Nucs Aug 28, 2019
6b2fa40
BaseSession: Reverted all changes
Nucs Aug 28, 2019
854c2e5
Binding.Util: Minor perf-op
Nucs Aug 28, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/TensorFlowNET.Core/Assembly/Properties.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
using System.Runtime.CompilerServices;
#if DEBUG
[assembly: InternalsVisibleTo("TensorFlowNET.UnitTest, PublicKey=00240000048000009400000006020000002400005253413100040000010001004b86c4cb78549b34bab61a3b1800e23bfeb5b3ec390074041536a7e3cbd97f5f04cf0f857155a8928eaa29ebfd11cfbbad3ba70efea7bda3226c6a8d370a4cd303f714486b6ebc225985a638471e6ef571cc92a4613c00b8fa65d61ccee0cbe5f36330c9a01f4183559f1bef24cc2917c6d913e3a541333a1d05d9bed22b38cb")]
#endif
9 changes: 7 additions & 2 deletions src/TensorFlowNET.Core/Binding.Util.cs
Original file line number Diff line number Diff line change
Expand Up @@ -178,13 +178,18 @@ public static float time()

public static IEnumerable<(TKey, TValue)> enumerate<TKey, TValue>(KeyValuePair<TKey, TValue>[] values)
{
foreach (var item in values)
var len = values.Length;
for (var i = 0; i < len; i++)
{
var item = values[i];
yield return (item.Key, item.Value);
}
}

public static IEnumerable<(int, T)> enumerate<T>(IList<T> values)
{
for (int i = 0; i < values.Count; i++)
var len = values.Count;
for (int i = 0; i < len; i++)
yield return (i, values[i]);
}

Expand Down
102 changes: 80 additions & 22 deletions src/TensorFlowNET.Core/Buffers/Buffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,58 +15,116 @@ limitations under the License.
******************************************************************************/

using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using NumSharp.Backends.Unmanaged;
using static Tensorflow.c_api;

namespace Tensorflow
{
/// <summary>
/// Represents a TF_Buffer that can be passed to Tensorflow.
/// </summary>
public class Buffer : DisposableObject
{
private TF_Buffer buffer => Marshal.PtrToStructure<TF_Buffer>(_handle);
private unsafe TF_Buffer buffer
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => *bufferptr;
}

private unsafe TF_Buffer* bufferptr
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => (TF_Buffer*) _handle;
}

public byte[] Data
/// <summary>
/// The memory block representing this buffer.
/// </summary>
/// <remarks>The deallocator is set to null.</remarks>
public UnmanagedMemoryBlock<byte> MemoryBlock
{
get
get
{
var data = new byte[buffer.length];
if (data.Length > 0)
Marshal.Copy(buffer.data, data, 0, data.Length);
return data;
unsafe
{
EnsureNotDisposed();
var buff = (TF_Buffer*) _handle;
return new UnmanagedMemoryBlock<byte>((byte*) buff->data.ToPointer(), (long) buff->length);
}
}
}

public int Length => (int)buffer.length;

public Buffer()
/// <summary>
/// The bytes length of this buffer.
/// </summary>
public ulong Length
{
_handle = c_api.TF_NewBuffer();
get
{
EnsureNotDisposed();
return buffer.length;
}
}

public Buffer(IntPtr handle)
public Buffer() => _handle = TF_NewBuffer();

internal Buffer(IntPtr handle)
{
if (handle == IntPtr.Zero)
throw new ArgumentException("Handle (IntPtr) can't be zero.", nameof(handle));

_handle = handle;
}

public Buffer(byte[] data)
{
var dst = Marshal.AllocHGlobal(data.Length);
Marshal.Copy(data, 0, dst, data.Length);
public Buffer(byte[] data) : this(_toBuffer(data))
{ }

_handle = c_api.TF_NewBufferFromString(dst, (ulong)data.Length);
private static IntPtr _toBuffer(byte[] data)
{
if (data == null)
throw new ArgumentNullException(nameof(data));

Marshal.FreeHGlobal(dst);
unsafe
{
fixed (byte* src = data)
return TF_NewBufferFromString(new IntPtr(src), (ulong) data.LongLength);
}
}

public static implicit operator IntPtr(Buffer buffer)
{
buffer.EnsureNotDisposed();
return buffer._handle;
}

public static implicit operator byte[](Buffer buffer)
public static explicit operator byte[](Buffer buffer) => buffer.ToArray(); //has to be explicit, developer will assume it doesn't cost.

/// <summary>
/// Copies this buffer's contents onto a <see cref="byte"/> array.
/// </summary>
public byte[] ToArray()
{
return buffer.Data;
EnsureNotDisposed();

unsafe
{
var len = buffer.length;
if (len == 0)
return Array.Empty<byte>();

byte[] data = new byte[len];
fixed (byte* dst = data)
System.Buffer.MemoryCopy((void*) bufferptr->data, dst, len, len);

return data;
}
}

protected override void DisposeUnmanagedResources(IntPtr handle)
=> c_api.TF_DeleteBuffer(handle);
{
TF_DeleteBuffer(handle);
}
}
}
}
53 changes: 33 additions & 20 deletions src/TensorFlowNET.Core/DisposableObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ limitations under the License.

using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using System.Text;

namespace Tensorflow
Expand All @@ -26,27 +28,33 @@ namespace Tensorflow
public abstract class DisposableObject : IDisposable
{
protected IntPtr _handle;
protected bool _disposed;

protected DisposableObject() { }
[SuppressMessage("ReSharper", "UnusedMember.Global")]
protected DisposableObject()
{ }

protected DisposableObject(IntPtr handle)
protected DisposableObject(IntPtr handle)
=> _handle = handle;

[SuppressMessage("ReSharper", "InvertIf")]
private void internal_dispose(bool disposing)
{
if (disposing)
{
// free unmanaged resources (unmanaged objects) and override a finalizer below.
if (_handle != IntPtr.Zero)
{
// dispose managed state (managed objects).
DisposeManagedResources();
if (_disposed)
return;

_disposed = true;

// set large fields to null.
DisposeUnmanagedResources(_handle);
//first handle managed, they might use the unmanaged resources.
if (disposing)
// dispose managed state (managed objects).
DisposeManagedResources();

_handle = IntPtr.Zero;
}
//free unmanaged memory
if (_handle != IntPtr.Zero)
{
DisposeUnmanagedResources(_handle);
_handle = IntPtr.Zero;
}
}

Expand All @@ -55,28 +63,33 @@ private void internal_dispose(bool disposing)
/// </summary>
/// <remarks>Equivalent to what you would perform inside <see cref="Dispose()"/></remarks>
protected virtual void DisposeManagedResources()
{
}
{ }

/// <summary>
/// Dispose any unmanaged resources related to given <paramref name="handle"/>.
/// </summary>
protected abstract void DisposeUnmanagedResources(IntPtr handle);

// override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
~DisposableObject()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
internal_dispose(false);
}

// This code added to correctly implement the disposable pattern.
public void Dispose()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
internal_dispose(true);
// uncomment the following line if the finalizer is overridden above.
GC.SuppressFinalize(this);
}

/// <summary>
/// If <see cref="_handle"/> is <see cref="IntPtr.Zero"/> then throws <see cref="ObjectDisposedException"/>
/// </summary>
/// <exception cref="ObjectDisposedException">When <see cref="_handle"/> is <see cref="IntPtr.Zero"/></exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
protected void EnsureNotDisposed()
{
if (_disposed)
throw new ObjectDisposedException($"Unable to access disposed object, Type: {GetType().Name}");
}
}
}
29 changes: 12 additions & 17 deletions src/TensorFlowNET.Core/Eager/Context.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@

namespace Tensorflow.Eager
{
public class Context : IDisposable
public class Context : DisposableObject
{
private IntPtr _handle;

public static int GRAPH_MODE = 0;
public static int EAGER_MODE = 1;
public const int GRAPH_MODE = 0;
public const int EAGER_MODE = 1;

public int default_execution_mode;

Expand All @@ -17,19 +15,16 @@ public Context(ContextOptions opts, Status status)
status.Check(true);
}

public void Dispose()
{
c_api.TFE_DeleteContext(_handle);
}
/// <summary>
/// Dispose any unmanaged resources related to given <paramref name="handle"/>.
/// </summary>
protected sealed override void DisposeUnmanagedResources(IntPtr handle)
=> c_api.TFE_DeleteContext(_handle);

public bool executing_eagerly()
{
return false;
}

public static implicit operator IntPtr(Context ctx)
{
return ctx._handle;
}
public bool executing_eagerly() => false;

public static implicit operator IntPtr(Context ctx)
=> ctx._handle;
}
}
25 changes: 11 additions & 14 deletions src/TensorFlowNET.Core/Eager/ContextOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,20 @@

namespace Tensorflow.Eager
{
public class ContextOptions : IDisposable //TODO! Eli: Shouldn't this inherieting DisposableObject?
public class ContextOptions : DisposableObject
{
private IntPtr _handle;
public ContextOptions() : base(c_api.TFE_NewContextOptions())
{ }

public ContextOptions()
{
_handle = c_api.TFE_NewContextOptions();
}
/// <summary>
/// Dispose any unmanaged resources related to given <paramref name="handle"/>.
/// </summary>
protected sealed override void DisposeUnmanagedResources(IntPtr handle)
=> c_api.TFE_DeleteContextOptions(_handle);

public void Dispose()
{
c_api.TFE_DeleteContextOptions(_handle);
}

public static implicit operator IntPtr(ContextOptions opts)
{
return opts._handle;
}
public static implicit operator IntPtr(ContextOptions opts)
=> opts._handle;
}

}
2 changes: 1 addition & 1 deletion src/TensorFlowNET.Core/Exceptions/KeyError.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace Tensorflow
{
public class KeyError : Exception
public class KeyError : TensorflowException
{
public KeyError() : base()
{
Expand Down
2 changes: 1 addition & 1 deletion src/TensorFlowNET.Core/Exceptions/RuntimeError.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace Tensorflow
{
public class RuntimeError : Exception
public class RuntimeError : TensorflowException
{
public RuntimeError() : base()
{
Expand Down
36 changes: 36 additions & 0 deletions src/TensorFlowNET.Core/Exceptions/TensorflowException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System;
using System.Runtime.Serialization;

namespace Tensorflow
{

/// <summary>
/// Serves as a base class to all exceptions of Tensorflow.NET.
/// </summary>
[Serializable]
public class TensorflowException : Exception
{
/// <summary>Initializes a new instance of the <see cref="T:System.Exception"></see> class.</summary>
public TensorflowException()
{ }

/// <summary>Initializes a new instance of the <see cref="T:System.Exception"></see> class with serialized data.</summary>
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"></see> that holds the serialized object data about the exception being thrown.</param>
/// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"></see> that contains contextual information about the source or destination.</param>
/// <exception cref="T:System.ArgumentNullException">The <paramref name="info">info</paramref> parameter is null.</exception>
/// <exception cref="T:System.Runtime.Serialization.SerializationException">The class name is null or <see cref="P:System.Exception.HResult"></see> is zero (0).</exception>
protected TensorflowException(SerializationInfo info, StreamingContext context) : base(info, context)
{ }

/// <summary>Initializes a new instance of the <see cref="T:System.Exception"></see> class with a specified error message.</summary>
/// <param name="message">The message that describes the error.</param>
public TensorflowException(string message) : base(message)
{ }

/// <summary>Initializes a new instance of the <see cref="T:System.Exception"></see> class with a specified error message and a reference to the inner exception that is the cause of this exception.</summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified.</param>
public TensorflowException(string message, Exception innerException) : base(message, innerException)
{ }
}
}
Loading