Browse Source

Align with tensorflow v2.4.1

tags/v0.40-tf2.4-tstring
Oceania2018 4 years ago
parent
commit
ad6ad8493c
8 changed files with 62 additions and 101 deletions
  1. +7
    -3
      src/TensorFlowNET.Console/MemoryBasicTest.cs
  2. +1
    -1
      src/TensorFlowNET.Console/Program.cs
  3. +1
    -1
      src/TensorFlowNET.Core/APIs/c_api.cs
  4. +6
    -4
      src/TensorFlowNET.Core/Tensorflow.Binding.csproj
  5. +22
    -85
      src/TensorFlowNET.Core/Tensors/Tensor.String.cs
  6. +16
    -2
      src/TensorFlowNET.Core/Tensors/Tensor.cs
  7. +4
    -1
      src/TensorFlowNET.Core/Tensors/c_api.tensor.cs
  8. +5
    -4
      test/TensorFlowNET.Native.UnitTest/Tensors/TensorTest.cs

+ 7
- 3
src/TensorFlowNET.Console/MemoryBasicTest.cs View File

@@ -4,6 +4,8 @@ using Tensorflow.Keras.ArgsDefinition;
using Tensorflow.Keras.Engine.DataAdapters; using Tensorflow.Keras.Engine.DataAdapters;
using static Tensorflow.Binding; using static Tensorflow.Binding;
using static Tensorflow.KerasApi; using static Tensorflow.KerasApi;
using System.Linq;
using System.Collections.Generic;


