| @@ -62,8 +62,14 @@ namespace Tensorflow.NumPy | |||||
| var tensor = base[slices.ToArray()]; | var tensor = base[slices.ToArray()]; | ||||
| if (tensor.Handle == null) | if (tensor.Handle == null) | ||||
| tensor = tf.defaultSession.eval(tensor); | |||||
| return new NDArray(tensor.Handle); | |||||
| { | |||||
| if (tf.executing_eagerly()) | |||||
| return new NDArray(tensor); | |||||
| else | |||||
| tensor = tf.defaultSession.eval(tensor); | |||||
| } | |||||
| return new NDArray(tensor); | |||||
| } | } | ||||
| unsafe T GetAtIndex<T>(params int[] indices) where T : unmanaged | unsafe T GetAtIndex<T>(params int[] indices) where T : unmanaged | ||||
| @@ -97,9 +97,6 @@ namespace Tensorflow | |||||
| /// </summary> | /// </summary> | ||||
| public SafeTensorHandleHandle EagerTensorHandle => _eagerTensorHandle; | public SafeTensorHandleHandle EagerTensorHandle => _eagerTensorHandle; | ||||
| protected bool isReferencedByNDArray; | |||||
| public bool IsReferencedByNDArray => isReferencedByNDArray; | |||||
| protected bool isCreatedInGraphMode; | protected bool isCreatedInGraphMode; | ||||
| public bool IsCreatedInGraphMode => isCreatedInGraphMode; | public bool IsCreatedInGraphMode => isCreatedInGraphMode; | ||||
| @@ -214,15 +211,6 @@ namespace Tensorflow | |||||
| return _tf_output.Value; | return _tf_output.Value; | ||||
| } | } | ||||
| public void SetReferencedByNDArray() | |||||
| { | |||||
| if (_handle is not null) | |||||
| { | |||||
| isReferencedByNDArray = true; | |||||
| _eagerTensorHandle = c_api.TFE_NewTensorHandle(_handle, tf.Status.Handle); | |||||
| } | |||||
| } | |||||
| public Tensor MaybeMove() | public Tensor MaybeMove() | ||||
| { | { | ||||
| @@ -141,12 +141,6 @@ namespace Tensorflow | |||||
| byte[] bytes = nd.ToByteArray(); | byte[] bytes = nd.ToByteArray(); | ||||
| tensor_proto.TensorContent = Google.Protobuf.ByteString.CopyFrom(bytes); | tensor_proto.TensorContent = Google.Protobuf.ByteString.CopyFrom(bytes); | ||||
| } | } | ||||
| else if (values is Tensor tensor && tensor.IsReferencedByNDArray) | |||||
| { | |||||
| var len = tensor.dtypesize * tensor.size; | |||||
| byte[] bytes = tensor.BufferToArray(); | |||||
| tensor_proto.TensorContent = Google.Protobuf.ByteString.CopyFrom(bytes); | |||||
| } | |||||
| else if (!values.GetType().IsArray) | else if (!values.GetType().IsArray) | ||||
| { | { | ||||
| switch (values) | switch (values) | ||||
| @@ -149,13 +149,6 @@ namespace Tensorflow | |||||
| else | else | ||||
| return constant_op.constant(nd); | return constant_op.constant(nd); | ||||
| } | } | ||||
| else if (value is Tensor tensor && tensor.IsReferencedByNDArray) | |||||
| { | |||||
| if (tf.executing_eagerly()) | |||||
| return tensor; | |||||
| else | |||||
| return constant_op.constant(tensor); | |||||
| } | |||||
| // graph mode | // graph mode | ||||
| Tensor ret = value switch | Tensor ret = value switch | ||||
| @@ -50,7 +50,7 @@ namespace Tensorflow.Benchmark.Leak | |||||
| optimizer: keras.optimizers.RMSprop(), | optimizer: keras.optimizers.RMSprop(), | ||||
| metrics: new[] { "accuracy" }); | metrics: new[] { "accuracy" }); | ||||
| model.fit(new NDArray(inputImages), outLables, batch_size: 32, epochs: 200); | |||||
| model.fit(inputImages, outLables, batch_size: 32, epochs: 200); | |||||
| keras.backend.clear_session(); | keras.backend.clear_session(); | ||||
| } | } | ||||
| @@ -74,9 +74,6 @@ namespace Tensorflow.Native.UnitTest | |||||
| protected SafeStatusHandle TF_NewStatus() | protected SafeStatusHandle TF_NewStatus() | ||||
| => c_api.TF_NewStatus(); | => c_api.TF_NewStatus(); | ||||
| protected void TF_DeleteTensor(SafeTensorHandle t) | |||||
| => c_api.TF_DeleteTensor(t.DangerousGetHandle()); | |||||
| protected IntPtr TF_TensorData(SafeTensorHandle t) | protected IntPtr TF_TensorData(SafeTensorHandle t) | ||||
| => c_api.TF_TensorData(t); | => c_api.TF_TensorData(t); | ||||
| @@ -58,7 +58,7 @@ namespace Tensorflow.Native.UnitTest.Eager | |||||
| EXPECT_EQ(product.Length * sizeof(float), (int)TF_TensorByteSize(t)); | EXPECT_EQ(product.Length * sizeof(float), (int)TF_TensorByteSize(t)); | ||||
| tf.memcpy(product, TF_TensorData(t), TF_TensorByteSize(t)); | tf.memcpy(product, TF_TensorData(t), TF_TensorByteSize(t)); | ||||
| c_api.TF_DeleteTensor(t.DangerousGetHandle()); | |||||
| t.Dispose(); | |||||
| EXPECT_EQ(7f, product[0]); | EXPECT_EQ(7f, product[0]); | ||||
| EXPECT_EQ(10f, product[1]); | EXPECT_EQ(10f, product[1]); | ||||
| EXPECT_EQ(15f, product[2]); | EXPECT_EQ(15f, product[2]); | ||||
| @@ -25,7 +25,7 @@ namespace Tensorflow.Native.UnitTest.Eager | |||||
| EXPECT_EQ(2.0f, data[1]); | EXPECT_EQ(2.0f, data[1]); | ||||
| EXPECT_EQ(3.0f, data[2]); | EXPECT_EQ(3.0f, data[2]); | ||||
| EXPECT_EQ(4.0f, data[3]); | EXPECT_EQ(4.0f, data[3]); | ||||
| c_api.TF_DeleteTensor(t.DangerousGetHandle()); | |||||
| t.Dispose(); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -51,7 +51,7 @@ namespace Tensorflow.Native.UnitTest.Eager | |||||
| ASSERT_EQ(TF_OK, TF_GetCode(status), TF_Message(status)); | ASSERT_EQ(TF_OK, TF_GetCode(status), TF_Message(status)); | ||||
| ASSERT_EQ(sizeof(float), (int)TF_TensorByteSize(t)); | ASSERT_EQ(sizeof(float), (int)TF_TensorByteSize(t)); | ||||
| tf.memcpy(&value, TF_TensorData(t).ToPointer(), sizeof(float)); | tf.memcpy(&value, TF_TensorData(t).ToPointer(), sizeof(float)); | ||||
| c_api.TF_DeleteTensor(t.DangerousGetHandle()); | |||||
| t.Dispose(); | |||||
| EXPECT_EQ(12.0f, value); | EXPECT_EQ(12.0f, value); | ||||
| } | } | ||||
| finally | finally | ||||
| @@ -21,7 +21,7 @@ namespace Tensorflow.Native.UnitTest.Eager | |||||
| using var status = c_api.TF_NewStatus(); | using var status = c_api.TF_NewStatus(); | ||||
| var th = c_api.TFE_NewTensorHandle(t, status); | var th = c_api.TFE_NewTensorHandle(t, status); | ||||
| CHECK_EQ(TF_OK, TF_GetCode(status), TF_Message(status)); | CHECK_EQ(TF_OK, TF_GetCode(status), TF_Message(status)); | ||||
| c_api.TF_DeleteTensor(t.DangerousGetHandle()); | |||||
| t.Dispose(); | |||||
| return th; | return th; | ||||
| } | } | ||||
| @@ -127,7 +127,7 @@ namespace Tensorflow.Native.UnitTest.Eager | |||||
| using var status = TF_NewStatus(); | using var status = TF_NewStatus(); | ||||
| var th = c_api.TFE_NewTensorHandle(t, status); | var th = c_api.TFE_NewTensorHandle(t, status); | ||||
| CHECK_EQ(TF_OK, TF_GetCode(status), TF_Message(status)); | CHECK_EQ(TF_OK, TF_GetCode(status), TF_Message(status)); | ||||
| TF_DeleteTensor(t); | |||||
| t.Dispose(); | |||||
| return th; | return th; | ||||
| } | } | ||||
| @@ -139,7 +139,7 @@ namespace Tensorflow.Native.UnitTest.Eager | |||||
| using var status = TF_NewStatus(); | using var status = TF_NewStatus(); | ||||
| var th = TFE_NewTensorHandle(t, status); | var th = TFE_NewTensorHandle(t, status); | ||||
| CHECK_EQ(TF_OK, TF_GetCode(status), TF_Message(status)); | CHECK_EQ(TF_OK, TF_GetCode(status), TF_Message(status)); | ||||
| TF_DeleteTensor(t); | |||||
| t.Dispose(); | |||||
| return th; | return th; | ||||
| } | } | ||||
| @@ -151,7 +151,7 @@ namespace Tensorflow.Native.UnitTest.Eager | |||||
| using var status = TF_NewStatus(); | using var status = TF_NewStatus(); | ||||
| var th = TFE_NewTensorHandle(t, status); | var th = TFE_NewTensorHandle(t, status); | ||||
| CHECK_EQ(TF_OK, TF_GetCode(status), TF_Message(status)); | CHECK_EQ(TF_OK, TF_GetCode(status), TF_Message(status)); | ||||
| TF_DeleteTensor(t); | |||||
| t.Dispose(); | |||||
| return th; | return th; | ||||
| } | } | ||||
| } | } | ||||
| @@ -64,7 +64,7 @@ namespace Tensorflow.Native.UnitTest | |||||
| foreach (var output in outputs) | foreach (var output in outputs) | ||||
| { | { | ||||
| outputs_.Add(output); | outputs_.Add(output); | ||||
| output_values_.Add(new SafeTensorHandle(IntPtr.Zero)); | |||||
| output_values_.Add(null); | |||||
| } | } | ||||
| } | } | ||||
| @@ -39,24 +39,18 @@ namespace Tensorflow.Native.UnitTest.Tensors | |||||
| public void TensorFromArray() | public void TensorFromArray() | ||||
| { | { | ||||
| var array = new float[1000]; | var array = new float[1000]; | ||||
| /*using (var t = new Tensor(array, new long[] { array.Length }, tf.float32)) | |||||
| using (var t = new Tensor(array)) | |||||
| { | { | ||||
| Assert.IsFalse(t.IsDisposed); | Assert.IsFalse(t.IsDisposed); | ||||
| Assert.AreEqual(1000 * sizeof(float), (int)t.bytesize); | Assert.AreEqual(1000 * sizeof(float), (int)t.bytesize); | ||||
| } | } | ||||
| using (var t = new Tensor(new float[] { 1 }, new long[] { 1 }, tf.float32)) | |||||
| using (var t = new Tensor(1)) | |||||
| { | { | ||||
| Assert.IsFalse(t.IsDisposed); | Assert.IsFalse(t.IsDisposed); | ||||
| Assert.AreEqual(1 * sizeof(float), (int)t.bytesize); | Assert.AreEqual(1 * sizeof(float), (int)t.bytesize); | ||||
| Assert.AreEqual(t.shape, Shape.Scalar); | |||||
| } | } | ||||
| using (var t = new Tensor(new float[] { 1 }, null, tf.float32)) | |||||
| { | |||||
| Assert.IsFalse(t.IsDisposed); | |||||
| Assert.AreEqual(1 * sizeof(float), (int)t.bytesize); | |||||
| t.shape.Should().BeEmpty(); | |||||
| }*/ | |||||
| } | } | ||||
| [TestMethod] | [TestMethod] | ||||
| @@ -80,8 +74,7 @@ namespace Tensorflow.Native.UnitTest.Tensors | |||||
| [TestMethod, Ignore] | [TestMethod, Ignore] | ||||
| public void MaybeMove() | public void MaybeMove() | ||||
| { | { | ||||
| NDArray nd = np.array(2, 3); | |||||
| Tensor t = new Tensor(nd); | |||||
| Tensor t = new Tensor(new[] { 2, 3 }); | |||||
| Tensor o = t.MaybeMove(); | Tensor o = t.MaybeMove(); | ||||
| ASSERT_TRUE(o.Handle.IsInvalid); // It is unsafe to move memory TF might not own. | ASSERT_TRUE(o.Handle.IsInvalid); // It is unsafe to move memory TF might not own. | ||||
| t.Dispose(); | t.Dispose(); | ||||
| @@ -94,17 +87,15 @@ namespace Tensorflow.Native.UnitTest.Tensors | |||||
| [TestMethod] | [TestMethod] | ||||
| public void Tensor() | public void Tensor() | ||||
| { | { | ||||
| var nd = np.array(1f, 2f, 3f, 4f, 5f, 6f).reshape((2, 3)); | |||||
| var tensor = new Tensor(nd); | |||||
| var array = tensor.ToArray<float>(); | |||||
| var array = new[] { 1f, 2f, 3f, 4f, 5f, 6f }; | |||||
| var tensor = new Tensor(array, (2, 3)); | |||||
| EXPECT_EQ(tensor.dtype, TF_DataType.TF_FLOAT); | EXPECT_EQ(tensor.dtype, TF_DataType.TF_FLOAT); | ||||
| EXPECT_EQ(tensor.rank, nd.ndim); | |||||
| EXPECT_EQ(tensor.shape[0], nd.dims[0]); | |||||
| EXPECT_EQ(tensor.shape[1], nd.dims[1]); | |||||
| EXPECT_EQ(tensor.bytesize, nd.size * sizeof(float)); | |||||
| Assert.IsTrue(Enumerable.SequenceEqual(nd.ToArray<float>(), new float[] { 1, 2, 3, 4, 5, 6 })); | |||||
| EXPECT_EQ(tensor.rank, 2); | |||||
| EXPECT_EQ(tensor.shape[0], 2L); | |||||
| EXPECT_EQ(tensor.shape[1], 3L); | |||||
| EXPECT_EQ(tensor.bytesize, 6ul * sizeof(float)); | |||||
| Assert.IsTrue(Enumerable.SequenceEqual(tensor.ToArray<float>(), new float[] { 1, 2, 3, 4, 5, 6 })); | |||||
| } | } | ||||
| /// <summary> | /// <summary> | ||||
| @@ -130,7 +121,7 @@ namespace Tensorflow.Native.UnitTest.Tensors | |||||
| Assert.AreEqual(TF_TString_Type.TF_TSTR_SMALL, c_api.TF_StringGetType(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); | |||||
| tensor.Dispose(); | |||||
| c_api.TF_StringDealloc(tstr); | c_api.TF_StringDealloc(tstr); | ||||
| } | } | ||||
| @@ -141,7 +141,7 @@ namespace TensorFlowNET.UnitTest | |||||
| public void assertAllClose(double value, NDArray array2, double eps = 1e-5) | public void assertAllClose(double value, NDArray array2, double eps = 1e-5) | ||||
| { | { | ||||
| var array1 = np.ones_like(array2) * value; | var array1 = np.ones_like(array2) * value; | ||||
| Assert.IsTrue(np.allclose(new NDArray(array1), array2, rtol: eps)); | |||||
| Assert.IsTrue(np.allclose(array1, array2, rtol: eps)); | |||||
| } | } | ||||
| public void assertProtoEquals(object toProto, object o) | public void assertProtoEquals(object toProto, object o) | ||||