From b4989fb744e026631b111a07269fa1dc6519ffba Mon Sep 17 00:00:00 2001 From: liym27 <33742067+liym27@users.noreply.github.com> Date: Mon, 11 Jan 2021 17:05:00 +0800 Subject: [PATCH] Support vector as type of op attribute and op set_value suppport vector as value (#30126) --- paddle/fluid/framework/attribute.h | 29 ++++++++++++ paddle/fluid/framework/framework.proto | 2 + paddle/fluid/framework/op_desc.cc | 4 ++ paddle/fluid/framework/type_defs.h | 9 ++-- paddle/fluid/operators/set_value_op.cc | 2 + paddle/fluid/operators/set_value_op.h | 4 ++ python/paddle/fluid/framework.py | 7 ++- .../tests/unittests/test_set_value_op.py | 46 +++++++++++++++++-- 8 files changed, 93 insertions(+), 10 deletions(-) diff --git a/paddle/fluid/framework/attribute.h b/paddle/fluid/framework/attribute.h index e516ae1efd..8a56b6dd18 100644 --- a/paddle/fluid/framework/attribute.h +++ b/paddle/fluid/framework/attribute.h @@ -165,6 +165,35 @@ struct ExtractAttribute { const std::string& attr_name_; }; +template <> +struct ExtractAttribute> { + explicit ExtractAttribute(const std::string& attr_name) + : attr_name_(attr_name) {} + + std::vector* operator()(Attribute& attr) const { + if (attr.type() == typeid(std::vector)) { // NOLINT + std::vector val = BOOST_GET_CONST(std::vector, attr); + std::vector vec(val.begin(), val.end()); + attr = vec; + } else if (attr.type() == typeid(std::vector)) { // NOLINT + std::vector val = BOOST_GET_CONST(std::vector, attr); + std::vector vec(val.begin(), val.end()); + attr = vec; + } + std::vector* attr_value = nullptr; + try { + attr_value = &boost::get>(attr); + } catch (boost::bad_get& bad_get) { + PADDLE_THROW(platform::errors::InvalidArgument( + "Cannot get attribute (%s) by type std::vector, its type is " + "%s.", + attr_name_, paddle::platform::demangle(attr.type().name()))); + } + return attr_value; + } + + const std::string& attr_name_; +}; template inline proto::AttrType AttrTypeID() { Attribute tmp = T(); diff --git a/paddle/fluid/framework/framework.proto b/paddle/fluid/framework/framework.proto index baaecb55d0..ff999d829c 100644 --- a/paddle/fluid/framework/framework.proto +++ b/paddle/fluid/framework/framework.proto @@ -35,6 +35,7 @@ enum AttrType { LONG = 9; BLOCKS = 10; LONGS = 11; + FLOAT64S = 12; } // OpDesc describes an instance of a C++ framework::OperatorBase @@ -56,6 +57,7 @@ message OpDesc { optional int64 l = 13; repeated int32 blocks_idx = 14; repeated int64 longs = 15; + repeated double float64s = 16; }; message Var { diff --git a/paddle/fluid/framework/op_desc.cc b/paddle/fluid/framework/op_desc.cc index bccc92e5c4..bb9f7fe1da 100644 --- a/paddle/fluid/framework/op_desc.cc +++ b/paddle/fluid/framework/op_desc.cc @@ -714,6 +714,10 @@ struct SetAttrDescVisitor : public boost::static_visitor { VectorToRepeated(v, attr_->mutable_longs()); } + void operator()(const std::vector &v) const { + VectorToRepeated(v, attr_->mutable_float64s()); + } + void operator()(boost::blank) const { PADDLE_THROW(platform::errors::Unavailable( "Unsupported calling method of SetAttrDescVisitor object for " diff --git a/paddle/fluid/framework/type_defs.h b/paddle/fluid/framework/type_defs.h index 0ff2b2fd73..4d2f07fa49 100644 --- a/paddle/fluid/framework/type_defs.h +++ b/paddle/fluid/framework/type_defs.h @@ -38,11 +38,10 @@ using VariableNameMap = std::map>; using VariableValueMap = std::map>; // The order should be as same as framework.proto -using Attribute = - boost::variant, - std::vector, std::vector, bool, - std::vector, BlockDesc*, int64_t, - std::vector, std::vector>; +using Attribute = boost::variant< + boost::blank, int, float, std::string, std::vector, std::vector, + std::vector, bool, std::vector, BlockDesc*, int64_t, + std::vector, std::vector, std::vector>; using AttributeMap = std::unordered_map; diff --git a/paddle/fluid/operators/set_value_op.cc b/paddle/fluid/operators/set_value_op.cc index a928668a22..1d8bfc9985 100644 --- a/paddle/fluid/operators/set_value_op.cc +++ b/paddle/fluid/operators/set_value_op.cc @@ -79,6 +79,8 @@ class SetValueMaker : public framework::OpProtoAndCheckerMaker { .SetDefault({}); AddAttr>("int64_values", "store the int64 values") .SetDefault({}); + AddAttr>("fp64_values", "store the float64 values") + .SetDefault({}); AddAttr>("shape", "(vector) Shape of values.") .SetDefault({}); diff --git a/paddle/fluid/operators/set_value_op.h b/paddle/fluid/operators/set_value_op.h index 1f08e81bf0..a400dae3e0 100644 --- a/paddle/fluid/operators/set_value_op.h +++ b/paddle/fluid/operators/set_value_op.h @@ -43,9 +43,13 @@ inline std::string GetValueName(framework::proto::VarType::Type data_type) { case framework::proto::VarType::FP32: value_name = "fp32_values"; break; + case framework::proto::VarType::FP64: + value_name = "fp64_values"; + break; case framework::proto::VarType::BOOL: value_name = "bool_values"; break; + default: PADDLE_THROW(platform::errors::Unimplemented( "Unsupported data type(code %d) for SetValue operator, only " diff --git a/python/paddle/fluid/framework.py b/python/paddle/fluid/framework.py index 143b4a8f71..a0a77174ff 100644 --- a/python/paddle/fluid/framework.py +++ b/python/paddle/fluid/framework.py @@ -1897,9 +1897,10 @@ class Variable(object): dtype = self.dtype attrs['dtype'] = dtype + from .data_feeder import convert_dtype # 2.1 value is an integer of float if isinstance(value, (int, float)): - value = np.array([value]) + value = np.array([value]).astype(convert_dtype(dtype)) # 2.2 value is a np.ndarray if isinstance(value, np.ndarray): @@ -1910,6 +1911,9 @@ class Variable(object): elif dtype == core.VarDesc.VarType.FP32: value_name = "fp32_values" values = [float(v) for v in value.flat] + elif dtype == core.VarDesc.VarType.FP64: + value_name = "fp64_values" + values = [float(v) for v in value.flat] elif dtype == core.VarDesc.VarType.INT32: value_name = "int32_values" values = [int(v) for v in value.flat] @@ -1917,7 +1921,6 @@ class Variable(object): value_name = "int64_values" values = [int(v) for v in value.flat] else: - from .data_feeder import convert_dtype raise TypeError( "When assign a numpy.ndarray, integer or float to a paddle.Tensor, " "the data type of the paddle.Tensor must be bool, float32, int32 or int64, but " diff --git a/python/paddle/fluid/tests/unittests/test_set_value_op.py b/python/paddle/fluid/tests/unittests/test_set_value_op.py index cc5bf01b62..aca685a410 100644 --- a/python/paddle/fluid/tests/unittests/test_set_value_op.py +++ b/python/paddle/fluid/tests/unittests/test_set_value_op.py @@ -102,7 +102,7 @@ class TestSetValueItemSlice4(TestSetValueApi): # 2. Test different type of value: int, float, numpy.ndarray, Tensor -# 2.1 value is int32, int64, float32, bool +# 2.1 value is int32, int64, float32, float64, bool def create_test_value_int32(parent): @@ -165,6 +165,26 @@ create_test_value_fp32(TestSetValueItemSlice3) create_test_value_fp32(TestSetValueItemSlice4) +def create_test_value_fp64(parent): + class TestValueInt(parent): + def set_value(self): + self.value = 2.0**127 # float32:[-2^128, 2^128) + + def set_dtype(self): + self.dtype = "float64" + + cls_name = "{0}_{1}".format(parent.__name__, "ValueFp64") + TestValueInt.__name__ = cls_name + globals()[cls_name] = TestValueInt + + +create_test_value_fp64(TestSetValueItemInt) +create_test_value_fp64(TestSetValueItemSlice) +create_test_value_fp64(TestSetValueItemSlice2) +create_test_value_fp64(TestSetValueItemSlice3) +create_test_value_fp64(TestSetValueItemSlice4) + + def create_test_value_bool(parent): class TestValueInt(parent): def set_value(self): @@ -185,7 +205,7 @@ create_test_value_bool(TestSetValueItemSlice3) create_test_value_bool(TestSetValueItemSlice4) -# 2.2 value is numpy.array (int32, int64, float32, bool) +# 2.2 value is numpy.array (int32, int64, float32, float64, bool) def create_test_value_numpy_int32(parent): class TestValueInt(parent): def set_value(self): @@ -246,6 +266,26 @@ create_test_value_numpy_fp32(TestSetValueItemSlice3) create_test_value_numpy_fp32(TestSetValueItemSlice4) +def create_test_value_numpy_fp64(parent): + class TestValueInt(parent): + def set_value(self): + self.value = np.array([2**127]).astype("float64") + + def set_dtype(self): + self.dtype = "float64" + + cls_name = "{0}_{1}".format(parent.__name__, "ValueNumpyFp64") + TestValueInt.__name__ = cls_name + globals()[cls_name] = TestValueInt + + +create_test_value_numpy_fp64(TestSetValueItemInt) +create_test_value_numpy_fp64(TestSetValueItemSlice) +create_test_value_numpy_fp64(TestSetValueItemSlice2) +create_test_value_numpy_fp64(TestSetValueItemSlice3) +create_test_value_numpy_fp64(TestSetValueItemSlice4) + + def create_test_value_numpy_bool(parent): class TestValueInt(parent): def set_value(self): @@ -451,7 +491,7 @@ class TestError(TestSetValueBase): TypeError, "When assign a numpy.ndarray, integer or float to a paddle.Tensor, " ): - y = paddle.ones(shape=self.shape, dtype="float64") + y = paddle.ones(shape=self.shape, dtype="float16") y[0] = 1 def _step_error(self): -- GitLab