Skip to content

Commit

Permalink
[Cherry-Pick] Support vector<double> as type of op attribute and op s…
Browse files Browse the repository at this point in the history
…et_value suppport vector<double> as value (PaddlePaddle#30126)
  • Loading branch information
liym27 committed Jan 11, 2021
1 parent afbc636 commit cf10e7a
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 10 deletions.
29 changes: 29 additions & 0 deletions paddle/fluid/framework/attribute.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,35 @@ struct ExtractAttribute<float> {
const std::string& attr_name_;
};

template <>
struct ExtractAttribute<std::vector<double>> {
explicit ExtractAttribute(const std::string& attr_name)
: attr_name_(attr_name) {}

std::vector<double>* operator()(Attribute& attr) const {
if (attr.type() == typeid(std::vector<int>)) { // NOLINT
std::vector<int> val = BOOST_GET_CONST(std::vector<int>, attr);
std::vector<double> vec(val.begin(), val.end());
attr = vec;
} else if (attr.type() == typeid(std::vector<float>)) { // NOLINT
std::vector<float> val = BOOST_GET_CONST(std::vector<float>, attr);
std::vector<double> vec(val.begin(), val.end());
attr = vec;
}
std::vector<double>* attr_value = nullptr;
try {
attr_value = &boost::get<std::vector<double>>(attr);
} catch (boost::bad_get& bad_get) {
PADDLE_THROW(platform::errors::InvalidArgument(
"Cannot get attribute (%s) by type std::vector<double>, its type is "
"%s.",
attr_name_, paddle::platform::demangle(attr.type().name())));
}
return attr_value;
}

const std::string& attr_name_;
};
template <typename T>
inline proto::AttrType AttrTypeID() {
Attribute tmp = T();
Expand Down
2 changes: 2 additions & 0 deletions paddle/fluid/framework/framework.proto
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ enum AttrType {
LONG = 9;
BLOCKS = 10;
LONGS = 11;
FLOAT64S = 12;
}

// OpDesc describes an instance of a C++ framework::OperatorBase
Expand All @@ -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 {
Expand Down
4 changes: 4 additions & 0 deletions paddle/fluid/framework/op_desc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -714,6 +714,10 @@ struct SetAttrDescVisitor : public boost::static_visitor<void> {
VectorToRepeated(v, attr_->mutable_longs());
}

void operator()(const std::vector<double> &v) const {
VectorToRepeated(v, attr_->mutable_float64s());
}

void operator()(boost::blank) const {
PADDLE_THROW(platform::errors::Unavailable(
"Unsupported calling method of SetAttrDescVisitor object for "
Expand Down
9 changes: 4 additions & 5 deletions paddle/fluid/framework/type_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,10 @@ using VariableNameMap = std::map<std::string, std::vector<std::string>>;
using VariableValueMap = std::map<std::string, std::vector<Variable*>>;

// The order should be as same as framework.proto
using Attribute =
boost::variant<boost::blank, int, float, std::string, std::vector<int>,
std::vector<float>, std::vector<std::string>, bool,
std::vector<bool>, BlockDesc*, int64_t,
std::vector<BlockDesc*>, std::vector<int64_t>>;
using Attribute = boost::variant<
boost::blank, int, float, std::string, std::vector<int>, std::vector<float>,
std::vector<std::string>, bool, std::vector<bool>, BlockDesc*, int64_t,
std::vector<BlockDesc*>, std::vector<int64_t>, std::vector<double>>;

using AttributeMap = std::unordered_map<std::string, Attribute>;

Expand Down
2 changes: 2 additions & 0 deletions paddle/fluid/operators/set_value_op.cc
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ class SetValueMaker : public framework::OpProtoAndCheckerMaker {
.SetDefault({});
AddAttr<std::vector<int64_t>>("int64_values", "store the int64 values")
.SetDefault({});
AddAttr<std::vector<double>>("fp64_values", "store the float64 values")
.SetDefault({});

AddAttr<std::vector<int64_t>>("shape", "(vector<int64_t>) Shape of values.")
.SetDefault({});
Expand Down
4 changes: 4 additions & 0 deletions paddle/fluid/operators/set_value_op.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 "
Expand Down
7 changes: 5 additions & 2 deletions python/paddle/fluid/framework.py
Original file line number Diff line number Diff line change
Expand Up @@ -1893,9 +1893,10 @@ def __setitem__(self, item, value):
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):
Expand All @@ -1906,14 +1907,16 @@ def __setitem__(self, item, value):
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]
elif dtype == core.VarDesc.VarType.INT64:
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 "
Expand Down
46 changes: 43 additions & 3 deletions python/paddle/fluid/tests/unittests/test_set_value_op.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ def _get_answer(self):


# 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):
Expand Down Expand Up @@ -165,6 +165,26 @@ def set_dtype(self):
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):
Expand All @@ -185,7 +205,7 @@ def set_dtype(self):
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):
Expand Down Expand Up @@ -246,6 +266,26 @@ def set_dtype(self):
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):
Expand Down Expand Up @@ -451,7 +491,7 @@ def _dtype_error(self):
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):
Expand Down

0 comments on commit cf10e7a

Please sign in to comment.