diff --git a/cmake/package.cmake b/cmake/package.cmake index c18ceff2d0d..430cd35e1bb 100644 --- a/cmake/package.cmake +++ b/cmake/package.cmake @@ -309,6 +309,7 @@ install( ${CMAKE_SOURCE_DIR}/mindspore/python/mindspore/compression ${CMAKE_SOURCE_DIR}/mindspore/python/mindspore/rewrite ${CMAKE_SOURCE_DIR}/mindspore/python/mindspore/run_check + ${CMAKE_SOURCE_DIR}/mindspore/python/mindspore/experimental DESTINATION ${INSTALL_PY_DIR} COMPONENT mindspore ) diff --git a/cmake/package_mac.cmake b/cmake/package_mac.cmake index e268d7856bd..ef02af02d13 100644 --- a/cmake/package_mac.cmake +++ b/cmake/package_mac.cmake @@ -189,6 +189,7 @@ install( ${CMAKE_SOURCE_DIR}/mindspore/python/mindspore/compression ${CMAKE_SOURCE_DIR}/mindspore/python/mindspore/rewrite ${CMAKE_SOURCE_DIR}/mindspore/python/mindspore/run_check + ${CMAKE_SOURCE_DIR}/mindspore/python/mindspore/experimental DESTINATION ${INSTALL_PY_DIR} COMPONENT mindspore ) diff --git a/cmake/package_win.cmake b/cmake/package_win.cmake index f4681e5af93..c46799cbda2 100644 --- a/cmake/package_win.cmake +++ b/cmake/package_win.cmake @@ -243,6 +243,7 @@ install( ${CMAKE_SOURCE_DIR}/mindspore/python/mindspore/compression ${CMAKE_SOURCE_DIR}/mindspore/python/mindspore/rewrite ${CMAKE_SOURCE_DIR}/mindspore/python/mindspore/run_check + ${CMAKE_SOURCE_DIR}/mindspore/python/mindspore/experimental DESTINATION ${INSTALL_PY_DIR} COMPONENT mindspore ) diff --git a/mindspore/ccsrc/include/common/pybind_api/api_register.h b/mindspore/ccsrc/include/common/pybind_api/api_register.h index 3f9ec5a7719..e4ac455ca71 100644 --- a/mindspore/ccsrc/include/common/pybind_api/api_register.h +++ b/mindspore/ccsrc/include/common/pybind_api/api_register.h @@ -53,6 +53,7 @@ void RegMetaTensor(py::module *m); void RegCSRTensor(py::module *m); void RegCOOTensor(py::module *m); void RegRowTensor(py::module *m); +void RegMapTensor(py::module *m); } // namespace tensor namespace opt { diff --git a/mindspore/ccsrc/pipeline/jit/init.cc b/mindspore/ccsrc/pipeline/jit/init.cc index 1238dd729f2..8a62b3dfc2d 100644 --- a/mindspore/ccsrc/pipeline/jit/init.cc +++ b/mindspore/ccsrc/pipeline/jit/init.cc @@ -104,6 +104,7 @@ void RegModule(py::module *m) { mindspore::tensor::RegCSRTensor(m); mindspore::tensor::RegCOOTensor(m); mindspore::tensor::RegRowTensor(m); + mindspore::tensor::RegMapTensor(m); RegValues(m); mindspore::initializer::RegRandomNormal(m); RegMsContext(m); diff --git a/mindspore/ccsrc/pybind_api/ir/map_tensor_py.cc b/mindspore/ccsrc/pybind_api/ir/map_tensor_py.cc new file mode 100644 index 00000000000..08dc7c70877 --- /dev/null +++ b/mindspore/ccsrc/pybind_api/ir/map_tensor_py.cc @@ -0,0 +1,64 @@ +/** + * Copyright 2022 Huawei Technologies Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "pybind_api/ir/map_tensor_py.h" +#include +#include "pybind_api/ir/tensor_py.h" +#include "include/common/pybind_api/api_register.h" +#include "include/common/utils/python_adapter.h" +#include "utils/log_adapter.h" + +namespace mindspore { +using tensor::TensorPy; + +MapTensorPtr MapTensorPy::MakeMapTensor(const TypePtr &key_dtype, const TypePtr &value_dtype, + const ShapeVector &value_shape) { + TypeId key_dtype_id = ((key_dtype != nullptr) ? key_dtype->type_id() : TypeId::kNumberTypeInt32); + TypeId value_dtype_id = ((value_dtype != nullptr) ? value_dtype->type_id() : TypeId::kNumberTypeFloat32); + return std::make_shared(key_dtype_id, value_dtype_id, value_shape); +} + +void MapTensorPy::UpdateFromNumpy(const MapTensorPtr &map_tensor, + const std::tuple &numpy_data) { + MS_EXCEPTION_IF_NULL(map_tensor); + MapTensor::ExportData data; + constexpr size_t key_index = 0; + constexpr size_t value_index = 1; + constexpr size_t status_index = 2; + data.key_tensor = TensorPy::MakeTensorOfNumpy(std::get(numpy_data)); + data.value_tensor = TensorPy::MakeTensorOfNumpy(std::get(numpy_data)); + data.status_tensor = TensorPy::MakeTensorOfNumpy(std::get(numpy_data)); + map_tensor->Update(data); +} + +std::tuple MapTensorPy::ExportAsNumpy(const MapTensorPtr &map_tensor, bool full) { + MS_EXCEPTION_IF_NULL(map_tensor); + auto data = map_tensor->Export(full); + return std::make_tuple(TensorPy::AsNumpy(*data.key_tensor), TensorPy::AsNumpy(*data.value_tensor), + TensorPy::AsNumpy(*data.status_tensor)); +} + +namespace tensor { +void RegMapTensor(py::module *m) { + // Define python MapTensor class. + (void)py::class_(*m, "MapTensor_") + .def(py::init(&MapTensorPy::MakeMapTensor), py::arg("key_dtype"), py::arg("value_dtype"), py::arg("value_shape")) + .def_property_readonly("key_dtype", &MapTensor::KeyDtype) + .def_property_readonly("value_dtype", &MapTensor::ValueDtype) + .def_property_readonly("value_shape", &MapTensor::value_shape); +} +} // namespace tensor +} // namespace mindspore diff --git a/mindspore/ccsrc/pybind_api/ir/map_tensor_py.h b/mindspore/ccsrc/pybind_api/ir/map_tensor_py.h new file mode 100644 index 00000000000..bc359873c1c --- /dev/null +++ b/mindspore/ccsrc/pybind_api/ir/map_tensor_py.h @@ -0,0 +1,41 @@ +/** + * Copyright 2022 Huawei Technologies Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MINDSPORE_CCSRC_UTILS_MAP_TENSOR_PY_H_ +#define MINDSPORE_CCSRC_UTILS_MAP_TENSOR_PY_H_ + +#include +#include "pybind11/numpy.h" +#include "ir/map_tensor.h" + +namespace py = pybind11; + +namespace mindspore { +// +// MapTensor python adapter class. +// +class MapTensorPy { + public: + static MapTensorPtr MakeMapTensor(const TypePtr &key_dtype, const TypePtr &value_dtype, + const ShapeVector &value_shape); + + static void UpdateFromNumpy(const MapTensorPtr &map_tensor, + const std::tuple &numpy_data); + + static std::tuple ExportAsNumpy(const MapTensorPtr &map_tensor, bool full = false); +}; +} // namespace mindspore +#endif // MINDSPORE_CCSRC_UTILS_MAP_TENSOR_PY_H_ diff --git a/mindspore/core/ir/map_tensor.cc b/mindspore/core/ir/map_tensor.cc new file mode 100644 index 00000000000..c4653ffa9a1 --- /dev/null +++ b/mindspore/core/ir/map_tensor.cc @@ -0,0 +1,50 @@ +/** + * Copyright 2022 Huawei Technologies Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ir/map_tensor.h" +#include "utils/log_adapter.h" + +namespace mindspore { +using tensor::Tensor; +using tensor::TensorPtr; + +std::size_t MapTensor::hash() const { return static_cast(tid()); } + +bool MapTensor::operator==(const MapTensor &other) const { return this == &other; } + +TensorPtr MapTensor::Get(const TensorPtr &key_tensor, const TensorPtr &default_value) { + MS_EXCEPTION_IF_NULL(key_tensor); + MS_EXCEPTION_IF_NULL(default_value); + return nullptr; +} + +void MapTensor::Put(const TensorPtr &key_tensor, const TensorPtr &value_tensor) { + MS_EXCEPTION_IF_NULL(key_tensor); + MS_EXCEPTION_IF_NULL(value_tensor); +} + +void MapTensor::Erase(const TensorPtr &key_tensor) { MS_EXCEPTION_IF_NULL(key_tensor); } + +void MapTensor::Update(const MapTensor::ExportData &data) { + MS_EXCEPTION_IF_NULL(data.key_tensor); + MS_EXCEPTION_IF_NULL(data.value_tensor); +} + +MapTensor::ExportData MapTensor::Export(bool full) { + MS_LOG(DEBUG) << (full ? "Full" : "Incremental") << " export MapTensor"; + return {nullptr, nullptr, nullptr}; +} +} // namespace mindspore diff --git a/mindspore/core/ir/map_tensor.h b/mindspore/core/ir/map_tensor.h new file mode 100644 index 00000000000..ab2aab6d961 --- /dev/null +++ b/mindspore/core/ir/map_tensor.h @@ -0,0 +1,129 @@ +/** + * Copyright 2022 Huawei Technologies Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MINDSPORE_CORE_IR_MAP_TENSOR_H_ +#define MINDSPORE_CORE_IR_MAP_TENSOR_H_ + +#include +#include +#include "ir/anf.h" +#include "ir/dtype.h" +#include "ir/tensor.h" +#include "utils/macros.h" +#include "utils/shape_utils.h" + +namespace mindspore { +/// +/// \brief MapTensor is a dynamic tensor with map like index functions. +/// +class MS_CORE_API MapTensor final : public Value { + public: + using Tensor = tensor::Tensor; + using TensorPtr = tensor::TensorPtr; + + struct ExportData { + TensorPtr key_tensor; + TensorPtr value_tensor; + TensorPtr status_tensor; + }; + + enum class Status { + kUnchanged = 0, + kModified = 1, + kErased = 2, + }; + + /// \brief Create a empty MapTensor. + /// + /// \param[in] key_dtype [TypeId] The key data type id. + /// \param[in] value_dtype [TypeId] The value data type id. + /// \param[in] value_shape [TypeId] The value shape. + MapTensor(TypeId key_dtype, TypeId value_dtype, const ShapeVector &value_shape) + : key_dtype_(key_dtype), value_dtype_(value_dtype), value_shape_(value_shape) {} + + ~MapTensor() override = default; + + MS_DECLARE_PARENT(MapTensor, Value) + + std::size_t hash() const override; + + bool operator==(const Value &other) const override { + if (this == &other) { + return true; + } + if (!other.isa()) { + return false; + } + auto other_ = static_cast(other); + return *this == other_; + } + + bool operator==(const MapTensor &other) const; + + TypeId key_dtype() const { return key_dtype_; } + + TypeId value_dtype() const { return value_dtype_; } + + const ShapeVector &value_shape() const { return value_shape_; } + + TypePtr KeyDtype() const { return TypeIdToType(key_dtype_); } + + TypePtr ValueDtype() const { return TypeIdToType(value_dtype_); } + + /// \brief Get or create values. + /// + /// \param[in] key_tensor [Tensor] The key tensor. + /// \param[in] default_value [Tensor] The default value tensor. + /// \return The value tensor according the key tensor. + TensorPtr Get(const TensorPtr &key_tensor, const TensorPtr &default_value); + + /// \brief Put or insert key value pairs. + /// + /// \param[in] key_tensor [Tensor] The key tensor. + /// \param[in] value_tensor [Tensor] The value tensor. + void Put(const TensorPtr &key_tensor, const TensorPtr &value_tensor); + + /// \brief Remove items with the given keys. + /// + /// \param[in] key_tensor [Tensor] The key tensor. + void Erase(const TensorPtr &key_tensor); + + /// \brief Update MapTensor from exported data. + /// + /// \param[in] data [ExportData] The data. + void Update(const ExportData &data); + + /// \brief Update MapTensor from exported data. + /// + /// \param[in] full [bool] True for full export, false for incremental export. + /// \return The exported data. + ExportData Export(bool full = false); + + private: + // Data type of the key. + TypeId key_dtype_; + + // Data type of the value. + TypeId value_dtype_; + + // Shape of the value. + ShapeVector value_shape_; +}; + +// Smart pointer for MapTensor. +using MapTensorPtr = std::shared_ptr; +} // namespace mindspore +#endif // MINDSPORE_CORE_IR_MAP_TENSOR_H_ diff --git a/mindspore/lite/test/config_level0/cropped_size.cfg b/mindspore/lite/test/config_level0/cropped_size.cfg index 3339ece8461..87b4107f21f 100644 --- a/mindspore/lite/test/config_level0/cropped_size.cfg +++ b/mindspore/lite/test/config_level0/cropped_size.cfg @@ -1,2 +1,2 @@ Note: This is the mindspore Lite inference framework size threshold. Offline review is required before modify this value!!! -1083704 +1085704 diff --git a/mindspore/python/mindspore/experimental/__init__.py b/mindspore/python/mindspore/experimental/__init__.py new file mode 100644 index 00000000000..0f50c219c5e --- /dev/null +++ b/mindspore/python/mindspore/experimental/__init__.py @@ -0,0 +1,20 @@ +# Copyright 2022 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +"""Experimental module.""" +from __future__ import absolute_import +from mindspore.experimental.map_parameter import MapParameter + +# Symbols from experimental module. +__all__ = ["MapParameter"] diff --git a/mindspore/python/mindspore/experimental/map_parameter.py b/mindspore/python/mindspore/experimental/map_parameter.py new file mode 100644 index 00000000000..ef44216bb04 --- /dev/null +++ b/mindspore/python/mindspore/experimental/map_parameter.py @@ -0,0 +1,126 @@ +# Copyright 2022 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +"""MapParameter implementation.""" +from __future__ import absolute_import + +__all__ = ['MapParameter'] + +import numbers +import mindspore as ms +from mindspore.common.parameter import Parameter +from mindspore.common.initializer import initializer +from mindspore._c_expression import Tensor as Tensor_ +from mindspore._c_expression import MapTensor_ + + +class MapParameter(Parameter): + """ + MapParameter is a parameter that stores a map like data structure. + + .. warning:: + This is an experimental prototype that is subject to change and/or deletion. + + Args: + key_dtype (:class:`mindspore.dtype`): The data type of the key. The argument should be defined in + `mindspore.dtype`, currently only integer types are supported. Default: int32. + value_dtype (:class:`mindspore.dtype`): The data type of the value Tensor. The argument should + be defined in `mindspore.dtype`. Default: float32. + value_shape (Union[tuple, list, int]): Used to indicate the shape of the value Tensor. The argument should be + a list of integers, a tuple of integers or an integer. Default: 1. + default_value (Union[Tensor, str]): The default value Tensor or initializer name. Default: 'zeros'. + name (str): Name of the map parameter. Default: None. + requires_grad (bool): True if the parameter requires gradient. Default: True. + + + Examples: + >>> import mindspore as ms + >>> from mindspore import Tensor + >>> from mindspore.experimental import MapParameter + >>> + >>> m = MapParameter(key_dtype=ms.int32, value_dtype=ms.float32, value_shape=(3), default_value='zeros') + >>> t = m.get(Tensor([1, 2, 3], dtype=ms.int32)) + [[0. 0. 0.] + [0. 0. 0.] + [0. 0. 0.]] + >>> m.put(Tensor([1, 2], dtype=ms.int32), Tensor([[1, 1, 1], [2, 2, 2]], dtype=np.float32)) + >>> t = m.get(Tensor([1, 2, 3], dtype=ms.int32)) + >>> print(t) + [[1. 1. 1.] + [2. 2. 2.] + [0. 0. 0.]] + >>> m.del(Tensor([2, 3], dtype=ms.int32)) + >>> t = m.get(Tensor([1, 2, 3], dtype=ms.int32)) + >>> print(t) + [[1. 1. 1.] + [0. 0. 0.] + [0. 0. 0.]] + """ + + def __new__(cls, key_dtype=ms.int32, value_dtype=ms.float32, value_shape=1, default_value='zeros', **kwargs): + if isinstance(value_shape, numbers.Number): + value_shape = (value_shape,) + data = Tensor_(value_dtype, value_shape) + obj = Tensor_.__new__(cls) + Tensor_.__init__(obj, data) + obj.key_dtype = key_dtype + obj.value_dtype = value_dtype + obj.value_shape = value_shape + obj.default_value = default_value + return obj + + def __init__(self, name=None, requires_grad=True, **kwargs): + Parameter.__init__(self, self, name=name, requires_grad=requires_grad) + self.map_tensor_ = MapTensor_(self.key_dtype, self.value_dtype, self.value_shape) + + def get(self, key_tensor, default_value=None): + """ + Get value tensor according the key tensor, fill and return the default value if key is not existed. + + Args: + key_tensor (Tensor): The key tensor. + default_value (Union[Tensor, str]): The default value or initializer. Default: None + + Returns: + Tensor, the value tensor for the key tensor. + """ + if default_value is None: + default_value = self.default_value + result = initializer(default_value, shape=(key_tensor.shape + self.value_shape), dtype=self.value_dtype) + return result.init_data() + + def put(self, key_tensor, value_tensor): + """ + Insert or update records according the given key tensor and value tensor. + + Args: + key_tensor (Tensor): The key tensor. + value_tensor (Tensor): The value tensor. + + Returns: + MapParameter, the MapParameter object itself. + """ + return self + + def erase(self, key_tensor): + """ + Remove records according the given key tensor. + + Args: + key_tensor (Tensor): The key tensor. + + Returns: + MapParameter, the MapParameter object itself. + """ + return self diff --git a/tests/ut/cpp/ir/map_tensor_test.cc b/tests/ut/cpp/ir/map_tensor_test.cc new file mode 100644 index 00000000000..271c8ff7786 --- /dev/null +++ b/tests/ut/cpp/ir/map_tensor_test.cc @@ -0,0 +1,38 @@ +/** + * Copyright 2022 Huawei Technologies Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include "common/common_test.h" +#include "ir/tensor.h" +#include "ir/map_tensor.h" + +namespace mindspore { +using tensor::Tensor; +using tensor::TensorPtr; + +class TestMapTensor : public UT::Common { + public: + TestMapTensor() = default; + ~TestMapTensor() = default; +}; + +/// Feature: MapTensor +/// Description: test MapTensor API. +/// Expectation: MapTensor API work as expected. +TEST_F(TestMapTensor, TestApi) { + auto m = std::make_shared(kNumberTypeInt32, kNumberTypeFloat32, ShapeVector{4}); + ASSERT_TRUE(m != nullptr); +} +} // namespace mindspore diff --git a/tests/ut/python/nn/test_map_parameter.py b/tests/ut/python/nn/test_map_parameter.py new file mode 100644 index 00000000000..d4671a55035 --- /dev/null +++ b/tests/ut/python/nn/test_map_parameter.py @@ -0,0 +1,42 @@ +# Copyright 2022 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +import numpy as np +import mindspore as ms +from mindspore import Tensor +from mindspore.experimental import MapParameter + + +def test_basic_operations(): + """ + Feature: MapParameter + Description: Test MapParameter basic operations. + Expectation: MapParameter works as expected. + """ + m = MapParameter(key_dtype=ms.int32, value_dtype=ms.float32, value_shape=(2), default_value='zeros', name='my_map') + assert m.name == 'my_map' + assert m.requires_grad + + t = m.get(Tensor([1, 2, 3], dtype=ms.int32)) + assert t.dtype == ms.float32 + assert t.shape == (3, 2) + assert np.allclose(t.asnumpy(), 0) + + t = m.get(Tensor([1, 2, 3], dtype=ms.int32), 'ones') + assert t.dtype == ms.float32 + assert t.shape == (3, 2) + assert np.allclose(t.asnumpy(), 1) + + m.put(Tensor([1, 2, 3], dtype=ms.int32), Tensor([[1, 1], [2, 2], [3, 3]], dtype=ms.float32)) + m.erase(Tensor([1, 2, 3], dtype=ms.int32))