From 19228bd14292ede64821565e6f1c36b7aef2024c Mon Sep 17 00:00:00 2001 From: Leo Chen Date: Fri, 11 Sep 2020 18:57:06 +0800 Subject: [PATCH] Temporally disable zero_copy (#27248) * temporally disable zero_copy * add test * follow comments --- python/paddle/fluid/dygraph/base.py | 18 +++++++++++++---- .../unittests/test_imperative_numpy_bridge.py | 20 +++++++++++++------ python/paddle/tensor/creation.py | 9 ++++----- 3 files changed, 32 insertions(+), 15 deletions(-) diff --git a/python/paddle/fluid/dygraph/base.py b/python/paddle/fluid/dygraph/base.py index c548bdfeba..2f95c2b900 100644 --- a/python/paddle/fluid/dygraph/base.py +++ b/python/paddle/fluid/dygraph/base.py @@ -25,6 +25,7 @@ from .tracer import Tracer import logging import objgraph from ..data_feeder import convert_dtype +import warnings __all__ = [ 'no_grad', 'no_grad_', 'grad', 'guard', 'enable_dygraph', 'disable_dygraph', @@ -609,10 +610,10 @@ def to_variable(value, name=None, zero_copy=None, dtype=None): uint8, uint16, complex64, complex128}. name(str, optional): The default value is None. Normally there is no need for user to set this property. For more information, please - refer to :ref:`api_guide_Name` . + refer to :ref:`api_guide_Name` . zero_copy(bool, optional): Whether to share memory with the input numpy array. This parameter only works with CPUPlace and will be set to - True when it is None. Default: None. + True when it is None. Default: None. (Note: zero_copy is discarded temporally for some reason.) dtype(str, optional): The desired data type of returned ``Variable`` . Can be 'bool' , 'float16' , 'float32' , 'float64' , 'int8' , 'int16' , 'int32' , 'int64' , 'uint8' . Default: None. @@ -665,8 +666,17 @@ def to_variable(value, name=None, zero_copy=None, dtype=None): else: if isinstance(framework._current_expected_place(), framework.core.CPUPlace): - if zero_copy is None: - zero_copy = True + #TODO(zhiqiu): we found two problems when enable zero_copy on CPUPlace. + # (1): eigen requires 16-bytes alignments, but the data of numpy array may not statisfy. + # Details: https://eigen.tuxfamily.org/dox/group__TopicUnalignedArrayAssert.html + # (2): when used in flask framework, it may result in hang. + # Details: https://github.com/PaddlePaddle/Paddle/issues/26635 + # So, we temporally diable the zero_copy strategy. + if zero_copy == True: + warnings.warn( + "Currently, zero_copy is not supported, and it will be discarded." + ) + zero_copy = False else: assert not zero_copy, "zero_copy mode can only be used with CPUPlace" diff --git a/python/paddle/fluid/tests/unittests/test_imperative_numpy_bridge.py b/python/paddle/fluid/tests/unittests/test_imperative_numpy_bridge.py index da01be8159..772dd913e4 100644 --- a/python/paddle/fluid/tests/unittests/test_imperative_numpy_bridge.py +++ b/python/paddle/fluid/tests/unittests/test_imperative_numpy_bridge.py @@ -15,18 +15,26 @@ import unittest import numpy as np import paddle.fluid as fluid +import warnings class TestImperativeNumpyBridge(unittest.TestCase): def test_tensor_from_numpy(self): data_np = np.array([[2, 3, 1]]).astype('float32') with fluid.dygraph.guard(fluid.CPUPlace()): - var = fluid.dygraph.to_variable(data_np, zero_copy=True) - self.assertTrue(np.array_equal(var.numpy(), data_np)) - data_np[0][0] = 4 - self.assertEqual(data_np[0][0], 4) - self.assertEqual(var[0][0].numpy()[0], 4) - self.assertTrue(np.array_equal(var.numpy(), data_np)) + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + var = fluid.dygraph.to_variable(data_np, zero_copy=True) + assert "Currently, zero_copy is not supported, and it will be discarded." in str( + w[-1].message) + # Temporally diable zero_copy + # var = fluid.dygraph.to_variable(data_np, zero_copy=True) + # self.assertTrue(np.array_equal(var.numpy(), data_np)) + # data_np[0][0] = 4 + # self.assertEqual(data_np[0][0], 4) + # self.assertEqual(var[0][0].numpy()[0], 4) + # self.assertTrue(np.array_equal(var.numpy(), data_np)) + var2 = fluid.dygraph.to_variable(data_np, zero_copy=False) self.assertTrue(np.array_equal(var2.numpy(), data_np)) data_np[0][0] = -1 diff --git a/python/paddle/tensor/creation.py b/python/paddle/tensor/creation.py index b75e2a8851..8011b92964 100644 --- a/python/paddle/tensor/creation.py +++ b/python/paddle/tensor/creation.py @@ -63,8 +63,7 @@ def to_tensor(data, dtype=None, place=None, stop_gradient=True): If the ``data`` is already a tensor, and ``dtype`` or ``place`` does't change, no copy will be performed and return origin tensor, otherwise a new tensor will be constructed - and returned. Similarly, if the data is an numpy\.ndarray of with the same ``dtype`` - and the current place is cpu, no copy will be performed. + and returned. The ``ComplexTensor`` is a unique type of paddle. If x is ``ComplexTensor``, then ``x.real`` is the real part, and ``x.imag`` is the imaginary part. @@ -209,20 +208,20 @@ def to_tensor(data, dtype=None, place=None, stop_gradient=True): value=data, place=place, persistable=False, - zero_copy=True, + zero_copy=False, stop_gradient=stop_gradient) else: name = unique_name.generate('generated_tensor') real_tensor = paddle.Tensor( value=data.real, place=place, - zero_copy=True, + zero_copy=False, name=name + ".real", stop_gradient=stop_gradient) imag_tensor = paddle.Tensor( value=data.imag, place=place, - zero_copy=True, + zero_copy=False, name=name + ".imag", stop_gradient=stop_gradient) return paddle.ComplexTensor(real_tensor, imag_tensor) -- GitLab