namespace Tensorflow namespace Tensorflow
{ {
@@ -35,13 +37,15 @@ namespace Tensorflow
public Action<int, int> ConstantString public Action<int, int> ConstantString
=> (epoch, iterate) => => (epoch, iterate) =>
{ {
var tensor = tf.constant(new string[]
var strList = new string[]
{ {
"Biden immigration bill would put millions of illegal immigrants on 8-year fast-track to citizenship", "Biden immigration bill would put millions of illegal immigrants on 8-year fast-track to citizenship",
"The Associated Press, which also reported that the eight-year path is in the bill.", "The Associated Press, which also reported that the eight-year path is in the bill.",
"The bill would also include provisions to stem the flow of migration by addressing root causes of migration from south of the border." "The bill would also include provisions to stem the flow of migration by addressing root causes of migration from south of the border."
});
var data = tensor.numpy();
};

var tensor = tf.constant(strList, TF_DataType.TF_STRING);
var data = tensor.StringData();
}; };


public Action<int, int> Variable public Action<int, int> Variable


+ 1
- 1
src/TensorFlowNET.Console/Program.cs View File

@@ -47,7 +47,7 @@ namespace Tensorflow
// explaination of constant // explaination of constant
mm.Execute(10, 100 * batchSize, basic.Constant2x3); mm.Execute(10, 100 * batchSize, basic.Constant2x3);


mm.Execute(10, 100 * batchSize, basic.ConstantString);
mm.Execute(10, batchSize, basic.ConstantString);


// 100K float variable. // 100K float variable.
mm.Execute(10, batchSize, basic.Variable); mm.Execute(10, batchSize, basic.Variable);


+ 1
- 1
src/TensorFlowNET.Core/APIs/c_api.cs View File

@@ -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:\Projects\tensorflow-haiping\bazel-bin\tensorflow\tensorflow";


public static string StringPiece(IntPtr handle) public static string StringPiece(IntPtr handle)
{ {


+ 6
- 4
src/TensorFlowNET.Core/Tensorflow.Binding.csproj View File

@@ -5,7 +5,7 @@
<AssemblyName>TensorFlow.NET</AssemblyName> <AssemblyName>TensorFlow.NET</AssemblyName>
<RootNamespace>Tensorflow</RootNamespace> <RootNamespace>Tensorflow</RootNamespace>
<TargetTensorFlow>2.2.0</TargetTensorFlow> <TargetTensorFlow>2.2.0</TargetTensorFlow>
<Version>0.33.0</Version>
<Version>0.40.0</Version>
<LangVersion>8.0</LangVersion> <LangVersion>8.0</LangVersion>
<Authors>Haiping Chen, Meinrad Recheis, Eli Belash</Authors> <Authors>Haiping Chen, Meinrad Recheis, Eli Belash</Authors>
<Company>SciSharp STACK</Company> <Company>SciSharp STACK</Company>
@@ -19,7 +19,7 @@
<Description>Google's TensorFlow full binding in .NET Standard. <Description>Google's TensorFlow full binding in .NET Standard.
Building, training and infering deep learning models. Building, training and infering deep learning models.
https://tensorflownet.readthedocs.io</Description> https://tensorflownet.readthedocs.io</Description>
<AssemblyVersion>0.33.0.0</AssemblyVersion>
<AssemblyVersion>0.40.0.0</AssemblyVersion>
<PackageReleaseNotes>tf.net 0.20.x and above are based on tensorflow native 2.x. <PackageReleaseNotes>tf.net 0.20.x and above are based on tensorflow native 2.x.


* Eager Mode is added finally. * Eager Mode is added finally.
@@ -29,8 +29,10 @@ https://tensorflownet.readthedocs.io</Description>
* Improve memory usage. * Improve memory usage.


TensorFlow .NET v0.3x is focused on making more Keras API works. TensorFlow .NET v0.3x is focused on making more Keras API works.
Keras API is a separate package released as TensorFlow.Keras.</PackageReleaseNotes>
<FileVersion>0.33.0.0</FileVersion>
Keras API is a separate package released as TensorFlow.Keras.

tf.net 0.4x.x aligns with TensorFlow v2.4.1 native library.</PackageReleaseNotes>
<FileVersion>0.40.0.0</FileVersion>
<PackageLicenseFile>LICENSE</PackageLicenseFile> <PackageLicenseFile>LICENSE</PackageLicenseFile>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance> <PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<SignAssembly>true</SignAssembly> <SignAssembly>true</SignAssembly>


+ 22
- 85
src/TensorFlowNET.Core/Tensors/Tensor.String.cs View File

@@ -8,27 +8,7 @@ namespace Tensorflow
{ {
public partial class Tensor public partial class Tensor
{ {
const ulong TF_TSRING_SIZE = 24;

public IntPtr StringTensor25(string[] strings, TensorShape shape)
{
var handle = c_api.TF_AllocateTensor(TF_DataType.TF_STRING,
shape.dims.Select(x => (long)x).ToArray(),
shape.ndim,
(ulong)shape.size * TF_TSRING_SIZE);

var data = c_api.TF_TensorData(handle);
var tstr = c_api.TF_StringInit(handle);
// AllocationHandle = tstr;
// AllocationType = AllocationType.Tensorflow;
for (int i = 0; i< strings.Length; i++)
{
c_api.TF_StringCopy(tstr, strings[i], strings[i].Length);
tstr += (int)TF_TSRING_SIZE;
}
// c_api.TF_StringDealloc(tstr);
return handle;
}
const int TF_TSRING_SIZE = 24;


public IntPtr StringTensor(string[] strings, TensorShape shape) public IntPtr StringTensor(string[] strings, TensorShape shape)
{ {
@@ -40,69 +20,28 @@ namespace Tensorflow
return StringTensor(buffer, shape); return StringTensor(buffer, shape);
} }


public unsafe IntPtr StringTensor(byte[][] buffer, TensorShape shape)
public IntPtr StringTensor(byte[][] buffer, TensorShape shape)
{ {
ulong size = 0;
foreach (var b in buffer)
size += c_api.TF_StringEncodedSize((ulong)b.Length);

var src_size = size + (ulong)buffer.Length * sizeof(ulong);
var handle = c_api.TF_AllocateTensor(TF_DataType.TF_STRING, var handle = c_api.TF_AllocateTensor(TF_DataType.TF_STRING,
shape.dims.Select(x => (long)x).ToArray(),
shape.ndim == 0 ? null : shape.dims.Select(x => (long)x).ToArray(),
shape.ndim, shape.ndim,
src_size);
AllocationType = AllocationType.Tensorflow;
(ulong)shape.size * TF_TSRING_SIZE);


IntPtr data_start = c_api.TF_TensorData(handle);
IntPtr string_start = data_start + buffer.Length * sizeof(ulong);
IntPtr limit = data_start + (int)src_size;
ulong offset = 0;
var tstr = c_api.TF_TensorData(handle);
#if TRACK_TENSOR_LIFE
print($"New TString 0x{handle.ToString("x16")} {AllocationType} Data: 0x{tstr.ToString("x16")}");
#endif
for (int i = 0; i < buffer.Length; i++) for (int i = 0; i < buffer.Length; i++)
{ {
Marshal.WriteInt64(data_start, i * sizeof(ulong), (long)offset);
if (buffer[i].Length == 0)
{
Marshal.WriteByte(string_start, 0);
break;
}

fixed (byte* src = &buffer[i][0])
{
/*Marshal.WriteByte(string_start, Convert.ToByte(buffer[i].Length));
tf.memcpy((string_start + 1).ToPointer(), src, (ulong)buffer[i].Length);
string_start += buffer[i].Length + 1;
offset += buffer[i].Length + 1;*/

var written = c_api.TF_StringEncode(src, (ulong)buffer[i].Length, (byte*)string_start, (ulong)(limit.ToInt64() - string_start.ToInt64()), tf.Status.Handle);
tf.Status.Check(true);
string_start += (int)written;
offset += written;
}
c_api.TF_StringInit(tstr);
c_api.TF_StringCopy(tstr, buffer[i], buffer[i].Length);
var data = c_api.TF_StringGetDataPointer(tstr);
tstr += TF_TSRING_SIZE;
} }


return handle; return handle;
} }


public string[] StringData25()
{
string[] strings = new string[c_api.TF_Dim(_handle, 0)];
var tstrings = TensorDataPointer;
for (int i = 0; i< strings.Length; i++)
{
var tstringData = c_api.TF_StringGetDataPointer(tstrings);
/*var size = c_api.TF_StringGetSize(tstrings);
var capacity = c_api.TF_StringGetCapacity(tstrings);
var type = c_api.TF_StringGetType(tstrings);*/
strings[i] = c_api.StringPiece(tstringData);
tstrings += (int)TF_TSRING_SIZE;
}
return strings;
}

/// <summary>
/// Extracts string array from current Tensor.
/// </summary>
/// <exception cref="InvalidOperationException">When <see cref="dtype"/> != TF_DataType.TF_STRING</exception>
public string[] StringData() public string[] StringData()
{ {
var buffer = StringBytes(); var buffer = StringBytes();
@@ -114,7 +53,7 @@ namespace Tensorflow
return _str; return _str;
} }


public unsafe byte[][] StringBytes()
public byte[][] StringBytes()
{ {
if (dtype != TF_DataType.TF_STRING) if (dtype != TF_DataType.TF_STRING)
throw new InvalidOperationException($"Unable to call StringData when dtype != TF_DataType.TF_STRING (dtype is {dtype})"); throw new InvalidOperationException($"Unable to call StringData when dtype != TF_DataType.TF_STRING (dtype is {dtype})");
@@ -123,24 +62,22 @@ namespace Tensorflow
// TF_STRING tensors are encoded with a table of 8-byte offsets followed by TF_StringEncode-encoded bytes. // TF_STRING tensors are encoded with a table of 8-byte offsets followed by TF_StringEncode-encoded bytes.
// [offset1, offset2,...,offsetn, s1size, s1bytes, s2size, s2bytes,...,snsize,snbytes] // [offset1, offset2,...,offsetn, s1size, s1bytes, s2size, s2bytes,...,snsize,snbytes]
// //
long size = 1;
int size = 1;
foreach (var s in TensorShape.dims) foreach (var s in TensorShape.dims)
size *= s; size *= s;


var buffer = new byte[size][]; var buffer = new byte[size][];
var data_start = c_api.TF_TensorData(_handle);
data_start += (int)(size * sizeof(ulong));
var tstrings = TensorDataPointer;
for (int i = 0; i < buffer.Length; i++) for (int i = 0; i < buffer.Length; i++)
{ {
IntPtr dst = IntPtr.Zero;
ulong dstLen = 0;
var read = c_api.TF_StringDecode((byte*)data_start, bytesize, (byte**)&dst, ref dstLen, tf.Status.Handle);
tf.Status.Check(true);
buffer[i] = new byte[(int)dstLen];
Marshal.Copy(dst, buffer[i], 0, buffer[i].Length);
data_start += (int)read;
var data = c_api.TF_StringGetDataPointer(tstrings);
var len = c_api.TF_StringGetSize(tstrings);
buffer[i] = new byte[len];
// var capacity = c_api.TF_StringGetCapacity(tstrings);
// var type = c_api.TF_StringGetType(tstrings);
Marshal.Copy(data, buffer[i], 0, Convert.ToInt32(len));
tstrings += TF_TSRING_SIZE;
} }

return buffer; return buffer;
} }
} }


+ 16
- 2
src/TensorFlowNET.Core/Tensors/Tensor.cs View File

@@ -15,7 +15,6 @@
******************************************************************************/ ******************************************************************************/


using NumSharp; using NumSharp;
using NumSharp.Backends.Unmanaged;
using System; using System;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Globalization; using System.Globalization;
@@ -24,7 +23,6 @@ using System.Runtime.InteropServices;
using Tensorflow.Eager; using Tensorflow.Eager;
using Tensorflow.Framework; using Tensorflow.Framework;
using Tensorflow.Keras.Engine; using Tensorflow.Keras.Engine;
using Tensorflow.Variables;
using static Tensorflow.Binding; using static Tensorflow.Binding;


namespace Tensorflow namespace Tensorflow
@@ -287,6 +285,22 @@ namespace Tensorflow
throw new InvalidOperationException($"Tensor.AllocationHandle is not null ({AllocationHandle}) but AllocationType is not matched to a C# allocation type ({AllocationType})."); throw new InvalidOperationException($"Tensor.AllocationHandle is not null ({AllocationHandle}) but AllocationType is not matched to a C# allocation type ({AllocationType}).");
} }


if (dtype == TF_DataType.TF_STRING)
{
int size = 1;
foreach (var s in TensorShape.dims)
size *= s;
var tstr = TensorDataPointer;
#if TRACK_TENSOR_LIFE
print($"Delete TString 0x{handle.ToString("x16")} {AllocationType} Data: 0x{tstrings.ToString("x16")}");
#endif
for (int i = 0; i < size; i++)
{
c_api.TF_StringDealloc(tstr);
tstr += TF_TSRING_SIZE;
}
}

c_api.TF_DeleteTensor(handle); c_api.TF_DeleteTensor(handle);
} }




+ 4
- 1
src/TensorFlowNET.Core/Tensors/c_api.tensor.cs View File

@@ -182,7 +182,10 @@ namespace Tensorflow
public static extern unsafe ulong TF_StringEncode(byte* src, ulong src_len, byte* dst, ulong dst_len, SafeStatusHandle status); public static extern unsafe ulong TF_StringEncode(byte* src, ulong src_len, byte* dst, ulong dst_len, SafeStatusHandle status);


[DllImport(TensorFlowLibName)] [DllImport(TensorFlowLibName)]
public static extern IntPtr TF_StringInit(IntPtr t);
public static extern void TF_StringInit(IntPtr t);

[DllImport(TensorFlowLibName)]
public static extern void TF_StringCopy(IntPtr dst, byte[] text, long size);


[DllImport(TensorFlowLibName)] [DllImport(TensorFlowLibName)]
public static extern void TF_StringCopy(IntPtr dst, string text, long size); public static extern void TF_StringCopy(IntPtr dst, string text, long size);


+ 5
- 4
test/TensorFlowNET.Native.UnitTest/Tensors/TensorTest.cs View File

@@ -111,7 +111,7 @@ namespace Tensorflow.Native.UnitTest.Tensors
/// Port from c_api_test.cc /// Port from c_api_test.cc
/// `TEST_F(CApiAttributesTest, StringTensor)` /// `TEST_F(CApiAttributesTest, StringTensor)`
/// </summary> /// </summary>
[TestMethod, Ignore("Waiting for PR https://github.com/tensorflow/tensorflow/pull/46804")]
[TestMethod]
public void StringTensor() public void StringTensor()
{ {
string text = "Hello world!."; string text = "Hello world!.";
@@ -120,13 +120,14 @@ namespace Tensorflow.Native.UnitTest.Tensors
null, null,
0, 0,
1 * 24); 1 * 24);
var tstr = c_api.TF_StringInit(tensor);
var data = c_api.TF_StringGetDataPointer(tstr);
var tstr = c_api.TF_TensorData(tensor);
c_api.TF_StringInit(tstr);
c_api.TF_StringCopy(tstr, text, text.Length); c_api.TF_StringCopy(tstr, text, text.Length);
var data = c_api.TF_StringGetDataPointer(tstr);


Assert.AreEqual((ulong)text.Length, c_api.TF_StringGetSize(tstr)); Assert.AreEqual((ulong)text.Length, c_api.TF_StringGetSize(tstr));
Assert.AreEqual(text, c_api.StringPiece(data)); Assert.AreEqual(text, c_api.StringPiece(data));
Assert.AreEqual((ulong)text.Length, c_api.TF_TensorByteSize(tensor));
Assert.AreEqual(TF_TString_Type.TF_TSTR_SMALL, c_api.TF_StringGetType(tensor));
Assert.AreEqual(0, c_api.TF_NumDims(tensor)); Assert.AreEqual(0, c_api.TF_NumDims(tensor));


TF_DeleteTensor(tensor); TF_DeleteTensor(tensor);


Loading…
Cancel
Save