From 078020513c965456ad74cdcdfce69d2ae700c47a Mon Sep 17 00:00:00 2001 From: zhangbo9674 Date: Fri, 10 Feb 2023 07:30:41 +0000 Subject: [PATCH 01/26] add TypeUniquer and IrContext --- paddle/ir/CMakeLists.txt | 5 + paddle/ir/ir_context.cc | 54 ++++++++++ paddle/ir/ir_context.h | 60 +++++++++++ paddle/ir/type/CMakeLists.txt | 2 + paddle/ir/type/storage_uniquer.cc | 133 ++++++++++++++++++++++++ paddle/ir/type/storage_uniquer.h | 126 +++++++++++++++++++++++ paddle/ir/type/type_id.h | 73 ++++++++++++++ paddle/ir/type/type_support.h | 150 +++++++++++++++++----------- paddle/ir/type/type_support_test.cc | 1 + 9 files changed, 547 insertions(+), 57 deletions(-) create mode 100644 paddle/ir/ir_context.cc create mode 100644 paddle/ir/ir_context.h create mode 100644 paddle/ir/type/storage_uniquer.cc create mode 100644 paddle/ir/type/storage_uniquer.h create mode 100644 paddle/ir/type/type_id.h diff --git a/paddle/ir/CMakeLists.txt b/paddle/ir/CMakeLists.txt index d104ae066b59cd..a6f5a7783946d9 100644 --- a/paddle/ir/CMakeLists.txt +++ b/paddle/ir/CMakeLists.txt @@ -3,3 +3,8 @@ if(NOT WITH_NEWIR) endif() add_subdirectory(type) + +cc_library( + ir_context + SRCS ir_context.cc + DEPS storage_uniquer) diff --git a/paddle/ir/ir_context.cc b/paddle/ir/ir_context.cc new file mode 100644 index 00000000000000..f9be67cf255a46 --- /dev/null +++ b/paddle/ir/ir_context.cc @@ -0,0 +1,54 @@ +// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved. +// +// 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 "paddle/ir/ir_context.h" +#include +#include "paddle/ir/type/storage_uniquer.h" +#include "paddle/ir/type/type_support.h" +#include "paddle/phi/api/ext/exception.h" + +namespace ir { +/// The implementation class of the IrContext class +class IrContextImpl { + public: + IrContextImpl() {} + + ~IrContextImpl() {} + + /// \brief Cached AbstractType instances. + std::unordered_map registed_abstract_types_; + + /// \brief TypeStorage uniquer and cache instances. + StorageUniquer registed_storage_uniquer_; + + // TODO(zhangbo9674): add some built type. +}; + +IrContext::IrContext() : impl_(new IrContextImpl()) {} + +StorageUniquer &IrContext::storage_uniquer() { + return impl().registed_storage_uniquer_; +} + +const AbstractType &AbstractType::lookup(TypeId type_id, IrContext *ctx) { + auto &impl = ctx->impl(); + auto iter = impl.registed_abstract_types_.find(type_id); + if (iter == impl.registed_abstract_types_.end()) { + PD_THROW("The input data pointer is null."); + } else { + return *(iter->second); + } +} + +} // namespace ir diff --git a/paddle/ir/ir_context.h b/paddle/ir/ir_context.h new file mode 100644 index 00000000000000..3ea6160e4184ef --- /dev/null +++ b/paddle/ir/ir_context.h @@ -0,0 +1,60 @@ +// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved. +// +// 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. + +#pragma once + +#include + +namespace ir { +class IrContextImpl; +class StorageUniquer; + +/// \brief IrContext is a global singleton class used to store and manage Type +/// and its related data structures. +class IrContext { + public: + /// \brief Initializes a new instance of IrContext. + /// \return Global singleton for IrContext. + static IrContext *Instance() { + if (ir_context_ == nullptr) { + ir_context_ = new IrContext(); + } + return ir_context_; + } + + ~IrContext(); + + /// \brief Get an instance of IrContextImpl, a private member of IrContext. + /// For the specific definition of IrContextImpl, see ir_context.cc. \return + /// The instance of IrContextImpl. + IrContextImpl &impl() { return *impl_; } + + /// \brief Returns the storage uniquer used for constructing TypeStorage + /// instances. \return The storage uniquer used for constructing TypeStorage + /// instances. + StorageUniquer &storage_uniquer(); + + private: + IrContext(); + + IrContext(const IrContext &) = delete; + + void operator=(const IrContext &) = delete; + + static IrContext *ir_context_; + + const std::unique_ptr impl_; +}; + +} // namespace ir diff --git a/paddle/ir/type/CMakeLists.txt b/paddle/ir/type/CMakeLists.txt index 649ac7d74b4076..5e5ff9d7223e4b 100644 --- a/paddle/ir/type/CMakeLists.txt +++ b/paddle/ir/type/CMakeLists.txt @@ -2,3 +2,5 @@ cc_test( type_support_test SRCS type_support_test.cc DEPS gtest) + +cc_library(storage_uniquer SRCS storage_uniquer.cc) diff --git a/paddle/ir/type/storage_uniquer.cc b/paddle/ir/type/storage_uniquer.cc new file mode 100644 index 00000000000000..9cfb312440c4f5 --- /dev/null +++ b/paddle/ir/type/storage_uniquer.cc @@ -0,0 +1,133 @@ +// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved. +// +// 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 "paddle/ir/type/storage_uniquer.h" +#include +#include +#include "paddle/phi/api/ext/exception.h" + +namespace ir { + +struct ParametricStorageUniquer { + using BaseStorage = StorageUniquer::BaseStorage; + + explicit ParametricStorageUniquer(std::function del_func) + : del_func_(del_func) {} + + ~ParametricStorageUniquer() { + for (const auto &instance : parametric_instances_) { + del_func_(instance.second); + } + } + + /// \brief Get the storage of parametric type, if not in the cache, create and + /// insert the cache. + BaseStorage *GetOrCreateParametricStorage( + std::size_t hash_value, + std::function is_equal_func, + std::function ctor_func) { + BaseStorage *storage = nullptr; + if (parametric_instances_.count(hash_value) == 0) { + storage = ctor_func(); + parametric_instances_.emplace(hash_value, storage); + } else { + auto pr = parametric_instances_.equal_range(hash_value); + while (pr.first != pr.second) { + if (is_equal_func(pr.first->second)) { + return pr.first->second; + } + ++pr.first; + } + storage = ctor_func(); + parametric_instances_.emplace(hash_value, storage); + } + return storage; + } + + private: + std::unordered_multimap parametric_instances_; + + std::function del_func_; +}; + +struct StorageUniquerImpl { + using BaseStorage = StorageUniquer::BaseStorage; + + /// \brief Get the storage of parametric type, if not in the cache, create and + /// insert the cache. + BaseStorage *GetOrCreateParametricStorage( + TypeId type_id, + std::size_t hash_value, + std::function is_equal_func, + std::function ctor_func) { + if (parametric_uniquers_.find(type_id) == parametric_uniquers_.end()) + PD_THROW("The input data pointer is null."); + ParametricStorageUniquer ¶metric_storage = + *parametric_uniquers_[type_id]; + return parametric_storage.GetOrCreateParametricStorage( + hash_value, is_equal_func, ctor_func); + } + + /// \brief Get the storage of singleton type. + /// \param type_id The type id of the AbstractType. + BaseStorage *GetSingletonStorage(TypeId type_id) { + if (singleton_instances_.find(type_id) == singleton_instances_.end()) + PD_THROW("The input data pointer is null."); + BaseStorage *singleton_instance = singleton_instances_[type_id]; + return singleton_instance; + } + + void RegisterParametricStorageType( + TypeId type_id, std::function del_func); + + void RegisterSingletonStorageType(TypeId type_id, + std::function init_func); + + std::unordered_map> + parametric_uniquers_; + + std::unordered_map singleton_instances_; +}; + +StorageUniquer::StorageUniquer() : impl_(new StorageUniquerImpl()) {} + +StorageUniquer::BaseStorage *StorageUniquer::GetParametricStorageTypeImpl( + TypeId type_id, + std::size_t hash_value, + std::function is_equal_func, + std::function ctor_func) { + return impl_->GetOrCreateParametricStorage( + type_id, hash_value, is_equal_func, ctor_func); +} + +StorageUniquer::BaseStorage *StorageUniquer::GetSingletonStorageTypeImpl( + TypeId type_id) { + return impl_->GetSingletonStorage(type_id); +} + +void StorageUniquer::RegisterParametricStorageTypeImpl( + TypeId type_id, std::function del_func) { + impl_->parametric_uniquers_.emplace( + type_id, std::make_unique(del_func)); +} + +void StorageUniquer::RegisterSingletonStorageTypeImpl( + TypeId type_id, std::function ctor_func) { + if (impl_->singleton_instances_.find(type_id) != + impl_->singleton_instances_.end()) + PD_THROW("storage class already registered"); + impl_->singleton_instances_.emplace(type_id, ctor_func()); +} + +} // namespace ir diff --git a/paddle/ir/type/storage_uniquer.h b/paddle/ir/type/storage_uniquer.h new file mode 100644 index 00000000000000..8a36f7365ca673 --- /dev/null +++ b/paddle/ir/type/storage_uniquer.h @@ -0,0 +1,126 @@ +// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved. +// +// 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. + +#pragma once + +#include +#include +#include +#include "paddle/ir/type/type_id.h" + +namespace ir { +/// \brief The implementation of the class StorageUniquer. +struct StorageUniquerImpl; + +/// \brief A utility class for getting or creating Storage class instances. +/// Storage class must be a derived class of StorageUniquer::BaseStorage. +/// There are two types of Storage class: +/// One is a singleton type, which can directly obtain an instance through the +/// get method; The other is a parameteric type, which needs to comply with the +/// following conditions: (1) Need to define a type alias called ParamKey, it +/// serves as the unique identifier for the Storage class; (2) Need to provide a +/// hash method on the ParamKey for storage and access; (3) Need to provide +/// method 'bool operator==(const ParamKey &) const', used to compare Storage +/// instance and ParamKey instance. +class StorageUniquer { + public: + /// This class is the base class of all storage classes, + /// and any type of storage needs to inherit from this class. + class BaseStorage { + protected: + BaseStorage() = default; + }; + + StorageUniquer(); + + ~StorageUniquer(); + + /// \brief Get a unique storage instance of parametric Type. + /// \param init_func Used to initialize a newly inserted storage instance. + /// \param type_id The type id of the AbstractType. + /// \param args Parameters of the wrapped function. + /// \return A uniqued instance of Storage. + template + Storage *get(std::function init_func, + TypeId type_id, + Args &&...args) { + auto derived_param_key = Storage::ParamKey(std::forward(args)...); + std::size_t hash_value = Storage::HashValue(derived_param_key); + bool is_equal_func = [&derived_param_key](const BaseStorage *existing) { + return static_cast(*existing) == derived_param_key; + }; + auto ctor_func = [&]() { + auto *storage = Storage::Construct(derived_param_key); + if (init_func) init_func(storage); + return storage; + }; + return static_cast(GetParametricStorageTypeImpl( + type_id, hash_value, is_equal_func, ctor_func)); + } + + /// \brief Get a unique storage instance of singleton Type. + /// \param type_id The type id of the AbstractType. + /// \return A uniqued instance of Storage. + template + Storage *get(TypeId type_id) { + return static_cast(GetSingletonStorageTypeImpl(type_id)); + } + + /// \brief Register a new parametric storage class. + /// \param type_id The type id of the AbstractType. + template + void RegisterParametricStorageType(TypeId type_id) { + if (std::is_trivially_destructible::value) { + return RegisterParametricStorageTypeImpl(type_id, nullptr); + } else { + return RegisterParametricStorageTypeImpl( + type_id, [](BaseStorage *storage) { + static_cast(storage)->~Storage(); + }); + } + } + + /// \brief Register a new parametric storage class. + /// \param type_id The type id of the AbstractType. + /// \param init_func Used to initialize a newly inserted storage instance. + template + void RegisterSingletonStorageType(TypeId type_id, + std::function init_func) { + auto ctor_func = [&]() { + auto *storage = new Storage(nullptr); + if (init_func) init_func(storage); + return storage; + }; + RegisterSingletonStorageTypeImpl(type_id, ctor_func); + } + + private: + BaseStorage *GetParametricStorageTypeImpl( + TypeId type_id, + std::size_t hash_value, + std::function is_equal_func, + std::function ctor_func); + + BaseStorage *GetSingletonStorageTypeImpl(TypeId type_id); + + void RegisterParametricStorageTypeImpl( + TypeId type_id, std::function del_func); + + void RegisterSingletonStorageTypeImpl( + TypeId type_id, std::function ctor_func); + + std::unique_ptr impl_; +}; + +} // namespace ir diff --git a/paddle/ir/type/type_id.h b/paddle/ir/type/type_id.h new file mode 100644 index 00000000000000..6aa72decd0e3ea --- /dev/null +++ b/paddle/ir/type/type_id.h @@ -0,0 +1,73 @@ +// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved. +// +// 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. + +#pragma once + +#include + +namespace ir { + +/// \brief TypeId is the unique identification of Type, each Type corresponds to +/// a unique TypeId, the same id indicates the same Type class. TypeId provides +/// an instantiation interface: TypeId::get. +/// Example: +/// \code{cpp} +/// class TypeA {}; +/// TypeId type_a_id = TypeId::get(); +/// \endcode +class TypeId { + struct Storage {}; + + public: + /// \brief Returns the unique TypeId of Type T. + /// \return The unique TypeId of Type T. + template + static TypeId get() { + static Storage instance; + return TypeId(&instance); + } + + /// \brief Comparison operations. + inline bool operator==(const TypeId &other) const { + return storage_ == other.storage_; + } + + /// \brief Comparison operations. + inline bool operator!=(const TypeId &other) const { + return !(*this == other); + } + + /// \brief Enable hashing TypeId instances. + friend struct std::hash; + + private: + /// \brief Construct a TypeId and initialize storage. + /// \param storage The storage of this TypeId. + explicit TypeId(const Storage *storage) : storage_(storage) {} + + const Storage *storage_; +}; + +} // namespace ir + +// Custom specialization of std::hash can be injected in namespace std. +namespace std { +/// \brief Enable hashing TypeId instances. +template <> +struct hash { + std::size_t operator()(const ir::TypeId &obj) const { + return std::hash()(obj.storage_); + } +}; +} // namespace std diff --git a/paddle/ir/type/type_support.h b/paddle/ir/type/type_support.h index fc2a397768563b..36ccbfafa0b6ac 100644 --- a/paddle/ir/type/type_support.h +++ b/paddle/ir/type/type_support.h @@ -1,4 +1,4 @@ -// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved. +// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -14,51 +14,11 @@ #pragma once -#include +#include "paddle/ir/ir_context.h" +#include "paddle/ir/type/storage_uniquer.h" +#include "paddle/ir/type/type_id.h" namespace ir { - -/// \brief TypeId is the unique identification of Type, each Type corresponds to -/// a unique TypeId, the same id indicates the same Type class. TypeId provides -/// an instantiation interface: TypeId::get. -/// Example: -/// \code{cpp} -/// class TypeA {}; -/// TypeId type_a_id = TypeId::get(); -/// \endcode -class TypeId { - struct Storage {}; - - public: - /// \brief Returns the unique TypeId of Type T. - /// \return The unique TypeId of Type T. - template - static TypeId get() { - static Storage instance; - return TypeId(&instance); - } - - /// \brief Comparison operations. - inline bool operator==(const TypeId &other) const { - return storage_ == other.storage_; - } - - /// \brief Comparison operations. - inline bool operator!=(const TypeId &other) const { - return !(*this == other); - } - - /// \brief Enable hashing TypeId instances. - friend struct std::hash; - - private: - /// \brief Construct a TypeId and initialize storage. - /// \param storage The storage of this TypeId. - explicit TypeId(const Storage *storage) : storage_(storage) {} - - const Storage *storage_; -}; - /// \brief Abstract the properties and behaviors common to all Type classes into /// an AbstractType class. There are two types in Type system: /// on-parameter/singleton type and parameter-type. The common attributes of all @@ -74,9 +34,10 @@ class AbstractType { /// \return The type id of the AbstractType. TypeId type_id() const { return type_id_; } - /* TODO(zhangbo9674): After the IRContext is designed, AbstractType will be - * cached to IRContext with TypeId as key. - */ + /// \brief Find the AbstractType instance whose TypeId is type_id from + /// IrContext. \param type_id The type id of the AbstractType. \param ctx The + /// IrContext. \return The AbstractType instance whose TypeId is type_id. + static const AbstractType &lookup(TypeId type_id, IrContext *ctx); private: /// \brief The constructor is set to private and provides the user with the @@ -93,7 +54,9 @@ class AbstractType { /// type, in addition to AbstractType/TypeId, parameter information needs to be /// included. So that, non-parameter type can be constructed by TypeStorage /// directly but parameter type should be constructed by Derived TypeStorage. -class TypeStorage { +class TypeStorage : public StorageUniquer::BaseStorage { + friend StorageUniquer; + public: /// \brief Construct a TypeStorage and initialize abstract_type. /// \param abstract_type The abstract_type of this TypeStorage. @@ -105,18 +68,91 @@ class TypeStorage { const AbstractType &abstract_type() { return *abstract_type_; } private: + /// \brief Initialize TypeStorage based on the AbstractType* provided by the + /// user \param abstract_type AbstractType* provided by the user, the + /// construction method of AbstractType refers to AbstractType::get. + void initialize(const AbstractType &abstract_type) { + abstract_type_ = const_cast(&abstract_type); + } + AbstractType *abstract_type_{nullptr}; }; -} // namespace ir +/// \brief TypeUniquer is a utility class that provides interfaces for get or +/// unique Type instances in IrContext. +struct TypeUniquer { + /// \brief Get a unique instance of Type T from IrContext. Note: For a + /// parameteric_type, if not found in IrContext, it will try to create a new + /// instance and register it to IrContext; for a singleton_type, only search. + /// \param ctx The IrContext instance. + /// \param args Parameters of the wrapped function. + /// \return The unique instance of Type T from IrContext. + template + static T get(IrContext *ctx, Args &&...args) { + return GetWithTypeId( + ctx, + T::type_id(), + std::forward(args)...); // class Type需要提供type_id接口 + } + + /// \brief Get a unique instance of parametric Type T from IrContext. If not + /// found in IrContext, it will try to create a new instance and register it + /// to IrContext; \param ctx The IrContext instance. \param type_id The type + /// id of the AbstractType. \param args Parameters of the wrapped function. + /// \return The unique instance of Type T from IrContext. + template + static std::enable_if_t< + !std::is_same::value, + T> // T(class Type)需要提供ImplType(using ImplType=TypeStorage/派生) + GetWithTypeId(IrContext *ctx, TypeId type_id, Args &&...args) { + return ctx->storage_uniquer().get( + [&, type_id](TypeStorage *storage) { + storage->initialize(AbstractType::lookup(type_id, ctx)); + }, + type_id, + std::forward(args)...); + } -// Custom specialization of std::hash can be injected in namespace std. -namespace std { -/// \brief Enable hashing TypeId instances. -template <> -struct hash { - std::size_t operator()(const ir::TypeId &obj) const { - return std::hash()(obj.storage_); + /// \brief Get a unique instance of singleton Type T from IrContext, only + /// search. \param ctx The IrContext instance. \param type_id The type id of + /// the AbstractType. \return The unique instance of Type T from IrContext. + template + static std:: + enable_if_t::value, T> + GetWithTypeId(IrContext *ctx, TypeId type_id) { + return ctx->storage_uniquer().get(type_id); + } + + /// \brief Register a unique instance of Type T to IrContext. + /// \param ctx The IrContext instance. + template + static void RegisterType(IrContext *ctx) { + RegisterType(ctx, T::type_id()); // class Type需要提供type_id接口 + } + + /// \brief Register a unique instance of parametric Type T to IrContext. + /// \param ctx The IrContext instance. + /// \param type_id The type id of the Type T. + template + static std::enable_if_t< + !std::is_same::value> + RegisterType(IrContext *ctx, TypeId type_id) { + ctx->storage_uniquer().RegisterParametricStorageType( + type_id); + } + + /// \brief Register a unique instance of singleton Type T to IrContext. + /// \param ctx The IrContext instance. + /// \param type_id The type id of the Type T. + template + static std::enable_if_t< + std::is_same::value> + RegisterType(IrContext *ctx, TypeId type_id) { + ctx->storage_uniquer().RegisterSingletonStorageType( + type_id, [&ctx, type_id](TypeStorage *storage) { + storage->initialize(AbstractType::lookup(type_id, ctx)); + }); } }; -} // namespace std + +} // namespace ir diff --git a/paddle/ir/type/type_support_test.cc b/paddle/ir/type/type_support_test.cc index 061ef8e31c8b7c..f18db76c908b1e 100644 --- a/paddle/ir/type/type_support_test.cc +++ b/paddle/ir/type/type_support_test.cc @@ -15,6 +15,7 @@ limitations under the License. */ #include "paddle/ir/type/type_support.h" #include #include +#include "paddle/ir/type/type_id.h" TEST(type_support, type_id) { class TypeA {}; From 819ed9156b1ecb01974676e3043b9198291d82a7 Mon Sep 17 00:00:00 2001 From: zhangbo9674 Date: Fri, 10 Feb 2023 08:31:26 +0000 Subject: [PATCH 02/26] refine include code --- paddle/ir/ir_context.cc | 4 ++-- paddle/ir/type/storage_uniquer.cc | 4 ++-- paddle/ir/type/storage_uniquer.h | 1 + paddle/ir/type/type_support.h | 1 - 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/paddle/ir/ir_context.cc b/paddle/ir/ir_context.cc index f9be67cf255a46..09d56d56c73625 100644 --- a/paddle/ir/ir_context.cc +++ b/paddle/ir/ir_context.cc @@ -12,9 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "paddle/ir/ir_context.h" #include -#include "paddle/ir/type/storage_uniquer.h" + +#include "paddle/ir/ir_context.h" #include "paddle/ir/type/type_support.h" #include "paddle/phi/api/ext/exception.h" diff --git a/paddle/ir/type/storage_uniquer.cc b/paddle/ir/type/storage_uniquer.cc index 9cfb312440c4f5..fe22dfed784c96 100644 --- a/paddle/ir/type/storage_uniquer.cc +++ b/paddle/ir/type/storage_uniquer.cc @@ -12,13 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "paddle/ir/type/storage_uniquer.h" #include #include + +#include "paddle/ir/type/storage_uniquer.h" #include "paddle/phi/api/ext/exception.h" namespace ir { - struct ParametricStorageUniquer { using BaseStorage = StorageUniquer::BaseStorage; diff --git a/paddle/ir/type/storage_uniquer.h b/paddle/ir/type/storage_uniquer.h index 8a36f7365ca673..e3addb00dbbc5a 100644 --- a/paddle/ir/type/storage_uniquer.h +++ b/paddle/ir/type/storage_uniquer.h @@ -17,6 +17,7 @@ #include #include #include + #include "paddle/ir/type/type_id.h" namespace ir { diff --git a/paddle/ir/type/type_support.h b/paddle/ir/type/type_support.h index 36ccbfafa0b6ac..397f50ceb72606 100644 --- a/paddle/ir/type/type_support.h +++ b/paddle/ir/type/type_support.h @@ -16,7 +16,6 @@ #include "paddle/ir/ir_context.h" #include "paddle/ir/type/storage_uniquer.h" -#include "paddle/ir/type/type_id.h" namespace ir { /// \brief Abstract the properties and behaviors common to all Type classes into From e2336037d3d3f59b683c43dea76406de176d6c1a Mon Sep 17 00:00:00 2001 From: zhangbo9674 Date: Fri, 10 Feb 2023 12:59:11 +0000 Subject: [PATCH 03/26] add Type, TypeBase --- paddle/ir/type/type.h | 51 ++++++++++++++++++++++++++++++++++++++ paddle/ir/type/type_base.h | 46 ++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 paddle/ir/type/type.h create mode 100644 paddle/ir/type/type_base.h diff --git a/paddle/ir/type/type.h b/paddle/ir/type/type.h new file mode 100644 index 00000000000000..f72688b2dc43cf --- /dev/null +++ b/paddle/ir/type/type.h @@ -0,0 +1,51 @@ +// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved. +// +// 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. + +#pragma once + +#include "paddle/ir/type/type_support.h" + +namespace ir { +/// \brief class Type +class Type { + public: + using ImplType = TypeStorage; + + constexpr Type() = default; + + explicit Type(const ImplType *impl) : impl_(const_cast(impl)) {} + + Type(const Type &other) = default; + + Type &operator=(const Type &other) = default; + + bool operator==(Type other) const { return impl_ == other.impl_; } + + bool operator!=(Type other) const { return impl_ != other.impl_; } + + explicit operator bool() const { return impl_; } + + bool operator!() const { return impl_ == nullptr; } + + TypeId type_id() { return impl_->abstract_type().type_id(); } + + const AbstractType &abstract_type() { return impl_->abstract_type(); } + + ImplType *impl() const { return impl_; } + + protected: + ImplType *impl_{nullptr}; +}; + +} // namespace ir diff --git a/paddle/ir/type/type_base.h b/paddle/ir/type/type_base.h new file mode 100644 index 00000000000000..f905fb64f79dde --- /dev/null +++ b/paddle/ir/type/type_base.h @@ -0,0 +1,46 @@ +// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved. +// +// 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. + +#pragma once + +#include "paddle/ir/type/storage_uniquer.h" +#include "paddle/ir/type/type_id.h" + +namespace ir { +template +class TypeBase : public BaseT { + public: + using Base = TypeBase; + using ImplType = StorageT; + + static TypeId type_id() { return TypeId::get(); } + + template + static bool classof(T val) { + return val.type_id() == type_id(); + } + + template + static ConcreteT get(IrContext *ctx, Args... args) { + return UniquerT::template get(ctx, args...); + } + + /// Utility for easy access to the storage instance. + ImplType *impl() const { return static_cast(this->impl_); } +}; + +} // namespace ir From 40e8a6d17c29f371aeac916aa64a11560ccb0052 Mon Sep 17 00:00:00 2001 From: zhangbo9674 Date: Mon, 13 Feb 2023 09:42:24 +0000 Subject: [PATCH 04/26] add built-in type --- paddle/ir/CMakeLists.txt | 5 ++ paddle/ir/builtin_type.h | 31 +++++++++++ paddle/ir/ir_context.cc | 16 ++++-- paddle/ir/ir_context.h | 17 ++++-- paddle/ir/ir_context_test.cc | 23 +++++++++ paddle/ir/type/storage_uniquer.cc | 20 +++++--- paddle/ir/type/storage_uniquer.h | 24 ++++++++- paddle/ir/type/type.h | 13 ++++- paddle/ir/type/type_base.h | 12 ++++- paddle/ir/type/type_id.h | 18 ++++++- paddle/ir/type/type_support.h | 80 +++++++++++++++++++++++------ paddle/ir/type/type_support_test.cc | 3 +- 12 files changed, 225 insertions(+), 37 deletions(-) create mode 100644 paddle/ir/builtin_type.h create mode 100644 paddle/ir/ir_context_test.cc diff --git a/paddle/ir/CMakeLists.txt b/paddle/ir/CMakeLists.txt index a6f5a7783946d9..a47e83803a183a 100644 --- a/paddle/ir/CMakeLists.txt +++ b/paddle/ir/CMakeLists.txt @@ -8,3 +8,8 @@ cc_library( ir_context SRCS ir_context.cc DEPS storage_uniquer) + +cc_test( + ir_context_test + SRCS ir_context_test.cc + DEPS gtest ir_context) diff --git a/paddle/ir/builtin_type.h b/paddle/ir/builtin_type.h new file mode 100644 index 00000000000000..938201d1dd3971 --- /dev/null +++ b/paddle/ir/builtin_type.h @@ -0,0 +1,31 @@ +// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved. +// +// 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. + +#pragma once + +#include "paddle/ir/type/type.h" + +namespace ir { +/// +/// \brief Interfaces for user-created built-in types. For example: +/// Type fp32 = Float32Type::get(ctx); +/// +class Float32Type + : public Type::TypeBase { + public: + using Base::Base; + static Float32Type get(ir::IrContext *context); +}; + +} // namespace ir diff --git a/paddle/ir/ir_context.cc b/paddle/ir/ir_context.cc index 09d56d56c73625..2299e15eea9080 100644 --- a/paddle/ir/ir_context.cc +++ b/paddle/ir/ir_context.cc @@ -14,28 +14,32 @@ #include +#include "paddle/ir/builtin_type.h" #include "paddle/ir/ir_context.h" #include "paddle/ir/type/type_support.h" #include "paddle/phi/api/ext/exception.h" namespace ir { -/// The implementation class of the IrContext class +// The implementation class of the IrContext class class IrContextImpl { public: IrContextImpl() {} ~IrContextImpl() {} - /// \brief Cached AbstractType instances. + // Cached AbstractType instances. std::unordered_map registed_abstract_types_; - /// \brief TypeStorage uniquer and cache instances. + // TypeStorage uniquer and cache instances. StorageUniquer registed_storage_uniquer_; - // TODO(zhangbo9674): add some built type. + // Some built-in type. + Float32Type fp32_type; }; -IrContext::IrContext() : impl_(new IrContextImpl()) {} +IrContext::IrContext() : impl_(new IrContextImpl()) { + impl_->fp32_type = TypeUniquer::get(this); +} StorageUniquer &IrContext::storage_uniquer() { return impl().registed_storage_uniquer_; @@ -51,4 +55,6 @@ const AbstractType &AbstractType::lookup(TypeId type_id, IrContext *ctx) { } } +Float32Type Float32Type::get(IrContext *ctx) { return ctx->impl().fp32_type; } + } // namespace ir diff --git a/paddle/ir/ir_context.h b/paddle/ir/ir_context.h index 3ea6160e4184ef..45f836bedf2e97 100644 --- a/paddle/ir/ir_context.h +++ b/paddle/ir/ir_context.h @@ -20,12 +20,17 @@ namespace ir { class IrContextImpl; class StorageUniquer; +/// /// \brief IrContext is a global singleton class used to store and manage Type /// and its related data structures. +/// class IrContext { public: + /// /// \brief Initializes a new instance of IrContext. + /// /// \return Global singleton for IrContext. + /// static IrContext *Instance() { if (ir_context_ == nullptr) { ir_context_ = new IrContext(); @@ -35,14 +40,20 @@ class IrContext { ~IrContext(); + /// /// \brief Get an instance of IrContextImpl, a private member of IrContext. - /// For the specific definition of IrContextImpl, see ir_context.cc. \return - /// The instance of IrContextImpl. + /// For the specific definition of IrContextImpl, see ir_context.cc. + /// + /// \return The instance of IrContextImpl. + /// IrContextImpl &impl() { return *impl_; } /// \brief Returns the storage uniquer used for constructing TypeStorage - /// instances. \return The storage uniquer used for constructing TypeStorage /// instances. + /// + /// \return The storage uniquer used for constructing TypeStorage + /// instances. + /// StorageUniquer &storage_uniquer(); private: diff --git a/paddle/ir/ir_context_test.cc b/paddle/ir/ir_context_test.cc new file mode 100644 index 00000000000000..044140a3a212e9 --- /dev/null +++ b/paddle/ir/ir_context_test.cc @@ -0,0 +1,23 @@ +/* Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved. + +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 "paddle/ir/builtin_type.h" +#include "paddle/ir/ir_context.h" + +TEST(ir_context, ir_context) { + ir::IrContext *ctx = ir::IrContext::Instance(); + ir::Type fp32 = ir::Float32Type::get(ctx); +} diff --git a/paddle/ir/type/storage_uniquer.cc b/paddle/ir/type/storage_uniquer.cc index fe22dfed784c96..9fa6b58422443b 100644 --- a/paddle/ir/type/storage_uniquer.cc +++ b/paddle/ir/type/storage_uniquer.cc @@ -19,6 +19,8 @@ #include "paddle/phi/api/ext/exception.h" namespace ir { +// This is a structure for creating, caching, and looking up Storage of +// parameteric types. struct ParametricStorageUniquer { using BaseStorage = StorageUniquer::BaseStorage; @@ -31,8 +33,8 @@ struct ParametricStorageUniquer { } } - /// \brief Get the storage of parametric type, if not in the cache, create and - /// insert the cache. + // Get the storage of parametric type, if not in the cache, create and + // insert the cache. BaseStorage *GetOrCreateParametricStorage( std::size_t hash_value, std::function is_equal_func, @@ -56,16 +58,19 @@ struct ParametricStorageUniquer { } private: + // In order to prevent hash conflicts, the unordered_multimap data structure + // is used for storage. std::unordered_multimap parametric_instances_; std::function del_func_; }; +/// The implementation class of the StorageUniquer. struct StorageUniquerImpl { using BaseStorage = StorageUniquer::BaseStorage; - /// \brief Get the storage of parametric type, if not in the cache, create and - /// insert the cache. + // Get the storage of parametric type, if not in the cache, create and + // insert the cache. BaseStorage *GetOrCreateParametricStorage( TypeId type_id, std::size_t hash_value, @@ -79,8 +84,7 @@ struct StorageUniquerImpl { hash_value, is_equal_func, ctor_func); } - /// \brief Get the storage of singleton type. - /// \param type_id The type id of the AbstractType. + // Get the storage of singleton type. BaseStorage *GetSingletonStorage(TypeId type_id) { if (singleton_instances_.find(type_id) == singleton_instances_.end()) PD_THROW("The input data pointer is null."); @@ -88,15 +92,19 @@ struct StorageUniquerImpl { return singleton_instance; } + // Register a new parametric storage class. void RegisterParametricStorageType( TypeId type_id, std::function del_func); + // Register a new singleton storage class. void RegisterSingletonStorageType(TypeId type_id, std::function init_func); + // This map is a mapping between type id and parameteric type storage. std::unordered_map> parametric_uniquers_; + // This map is a mapping between type id and singleton type storage. std::unordered_map singleton_instances_; }; diff --git a/paddle/ir/type/storage_uniquer.h b/paddle/ir/type/storage_uniquer.h index e3addb00dbbc5a..fc4dc422b72db3 100644 --- a/paddle/ir/type/storage_uniquer.h +++ b/paddle/ir/type/storage_uniquer.h @@ -21,9 +21,12 @@ #include "paddle/ir/type/type_id.h" namespace ir { +/// /// \brief The implementation of the class StorageUniquer. +/// struct StorageUniquerImpl; +/// /// \brief A utility class for getting or creating Storage class instances. /// Storage class must be a derived class of StorageUniquer::BaseStorage. /// There are two types of Storage class: @@ -34,10 +37,13 @@ struct StorageUniquerImpl; /// hash method on the ParamKey for storage and access; (3) Need to provide /// method 'bool operator==(const ParamKey &) const', used to compare Storage /// instance and ParamKey instance. +/// class StorageUniquer { public: - /// This class is the base class of all storage classes, + /// + /// \brief This class is the base class of all storage classes, /// and any type of storage needs to inherit from this class. + /// class BaseStorage { protected: BaseStorage() = default; @@ -47,11 +53,14 @@ class StorageUniquer { ~StorageUniquer(); + /// /// \brief Get a unique storage instance of parametric Type. + /// /// \param init_func Used to initialize a newly inserted storage instance. /// \param type_id The type id of the AbstractType. /// \param args Parameters of the wrapped function. /// \return A uniqued instance of Storage. + /// template Storage *get(std::function init_func, TypeId type_id, @@ -70,16 +79,22 @@ class StorageUniquer { type_id, hash_value, is_equal_func, ctor_func)); } + /// /// \brief Get a unique storage instance of singleton Type. + /// /// \param type_id The type id of the AbstractType. /// \return A uniqued instance of Storage. + /// template Storage *get(TypeId type_id) { return static_cast(GetSingletonStorageTypeImpl(type_id)); } + /// /// \brief Register a new parametric storage class. + /// /// \param type_id The type id of the AbstractType. + /// template void RegisterParametricStorageType(TypeId type_id) { if (std::is_trivially_destructible::value) { @@ -92,9 +107,12 @@ class StorageUniquer { } } - /// \brief Register a new parametric storage class. + /// + /// \brief Register a new singleton storage class. + /// /// \param type_id The type id of the AbstractType. /// \param init_func Used to initialize a newly inserted storage instance. + /// template void RegisterSingletonStorageType(TypeId type_id, std::function init_func) { @@ -121,6 +139,8 @@ class StorageUniquer { void RegisterSingletonStorageTypeImpl( TypeId type_id, std::function ctor_func); + /// \brief StorageUniquerImpl is the implementation class of the + /// StorageUniquer. std::unique_ptr impl_; }; diff --git a/paddle/ir/type/type.h b/paddle/ir/type/type.h index f72688b2dc43cf..d9b2c00a16be57 100644 --- a/paddle/ir/type/type.h +++ b/paddle/ir/type/type.h @@ -17,14 +17,23 @@ #include "paddle/ir/type/type_support.h" namespace ir { -/// \brief class Type +/// +/// \brief Unified interface of the Type class. Derivation of all Type classes +/// only derives interfaces, not members. For example, DenseTensorType, +/// Float32Type, etc. are all derived classes of Type, but no new member +/// variables will be added. +/// class Type { public: + template + using TypeBase = + ir::StorageUserBase; + using ImplType = TypeStorage; constexpr Type() = default; - explicit Type(const ImplType *impl) : impl_(const_cast(impl)) {} + Type(const ImplType *impl) : impl_(const_cast(impl)) {} // NOLINT Type(const Type &other) = default; diff --git a/paddle/ir/type/type_base.h b/paddle/ir/type/type_base.h index f905fb64f79dde..42309bf586686c 100644 --- a/paddle/ir/type/type_base.h +++ b/paddle/ir/type/type_base.h @@ -18,13 +18,21 @@ #include "paddle/ir/type/type_id.h" namespace ir { +/// +/// \brief A utility class, when defining a concrete type ConcreteT, you need to +/// consider its base class BaseT and the corresponding memory type StorageT. We +/// connect the three by providing a TypeBase template tool class. +/// template -class TypeBase : public BaseT { +class StorageUserBase : public BaseT { public: - using Base = TypeBase; + using BaseT::BaseT; + + using Base = StorageUserBase; + using ImplType = StorageT; static TypeId type_id() { return TypeId::get(); } diff --git a/paddle/ir/type/type_id.h b/paddle/ir/type/type_id.h index 6aa72decd0e3ea..88b5878d178a22 100644 --- a/paddle/ir/type/type_id.h +++ b/paddle/ir/type/type_id.h @@ -18,42 +18,57 @@ namespace ir { +/// /// \brief TypeId is the unique identification of Type, each Type corresponds to /// a unique TypeId, the same id indicates the same Type class. TypeId provides /// an instantiation interface: TypeId::get. +/// /// Example: /// \code{cpp} /// class TypeA {}; /// TypeId type_a_id = TypeId::get(); /// \endcode +/// class TypeId { struct Storage {}; public: + /// /// \brief Returns the unique TypeId of Type T. + /// /// \return The unique TypeId of Type T. + /// template static TypeId get() { static Storage instance; return TypeId(&instance); } + /// /// \brief Comparison operations. + /// inline bool operator==(const TypeId &other) const { return storage_ == other.storage_; } + /// /// \brief Comparison operations. + /// inline bool operator!=(const TypeId &other) const { return !(*this == other); } + /// /// \brief Enable hashing TypeId instances. + /// friend struct std::hash; private: + /// /// \brief Construct a TypeId and initialize storage. + /// /// \param storage The storage of this TypeId. + /// explicit TypeId(const Storage *storage) : storage_(storage) {} const Storage *storage_; @@ -61,9 +76,10 @@ class TypeId { } // namespace ir -// Custom specialization of std::hash can be injected in namespace std. namespace std { +/// /// \brief Enable hashing TypeId instances. +/// template <> struct hash { std::size_t operator()(const ir::TypeId &obj) const { diff --git a/paddle/ir/type/type_support.h b/paddle/ir/type/type_support.h index 397f50ceb72606..886effb2a738da 100644 --- a/paddle/ir/type/type_support.h +++ b/paddle/ir/type/type_support.h @@ -16,60 +16,89 @@ #include "paddle/ir/ir_context.h" #include "paddle/ir/type/storage_uniquer.h" +#include "paddle/ir/type/type_base.h" namespace ir { +/// /// \brief Abstract the properties and behaviors common to all Type classes into /// an AbstractType class. There are two types in Type system: /// on-parameter/singleton type and parameter-type. The common attributes of all /// types is TypeId (and possibly others). Therefore, construct a class with /// TypeId as its member. +/// class AbstractType { public: + /// /// \brief Construct an AbstractType by TypeId directly. + /// /// \param type_id The type id of the AbstractType. + /// static AbstractType get(TypeId type_id) { return AbstractType(type_id); } + /// /// \brief Returns the type id of the AbstractType. + /// /// \return The type id of the AbstractType. + /// TypeId type_id() const { return type_id_; } + /// /// \brief Find the AbstractType instance whose TypeId is type_id from - /// IrContext. \param type_id The type id of the AbstractType. \param ctx The - /// IrContext. \return The AbstractType instance whose TypeId is type_id. + /// IrContext. + /// + /// \param type_id The type id of the AbstractType. + /// \param ctx The IrContext. + /// \return The AbstractType instance whose TypeId is type_id. + /// static const AbstractType &lookup(TypeId type_id, IrContext *ctx); private: + /// /// \brief The constructor is set to private and provides the user with the /// get method to obtain and manage the AstractType. + /// /// \param type_id The type id of the AbstractType. + /// explicit AbstractType(TypeId type_id) : type_id_(type_id) {} TypeId type_id_; }; +/// /// \brief TypeStorage is used to store all information of a Type. A Type object /// contains a TypeStorage. For non-parameter type, the information includes: /// TypeId, so TypeStorage only needs to include AbstractType; For parameter /// type, in addition to AbstractType/TypeId, parameter information needs to be /// included. So that, non-parameter type can be constructed by TypeStorage /// directly but parameter type should be constructed by Derived TypeStorage. +/// class TypeStorage : public StorageUniquer::BaseStorage { friend StorageUniquer; public: + /// /// \brief Construct a TypeStorage and initialize abstract_type. + /// /// \param abstract_type The abstract_type of this TypeStorage. + /// explicit TypeStorage(AbstractType *abstract_type) : abstract_type_(abstract_type) {} + /// /// \brief Returns the AbstractType of the TypeStorage. + /// /// \return The AbstractType of the TypeStorage. + /// const AbstractType &abstract_type() { return *abstract_type_; } private: + /// /// \brief Initialize TypeStorage based on the AbstractType* provided by the - /// user \param abstract_type AbstractType* provided by the user, the + /// user + /// + /// \param abstract_type AbstractType* provided by the user, the /// construction method of AbstractType refers to AbstractType::get. + /// void initialize(const AbstractType &abstract_type) { abstract_type_ = const_cast(&abstract_type); } @@ -77,33 +106,40 @@ class TypeStorage : public StorageUniquer::BaseStorage { AbstractType *abstract_type_{nullptr}; }; +/// /// \brief TypeUniquer is a utility class that provides interfaces for get or /// unique Type instances in IrContext. +/// struct TypeUniquer { + /// /// \brief Get a unique instance of Type T from IrContext. Note: For a /// parameteric_type, if not found in IrContext, it will try to create a new /// instance and register it to IrContext; for a singleton_type, only search. + /// /// \param ctx The IrContext instance. /// \param args Parameters of the wrapped function. /// \return The unique instance of Type T from IrContext. + /// template static T get(IrContext *ctx, Args &&...args) { return GetWithTypeId( - ctx, - T::type_id(), - std::forward(args)...); // class Type需要提供type_id接口 + ctx, T::type_id(), std::forward(args)...); } + /// /// \brief Get a unique instance of parametric Type T from IrContext. If not /// found in IrContext, it will try to create a new instance and register it - /// to IrContext; \param ctx The IrContext instance. \param type_id The type - /// id of the AbstractType. \param args Parameters of the wrapped function. + /// to IrContext; + /// + /// \param ctx The IrContext instance. + /// \param type_id The type id of the AbstractType. + /// \param args Parameters of the wrapped function. /// \return The unique instance of Type T from IrContext. + /// template - static std::enable_if_t< - !std::is_same::value, - T> // T(class Type)需要提供ImplType(using ImplType=TypeStorage/派生) - GetWithTypeId(IrContext *ctx, TypeId type_id, Args &&...args) { + static std:: + enable_if_t::value, T> + GetWithTypeId(IrContext *ctx, TypeId type_id, Args &&...args) { return ctx->storage_uniquer().get( [&, type_id](TypeStorage *storage) { storage->initialize(AbstractType::lookup(type_id, ctx)); @@ -112,26 +148,37 @@ struct TypeUniquer { std::forward(args)...); } + /// /// \brief Get a unique instance of singleton Type T from IrContext, only - /// search. \param ctx The IrContext instance. \param type_id The type id of - /// the AbstractType. \return The unique instance of Type T from IrContext. + /// search. + /// + /// \param ctx The IrContext instance. + /// \param type_id The type id of the AbstractType. + /// \return The unique instance of Type T from IrContext. + /// template static std:: enable_if_t::value, T> GetWithTypeId(IrContext *ctx, TypeId type_id) { - return ctx->storage_uniquer().get(type_id); + return ctx->storage_uniquer().get(type_id); } + /// /// \brief Register a unique instance of Type T to IrContext. + /// /// \param ctx The IrContext instance. + /// template static void RegisterType(IrContext *ctx) { RegisterType(ctx, T::type_id()); // class Type需要提供type_id接口 } + /// /// \brief Register a unique instance of parametric Type T to IrContext. + /// /// \param ctx The IrContext instance. /// \param type_id The type id of the Type T. + /// template static std::enable_if_t< !std::is_same::value> @@ -140,9 +187,12 @@ struct TypeUniquer { type_id); } + /// /// \brief Register a unique instance of singleton Type T to IrContext. + /// /// \param ctx The IrContext instance. /// \param type_id The type id of the Type T. + /// template static std::enable_if_t< std::is_same::value> diff --git a/paddle/ir/type/type_support_test.cc b/paddle/ir/type/type_support_test.cc index f18db76c908b1e..fb295deb22515c 100644 --- a/paddle/ir/type/type_support_test.cc +++ b/paddle/ir/type/type_support_test.cc @@ -12,10 +12,11 @@ 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 "paddle/ir/type/type_support.h" #include #include + #include "paddle/ir/type/type_id.h" +#include "paddle/ir/type/type_support.h" TEST(type_support, type_id) { class TypeA {}; From 4cdcc24803adaadc1a78979e9b5cadc0c20ed5fc Mon Sep 17 00:00:00 2001 From: zhangbo9674 Date: Tue, 14 Feb 2023 07:05:06 +0000 Subject: [PATCH 05/26] add bulit-in Float32Type --- paddle/ir/CMakeLists.txt | 11 +++++++---- paddle/ir/ir_context.cc | 18 ++++++++++++++++-- paddle/ir/ir_context.h | 17 +++++++++++++++++ paddle/ir/ir_context_test.cc | 28 +++++++++++++++------------- paddle/ir/type/storage_uniquer.cc | 19 +++++++------------ paddle/ir/type/storage_uniquer.h | 1 + paddle/ir/type/type_id.h | 1 + paddle/ir/type/type_support.h | 3 +++ paddle/ir/type/type_support_test.cc | 26 +++++++++++++------------- 9 files changed, 80 insertions(+), 44 deletions(-) diff --git a/paddle/ir/CMakeLists.txt b/paddle/ir/CMakeLists.txt index a47e83803a183a..747f6230ab558d 100644 --- a/paddle/ir/CMakeLists.txt +++ b/paddle/ir/CMakeLists.txt @@ -2,14 +2,17 @@ if(NOT WITH_NEWIR) return() endif() +message(STATUS, "add subdir type") add_subdirectory(type) +set(NEWIR_SOURCE_DIR "${PADDLE_SOURCE_DIR}/paddle/ir") +set(NEWIR_BINARY_DIR "${PADDLE_BINARY_DIR}/paddle/ir") + +message(STATUS, "cc_library ir_context") cc_library( ir_context SRCS ir_context.cc DEPS storage_uniquer) -cc_test( - ir_context_test - SRCS ir_context_test.cc - DEPS gtest ir_context) +message(STATUS, "cc_test ir_context_test") +cc_test_old(ir_context_test SRCS ir_context_test.cc DEPS ir_context gtest) diff --git a/paddle/ir/ir_context.cc b/paddle/ir/ir_context.cc index 2299e15eea9080..2bd87adbfc44b7 100644 --- a/paddle/ir/ir_context.cc +++ b/paddle/ir/ir_context.cc @@ -17,7 +17,6 @@ #include "paddle/ir/builtin_type.h" #include "paddle/ir/ir_context.h" #include "paddle/ir/type/type_support.h" -#include "paddle/phi/api/ext/exception.h" namespace ir { // The implementation class of the IrContext class @@ -37,7 +36,15 @@ class IrContextImpl { Float32Type fp32_type; }; +IrContext *IrContext::ir_context_ = nullptr; + IrContext::IrContext() : impl_(new IrContextImpl()) { + VLOG(4) << "==> Constructor for IrContext."; + VLOG(4) << "==> Register Float32Type."; + AbstractType *abstract_type = new AbstractType( + std::move(AbstractType::get(TypeId::get()))); + registed_abstracted_type().emplace(TypeId::get(), abstract_type); + TypeUniquer::RegisterType(this); impl_->fp32_type = TypeUniquer::get(this); } @@ -45,11 +52,18 @@ StorageUniquer &IrContext::storage_uniquer() { return impl().registed_storage_uniquer_; } +std::unordered_map + &IrContext::registed_abstracted_type() { + return impl().registed_abstract_types_; +} + const AbstractType &AbstractType::lookup(TypeId type_id, IrContext *ctx) { + VLOG(4) << "==> Get registed abstract type (" << &type_id + << ") from IrContext (" << ctx << ")."; auto &impl = ctx->impl(); auto iter = impl.registed_abstract_types_.find(type_id); if (iter == impl.registed_abstract_types_.end()) { - PD_THROW("The input data pointer is null."); + throw("Abstract type not found in IrContext."); } else { return *(iter->second); } diff --git a/paddle/ir/ir_context.h b/paddle/ir/ir_context.h index 45f836bedf2e97..3d17897be704e4 100644 --- a/paddle/ir/ir_context.h +++ b/paddle/ir/ir_context.h @@ -14,11 +14,15 @@ #pragma once +#include #include +#include namespace ir { class IrContextImpl; class StorageUniquer; +class AbstractType; +class TypeId; /// /// \brief IrContext is a global singleton class used to store and manage Type @@ -32,9 +36,12 @@ class IrContext { /// \return Global singleton for IrContext. /// static IrContext *Instance() { + VLOG(4) << "=> Instance called with context (ir_context_ == " << ir_context_ + << ")."; if (ir_context_ == nullptr) { ir_context_ = new IrContext(); } + VLOG(4) << " |-> (ir_context_ == " << ir_context_ << ")."; return ir_context_; } @@ -48,6 +55,7 @@ class IrContext { /// IrContextImpl &impl() { return *impl_; } + /// /// \brief Returns the storage uniquer used for constructing TypeStorage /// instances. /// @@ -56,6 +64,15 @@ class IrContext { /// StorageUniquer &storage_uniquer(); + /// + /// \brief Returns the storage uniquer used for constructing TypeStorage + /// instances. + /// + /// \return The storage uniquer used for constructing TypeStorage + /// instances. + /// + std::unordered_map ®isted_abstracted_type(); + private: IrContext(); diff --git a/paddle/ir/ir_context_test.cc b/paddle/ir/ir_context_test.cc index 044140a3a212e9..940463a45fcd17 100644 --- a/paddle/ir/ir_context_test.cc +++ b/paddle/ir/ir_context_test.cc @@ -1,23 +1,25 @@ -/* Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved. - -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. */ +// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved. +// +// 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 "paddle/ir/builtin_type.h" #include "paddle/ir/ir_context.h" +#include "paddle/ir/type/type_support.h" TEST(ir_context, ir_context) { ir::IrContext *ctx = ir::IrContext::Instance(); + auto &impl = ctx->impl(); ir::Type fp32 = ir::Float32Type::get(ctx); } diff --git a/paddle/ir/type/storage_uniquer.cc b/paddle/ir/type/storage_uniquer.cc index 9fa6b58422443b..8296083af4542b 100644 --- a/paddle/ir/type/storage_uniquer.cc +++ b/paddle/ir/type/storage_uniquer.cc @@ -16,7 +16,6 @@ #include #include "paddle/ir/type/storage_uniquer.h" -#include "paddle/phi/api/ext/exception.h" namespace ir { // This is a structure for creating, caching, and looking up Storage of @@ -77,7 +76,7 @@ struct StorageUniquerImpl { std::function is_equal_func, std::function ctor_func) { if (parametric_uniquers_.find(type_id) == parametric_uniquers_.end()) - PD_THROW("The input data pointer is null."); + throw("The input data pointer is null."); ParametricStorageUniquer ¶metric_storage = *parametric_uniquers_[type_id]; return parametric_storage.GetOrCreateParametricStorage( @@ -86,20 +85,13 @@ struct StorageUniquerImpl { // Get the storage of singleton type. BaseStorage *GetSingletonStorage(TypeId type_id) { + VLOG(4) << "==> StorageUniquerImpl::GetSingletonStorage()."; if (singleton_instances_.find(type_id) == singleton_instances_.end()) - PD_THROW("The input data pointer is null."); + throw("TypeId not found in IrContext."); BaseStorage *singleton_instance = singleton_instances_[type_id]; return singleton_instance; } - // Register a new parametric storage class. - void RegisterParametricStorageType( - TypeId type_id, std::function del_func); - - // Register a new singleton storage class. - void RegisterSingletonStorageType(TypeId type_id, - std::function init_func); - // This map is a mapping between type id and parameteric type storage. std::unordered_map> parametric_uniquers_; @@ -110,6 +102,8 @@ struct StorageUniquerImpl { StorageUniquer::StorageUniquer() : impl_(new StorageUniquerImpl()) {} +StorageUniquer::~StorageUniquer() = default; + StorageUniquer::BaseStorage *StorageUniquer::GetParametricStorageTypeImpl( TypeId type_id, std::size_t hash_value, @@ -132,9 +126,10 @@ void StorageUniquer::RegisterParametricStorageTypeImpl( void StorageUniquer::RegisterSingletonStorageTypeImpl( TypeId type_id, std::function ctor_func) { + VLOG(4) << "==> StorageUniquer::RegisterSingletonStorageTypeImpl()"; if (impl_->singleton_instances_.find(type_id) != impl_->singleton_instances_.end()) - PD_THROW("storage class already registered"); + throw("storage class already registered"); impl_->singleton_instances_.emplace(type_id, ctor_func()); } diff --git a/paddle/ir/type/storage_uniquer.h b/paddle/ir/type/storage_uniquer.h index fc4dc422b72db3..a23e5e3fcfa726 100644 --- a/paddle/ir/type/storage_uniquer.h +++ b/paddle/ir/type/storage_uniquer.h @@ -116,6 +116,7 @@ class StorageUniquer { template void RegisterSingletonStorageType(TypeId type_id, std::function init_func) { + VLOG(4) << "==> StorageUniquer::RegisterSingletonStorageType()"; auto ctor_func = [&]() { auto *storage = new Storage(nullptr); if (init_func) init_func(storage); diff --git a/paddle/ir/type/type_id.h b/paddle/ir/type/type_id.h index 88b5878d178a22..7dc2ac651224be 100644 --- a/paddle/ir/type/type_id.h +++ b/paddle/ir/type/type_id.h @@ -14,6 +14,7 @@ #pragma once +#include #include namespace ir { diff --git a/paddle/ir/type/type_support.h b/paddle/ir/type/type_support.h index 886effb2a738da..05c5a6a42e66d4 100644 --- a/paddle/ir/type/type_support.h +++ b/paddle/ir/type/type_support.h @@ -64,6 +64,8 @@ class AbstractType { TypeId type_id_; }; +struct TypeUniquer; + /// /// \brief TypeStorage is used to store all information of a Type. A Type object /// contains a TypeStorage. For non-parameter type, the information includes: @@ -74,6 +76,7 @@ class AbstractType { /// class TypeStorage : public StorageUniquer::BaseStorage { friend StorageUniquer; + friend TypeUniquer; public: /// diff --git a/paddle/ir/type/type_support_test.cc b/paddle/ir/type/type_support_test.cc index fb295deb22515c..5b1bf0214cf5b2 100644 --- a/paddle/ir/type/type_support_test.cc +++ b/paddle/ir/type/type_support_test.cc @@ -1,16 +1,16 @@ -/* Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved. - -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. */ +// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved. +// +// 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 From f5cb63dd84ee8c24b9c5e5e91083ede1fa037b3e Mon Sep 17 00:00:00 2001 From: zhangbo9674 Date: Tue, 14 Feb 2023 07:15:08 +0000 Subject: [PATCH 06/26] refine ut --- paddle/ir/ir_context_test.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/paddle/ir/ir_context_test.cc b/paddle/ir/ir_context_test.cc index 940463a45fcd17..c81dc9961653c2 100644 --- a/paddle/ir/ir_context_test.cc +++ b/paddle/ir/ir_context_test.cc @@ -20,6 +20,7 @@ TEST(ir_context, ir_context) { ir::IrContext *ctx = ir::IrContext::Instance(); - auto &impl = ctx->impl(); - ir::Type fp32 = ir::Float32Type::get(ctx); + ir::Type fp32_1 = ir::Float32Type::get(ctx); + ir::Type fp32_2 = ir::Float32Type::get(ctx); + EXPECT_EQ(fp32_1 == fp32_2, 1); } From 4fe071a653b7b10f52c5181ca22e30be0afc163b Mon Sep 17 00:00:00 2001 From: zhangbo9674 Date: Wed, 15 Feb 2023 11:26:48 +0000 Subject: [PATCH 07/26] refine code --- paddle/ir/CMakeLists.txt | 3 --- paddle/ir/builtin_type.h | 46 +++++++++++++++++++++++++++++++- paddle/ir/ir_context.cc | 36 +++++++++++++++++++++++-- paddle/ir/ir_context_test.cc | 15 ++++++++++- paddle/ir/type/storage_uniquer.h | 11 +++++--- paddle/ir/type/type.h | 21 ++++++++++++++- paddle/ir/type/type_id.h | 4 --- paddle/ir/type/type_support.h | 2 ++ 8 files changed, 123 insertions(+), 15 deletions(-) diff --git a/paddle/ir/CMakeLists.txt b/paddle/ir/CMakeLists.txt index 747f6230ab558d..81cf0733347f79 100644 --- a/paddle/ir/CMakeLists.txt +++ b/paddle/ir/CMakeLists.txt @@ -2,17 +2,14 @@ if(NOT WITH_NEWIR) return() endif() -message(STATUS, "add subdir type") add_subdirectory(type) set(NEWIR_SOURCE_DIR "${PADDLE_SOURCE_DIR}/paddle/ir") set(NEWIR_BINARY_DIR "${PADDLE_BINARY_DIR}/paddle/ir") -message(STATUS, "cc_library ir_context") cc_library( ir_context SRCS ir_context.cc DEPS storage_uniquer) -message(STATUS, "cc_test ir_context_test") cc_test_old(ir_context_test SRCS ir_context_test.cc DEPS ir_context gtest) diff --git a/paddle/ir/builtin_type.h b/paddle/ir/builtin_type.h index 938201d1dd3971..a5f3f82af4b158 100644 --- a/paddle/ir/builtin_type.h +++ b/paddle/ir/builtin_type.h @@ -22,10 +22,54 @@ namespace ir { /// Type fp32 = Float32Type::get(ctx); /// class Float32Type - : public Type::TypeBase { + : public ir::Type::TypeBase { public: using Base::Base; static Float32Type get(ir::IrContext *context); }; +struct IntegerTypeStorage; +class IntegerType + : public ir::Type::TypeBase { + public: + using Base::Base; + + /// Integer representation maximal bitwidth. + /// Note: This is aligned with the maximum width of llvm::IntegerType. + static constexpr unsigned kMaxWidth = (1 << 24) - 1; + + static IntegerType get(ir::IrContext *context, + unsigned width, + unsigned signedness = 0); +}; + +struct IntegerTypeStorage : public TypeStorage { + IntegerTypeStorage(unsigned width, unsigned signedness) + : width_(width), signedness_(signedness) {} + using ParamKey = std::pair; + + static std::size_t HashValue(const ParamKey &key) { + return hash_combine(std::hash()(std::get<0>(key)), + std::hash()(std::get<1>(key))); + } + + bool operator==(const ParamKey &key) const { + return ParamKey(width_, signedness_) == key; + } + + static IntegerTypeStorage *Construct(ParamKey key) { + return new IntegerTypeStorage(key.first, key.second); + } + + ParamKey GetAsKey() const { return ParamKey(width_, signedness_); } + + unsigned width_ : 30; + unsigned signedness_ : 2; + + private: + static std::size_t hash_combine(std::size_t lhs, std::size_t rhs) { + return lhs ^= rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2); + } +}; + } // namespace ir diff --git a/paddle/ir/ir_context.cc b/paddle/ir/ir_context.cc index 2bd87adbfc44b7..ce3b4aac62e35e 100644 --- a/paddle/ir/ir_context.cc +++ b/paddle/ir/ir_context.cc @@ -34,18 +34,29 @@ class IrContextImpl { // Some built-in type. Float32Type fp32_type; + IntegerType int1Ty; }; IrContext *IrContext::ir_context_ = nullptr; IrContext::IrContext() : impl_(new IrContextImpl()) { VLOG(4) << "==> Constructor for IrContext."; + VLOG(4) << "==> Register Float32Type."; - AbstractType *abstract_type = new AbstractType( + AbstractType *fp32_abstract_type = new AbstractType( std::move(AbstractType::get(TypeId::get()))); - registed_abstracted_type().emplace(TypeId::get(), abstract_type); + registed_abstracted_type().emplace(TypeId::get(), + fp32_abstract_type); TypeUniquer::RegisterType(this); impl_->fp32_type = TypeUniquer::get(this); + + VLOG(4) << "==> Register IntegerType."; + AbstractType *int_abstract_type = new AbstractType( + std::move(AbstractType::get(TypeId::get()))); + registed_abstracted_type().emplace(TypeId::get(), + int_abstract_type); + TypeUniquer::RegisterType(this); + impl_->int1Ty = TypeUniquer::get(this, 1, 0); } StorageUniquer &IrContext::storage_uniquer() { @@ -71,4 +82,25 @@ const AbstractType &AbstractType::lookup(TypeId type_id, IrContext *ctx) { Float32Type Float32Type::get(IrContext *ctx) { return ctx->impl().fp32_type; } +static IntegerType GetCachedIntegerType(unsigned width, + unsigned signedness, + IrContext *context) { + if (signedness != 0) return IntegerType(); + + switch (width) { + case 1: + return context->impl().int1Ty; + default: + return IntegerType(); + } +} + +IntegerType IntegerType::get(ir::IrContext *context, + unsigned width, + unsigned signedness) { + if (auto cached = GetCachedIntegerType(width, signedness, context)) + return cached; + return Base::get(context, width, signedness); +} + } // namespace ir diff --git a/paddle/ir/ir_context_test.cc b/paddle/ir/ir_context_test.cc index c81dc9961653c2..c77d5549cc03b2 100644 --- a/paddle/ir/ir_context_test.cc +++ b/paddle/ir/ir_context_test.cc @@ -18,9 +18,22 @@ #include "paddle/ir/ir_context.h" #include "paddle/ir/type/type_support.h" -TEST(ir_context, ir_context) { +TEST(ir_context, type) { + // Test creation of built-in singleton type. ir::IrContext *ctx = ir::IrContext::Instance(); ir::Type fp32_1 = ir::Float32Type::get(ctx); + + // Test interfaces of class Type ir::Type fp32_2 = ir::Float32Type::get(ctx); EXPECT_EQ(fp32_1 == fp32_2, 1); + EXPECT_EQ(fp32_1 != fp32_2, 0); + EXPECT_EQ(fp32_1.type_id() == fp32_2.type_id(), 1); + EXPECT_EQ(&fp32_1.abstract_type() == + &ir::AbstractType::lookup(fp32_1.type_id(), ctx), + 1); + EXPECT_EQ(ir::Float32Type::classof(fp32_1), 1); + + ir::Type int1_1 = ir::IntegerType::get(ctx, 1, 0); + ir::Type int1_2 = ir::IntegerType::get(ctx, 1, 0); + EXPECT_EQ(int1_1 == int1_2, 1); } diff --git a/paddle/ir/type/storage_uniquer.h b/paddle/ir/type/storage_uniquer.h index a23e5e3fcfa726..cf015e43248cac 100644 --- a/paddle/ir/type/storage_uniquer.h +++ b/paddle/ir/type/storage_uniquer.h @@ -65,9 +65,9 @@ class StorageUniquer { Storage *get(std::function init_func, TypeId type_id, Args &&...args) { - auto derived_param_key = Storage::ParamKey(std::forward(args)...); + auto derived_param_key = GetParamKey(std::forward(args)...); std::size_t hash_value = Storage::HashValue(derived_param_key); - bool is_equal_func = [&derived_param_key](const BaseStorage *existing) { + auto is_equal_func = [&derived_param_key](const BaseStorage *existing) { return static_cast(*existing) == derived_param_key; }; auto ctor_func = [&]() { @@ -118,7 +118,7 @@ class StorageUniquer { std::function init_func) { VLOG(4) << "==> StorageUniquer::RegisterSingletonStorageType()"; auto ctor_func = [&]() { - auto *storage = new Storage(nullptr); + auto *storage = new Storage(); if (init_func) init_func(storage); return storage; }; @@ -140,6 +140,11 @@ class StorageUniquer { void RegisterSingletonStorageTypeImpl( TypeId type_id, std::function ctor_func); + template + static typename ImplTy::ParamKey GetParamKey(Args &&...args) { + return typename ImplTy::ParamKey(args...); + } + /// \brief StorageUniquerImpl is the implementation class of the /// StorageUniquer. std::unique_ptr impl_; diff --git a/paddle/ir/type/type.h b/paddle/ir/type/type.h index d9b2c00a16be57..8367ba0be27a1c 100644 --- a/paddle/ir/type/type.h +++ b/paddle/ir/type/type.h @@ -39,8 +39,10 @@ class Type { Type &operator=(const Type &other) = default; + /// + /// \brief Comparison operations. + /// bool operator==(Type other) const { return impl_ == other.impl_; } - bool operator!=(Type other) const { return impl_ != other.impl_; } explicit operator bool() const { return impl_; } @@ -53,8 +55,25 @@ class Type { ImplType *impl() const { return impl_; } + /// + /// \brief Enable hashing Type. + /// + friend struct std::hash; + protected: ImplType *impl_{nullptr}; }; } // namespace ir + +namespace std { +/// +/// \brief Enable hashing Type. +/// +template <> +struct hash { + std::size_t operator()(const ir::Type &obj) const { + return std::hash()(obj.impl_); + } +}; +} // namespace std diff --git a/paddle/ir/type/type_id.h b/paddle/ir/type/type_id.h index 7dc2ac651224be..b7a2dcd362d012 100644 --- a/paddle/ir/type/type_id.h +++ b/paddle/ir/type/type_id.h @@ -51,10 +51,6 @@ class TypeId { inline bool operator==(const TypeId &other) const { return storage_ == other.storage_; } - - /// - /// \brief Comparison operations. - /// inline bool operator!=(const TypeId &other) const { return !(*this == other); } diff --git a/paddle/ir/type/type_support.h b/paddle/ir/type/type_support.h index 05c5a6a42e66d4..e4d244a9bf0d7d 100644 --- a/paddle/ir/type/type_support.h +++ b/paddle/ir/type/type_support.h @@ -87,6 +87,8 @@ class TypeStorage : public StorageUniquer::BaseStorage { explicit TypeStorage(AbstractType *abstract_type) : abstract_type_(abstract_type) {} + TypeStorage() {} + /// /// \brief Returns the AbstractType of the TypeStorage. /// From 23d22af0f7713bd9f54bf562a97cb502b5424713 Mon Sep 17 00:00:00 2001 From: zhangbo9674 Date: Thu, 16 Feb 2023 07:20:42 +0000 Subject: [PATCH 08/26] refine code --- paddle/ir/CMakeLists.txt | 6 +++-- paddle/ir/builtin_type.h | 31 ++++++++++++++++++++++- paddle/ir/ir_context.cc | 16 +++++++++++- paddle/ir/ir_context_test.cc | 19 +++++++++++++- paddle/ir/{type => }/storage_uniquer.cc | 2 +- paddle/ir/{type => }/storage_uniquer.h | 2 +- paddle/ir/{type => }/type.h | 2 +- paddle/ir/type/CMakeLists.txt | 6 ----- paddle/ir/{type => }/type_base.h | 4 +-- paddle/ir/{type => }/type_id.h | 0 paddle/ir/{type => }/type_support.h | 4 +-- paddle/ir/{type => }/type_support_test.cc | 4 +-- 12 files changed, 76 insertions(+), 20 deletions(-) rename paddle/ir/{type => }/storage_uniquer.cc (99%) rename paddle/ir/{type => }/storage_uniquer.h (99%) rename paddle/ir/{type => }/type.h (98%) delete mode 100644 paddle/ir/type/CMakeLists.txt rename paddle/ir/{type => }/type_base.h (95%) rename paddle/ir/{type => }/type_id.h (100%) rename paddle/ir/{type => }/type_support.h (98%) rename paddle/ir/{type => }/type_support_test.cc (95%) diff --git a/paddle/ir/CMakeLists.txt b/paddle/ir/CMakeLists.txt index 81cf0733347f79..91dd528e781f7b 100644 --- a/paddle/ir/CMakeLists.txt +++ b/paddle/ir/CMakeLists.txt @@ -2,14 +2,16 @@ if(NOT WITH_NEWIR) return() endif() -add_subdirectory(type) - set(NEWIR_SOURCE_DIR "${PADDLE_SOURCE_DIR}/paddle/ir") set(NEWIR_BINARY_DIR "${PADDLE_BINARY_DIR}/paddle/ir") +cc_library(storage_uniquer SRCS storage_uniquer.cc) + cc_library( ir_context SRCS ir_context.cc DEPS storage_uniquer) +cc_test_old(type_support_test SRCS type_support_test.cc DEPS gtest) + cc_test_old(ir_context_test SRCS ir_context_test.cc DEPS ir_context gtest) diff --git a/paddle/ir/builtin_type.h b/paddle/ir/builtin_type.h index a5f3f82af4b158..17e728654f5d1d 100644 --- a/paddle/ir/builtin_type.h +++ b/paddle/ir/builtin_type.h @@ -14,7 +14,7 @@ #pragma once -#include "paddle/ir/type/type.h" +#include "paddle/ir/type.h" namespace ir { /// @@ -28,6 +28,35 @@ class Float32Type static Float32Type get(ir::IrContext *context); }; +class Float32TypeBeta : public ir::Type { + public: + // 可以通过宏定义自动生成的(Float32TypeBeta, TypeStorage) + using Type::Type; // 必须提供 + + using ImplType = ir::TypeStorage; // 必须指定ImplType + + ImplType *impl() const { + return static_cast(this->impl_); + } // 必须提供 + + static TypeId type_id() { + return TypeId::get(); + } // 必须提供 + + template // 必须提供 + static bool classof(T val) { + return val.type_id() == type_id(); + } + + template // 必须提供 + static Float32TypeBeta create(IrContext *ctx, Args... args) { + return ir::TypeUniquer::template get(ctx, args...); + } + + // 手动提供的接口 + static Float32TypeBeta get(ir::IrContext *context); +}; + struct IntegerTypeStorage; class IntegerType : public ir::Type::TypeBase { diff --git a/paddle/ir/ir_context.cc b/paddle/ir/ir_context.cc index ce3b4aac62e35e..d888ee7617d3b8 100644 --- a/paddle/ir/ir_context.cc +++ b/paddle/ir/ir_context.cc @@ -16,7 +16,7 @@ #include "paddle/ir/builtin_type.h" #include "paddle/ir/ir_context.h" -#include "paddle/ir/type/type_support.h" +#include "paddle/ir/type_support.h" namespace ir { // The implementation class of the IrContext class @@ -35,6 +35,8 @@ class IrContextImpl { // Some built-in type. Float32Type fp32_type; IntegerType int1Ty; + + Float32TypeBeta fp32_type_beta; }; IrContext *IrContext::ir_context_ = nullptr; @@ -57,6 +59,14 @@ IrContext::IrContext() : impl_(new IrContextImpl()) { int_abstract_type); TypeUniquer::RegisterType(this); impl_->int1Ty = TypeUniquer::get(this, 1, 0); + + VLOG(4) << "==> Register Float32TypeBeta."; + AbstractType *fp32_abstract_type_beta = new AbstractType( + std::move(AbstractType::get(TypeId::get()))); + registed_abstracted_type().emplace(TypeId::get(), + fp32_abstract_type_beta); + TypeUniquer::RegisterType(this); + impl_->fp32_type_beta = TypeUniquer::get(this); } StorageUniquer &IrContext::storage_uniquer() { @@ -82,6 +92,10 @@ const AbstractType &AbstractType::lookup(TypeId type_id, IrContext *ctx) { Float32Type Float32Type::get(IrContext *ctx) { return ctx->impl().fp32_type; } +Float32TypeBeta Float32TypeBeta::get(IrContext *ctx) { + return ctx->impl().fp32_type_beta; +} + static IntegerType GetCachedIntegerType(unsigned width, unsigned signedness, IrContext *context) { diff --git a/paddle/ir/ir_context_test.cc b/paddle/ir/ir_context_test.cc index c77d5549cc03b2..c508a49c084f1f 100644 --- a/paddle/ir/ir_context_test.cc +++ b/paddle/ir/ir_context_test.cc @@ -16,7 +16,7 @@ #include "paddle/ir/builtin_type.h" #include "paddle/ir/ir_context.h" -#include "paddle/ir/type/type_support.h" +#include "paddle/ir/type_support.h" TEST(ir_context, type) { // Test creation of built-in singleton type. @@ -37,3 +37,20 @@ TEST(ir_context, type) { ir::Type int1_2 = ir::IntegerType::get(ctx, 1, 0); EXPECT_EQ(int1_1 == int1_2, 1); } + +TEST(ir_context, type_beta) { + // Test creation of built-in singleton type. + ir::IrContext *ctx = ir::IrContext::Instance(); + ir::Type fp32_beta_1 = ir::Float32TypeBeta::get(ctx); + + // Test interfaces of class Type + ir::Type fp32_beta_2 = ir::Float32TypeBeta::get(ctx); + EXPECT_EQ(fp32_beta_1 == fp32_beta_2, 1); + EXPECT_EQ(fp32_beta_1 != fp32_beta_2, 0); + EXPECT_EQ(fp32_beta_1.type_id() == fp32_beta_2.type_id(), 1); + EXPECT_EQ(&fp32_beta_1.abstract_type() == + &ir::AbstractType::lookup(fp32_beta_1.type_id(), ctx), + 1); + EXPECT_EQ(ir::Float32TypeBeta::classof(fp32_beta_1), 1); + EXPECT_EQ(ir::Float32Type::classof(fp32_beta_1), 0); +} diff --git a/paddle/ir/type/storage_uniquer.cc b/paddle/ir/storage_uniquer.cc similarity index 99% rename from paddle/ir/type/storage_uniquer.cc rename to paddle/ir/storage_uniquer.cc index 8296083af4542b..06cc4daa55fd27 100644 --- a/paddle/ir/type/storage_uniquer.cc +++ b/paddle/ir/storage_uniquer.cc @@ -15,7 +15,7 @@ #include #include -#include "paddle/ir/type/storage_uniquer.h" +#include "paddle/ir/storage_uniquer.h" namespace ir { // This is a structure for creating, caching, and looking up Storage of diff --git a/paddle/ir/type/storage_uniquer.h b/paddle/ir/storage_uniquer.h similarity index 99% rename from paddle/ir/type/storage_uniquer.h rename to paddle/ir/storage_uniquer.h index cf015e43248cac..297b5cabfacf2c 100644 --- a/paddle/ir/type/storage_uniquer.h +++ b/paddle/ir/storage_uniquer.h @@ -18,7 +18,7 @@ #include #include -#include "paddle/ir/type/type_id.h" +#include "paddle/ir/type_id.h" namespace ir { /// diff --git a/paddle/ir/type/type.h b/paddle/ir/type.h similarity index 98% rename from paddle/ir/type/type.h rename to paddle/ir/type.h index 8367ba0be27a1c..cff21192a5fb2c 100644 --- a/paddle/ir/type/type.h +++ b/paddle/ir/type.h @@ -14,7 +14,7 @@ #pragma once -#include "paddle/ir/type/type_support.h" +#include "paddle/ir/type_support.h" namespace ir { /// diff --git a/paddle/ir/type/CMakeLists.txt b/paddle/ir/type/CMakeLists.txt deleted file mode 100644 index 5e5ff9d7223e4b..00000000000000 --- a/paddle/ir/type/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -cc_test( - type_support_test - SRCS type_support_test.cc - DEPS gtest) - -cc_library(storage_uniquer SRCS storage_uniquer.cc) diff --git a/paddle/ir/type/type_base.h b/paddle/ir/type_base.h similarity index 95% rename from paddle/ir/type/type_base.h rename to paddle/ir/type_base.h index 42309bf586686c..6c337287f321df 100644 --- a/paddle/ir/type/type_base.h +++ b/paddle/ir/type_base.h @@ -14,8 +14,8 @@ #pragma once -#include "paddle/ir/type/storage_uniquer.h" -#include "paddle/ir/type/type_id.h" +#include "paddle/ir/storage_uniquer.h" +#include "paddle/ir/type_id.h" namespace ir { /// diff --git a/paddle/ir/type/type_id.h b/paddle/ir/type_id.h similarity index 100% rename from paddle/ir/type/type_id.h rename to paddle/ir/type_id.h diff --git a/paddle/ir/type/type_support.h b/paddle/ir/type_support.h similarity index 98% rename from paddle/ir/type/type_support.h rename to paddle/ir/type_support.h index e4d244a9bf0d7d..47869a3389cf06 100644 --- a/paddle/ir/type/type_support.h +++ b/paddle/ir/type_support.h @@ -15,8 +15,8 @@ #pragma once #include "paddle/ir/ir_context.h" -#include "paddle/ir/type/storage_uniquer.h" -#include "paddle/ir/type/type_base.h" +#include "paddle/ir/storage_uniquer.h" +#include "paddle/ir/type_base.h" namespace ir { /// diff --git a/paddle/ir/type/type_support_test.cc b/paddle/ir/type_support_test.cc similarity index 95% rename from paddle/ir/type/type_support_test.cc rename to paddle/ir/type_support_test.cc index 5b1bf0214cf5b2..dc4c0ac54b0914 100644 --- a/paddle/ir/type/type_support_test.cc +++ b/paddle/ir/type_support_test.cc @@ -15,8 +15,8 @@ #include #include -#include "paddle/ir/type/type_id.h" -#include "paddle/ir/type/type_support.h" +#include "paddle/ir/type_id.h" +#include "paddle/ir/type_support.h" TEST(type_support, type_id) { class TypeA {}; From cc757389345a8b73f6bd215511b445c60067a268 Mon Sep 17 00:00:00 2001 From: zhangbo9674 Date: Thu, 16 Feb 2023 09:21:01 +0000 Subject: [PATCH 09/26] delete type_base --- paddle/ir/builtin_type.h | 68 ++++++++++++++++++++---------------- paddle/ir/ir_context.cc | 16 +-------- paddle/ir/ir_context_test.cc | 17 --------- paddle/ir/type.h | 4 --- paddle/ir/type_base.h | 54 ---------------------------- paddle/ir/type_support.h | 1 - 6 files changed, 39 insertions(+), 121 deletions(-) delete mode 100644 paddle/ir/type_base.h diff --git a/paddle/ir/builtin_type.h b/paddle/ir/builtin_type.h index 17e728654f5d1d..d2086ad00a15d5 100644 --- a/paddle/ir/builtin_type.h +++ b/paddle/ir/builtin_type.h @@ -21,16 +21,9 @@ namespace ir { /// \brief Interfaces for user-created built-in types. For example: /// Type fp32 = Float32Type::get(ctx); /// -class Float32Type - : public ir::Type::TypeBase { +class Float32Type : public ir::Type { public: - using Base::Base; - static Float32Type get(ir::IrContext *context); -}; - -class Float32TypeBeta : public ir::Type { - public: - // 可以通过宏定义自动生成的(Float32TypeBeta, TypeStorage) + // 可以通过宏定义自动生成的(Float32Type, TypeStorage) using Type::Type; // 必须提供 using ImplType = ir::TypeStorage; // 必须指定ImplType @@ -39,9 +32,7 @@ class Float32TypeBeta : public ir::Type { return static_cast(this->impl_); } // 必须提供 - static TypeId type_id() { - return TypeId::get(); - } // 必须提供 + static TypeId type_id() { return TypeId::get(); } // 必须提供 template // 必须提供 static bool classof(T val) { @@ -49,27 +40,12 @@ class Float32TypeBeta : public ir::Type { } template // 必须提供 - static Float32TypeBeta create(IrContext *ctx, Args... args) { - return ir::TypeUniquer::template get(ctx, args...); + static Float32Type create(IrContext *ctx, Args... args) { + return ir::TypeUniquer::template get(ctx, args...); } // 手动提供的接口 - static Float32TypeBeta get(ir::IrContext *context); -}; - -struct IntegerTypeStorage; -class IntegerType - : public ir::Type::TypeBase { - public: - using Base::Base; - - /// Integer representation maximal bitwidth. - /// Note: This is aligned with the maximum width of llvm::IntegerType. - static constexpr unsigned kMaxWidth = (1 << 24) - 1; - - static IntegerType get(ir::IrContext *context, - unsigned width, - unsigned signedness = 0); + static Float32Type get(ir::IrContext *context); }; struct IntegerTypeStorage : public TypeStorage { @@ -101,4 +77,36 @@ struct IntegerTypeStorage : public TypeStorage { } }; +class IntegerType : public ir::Type { + public: + // 可以通过宏定义自动生成的(IntegerType, TypeStorage) + using Type::Type; // 必须提供 + + using ImplType = ir::IntegerTypeStorage; // 必须指定ImplType + + ImplType *impl() const { + return static_cast(this->impl_); + } // 必须提供 + + static TypeId type_id() { return TypeId::get(); } // 必须提供 + + template // 必须提供 + static bool classof(T val) { + return val.type_id() == type_id(); + } + + template // 必须提供 + static IntegerType create(IrContext *ctx, Args... args) { + return ir::TypeUniquer::template get(ctx, args...); + } + + /// Integer representation maximal bitwidth. + /// Note: This is aligned with the maximum width of llvm::IntegerType. + static constexpr unsigned kMaxWidth = (1 << 24) - 1; + + static IntegerType get(ir::IrContext *context, + unsigned width, + unsigned signedness = 0); +}; + } // namespace ir diff --git a/paddle/ir/ir_context.cc b/paddle/ir/ir_context.cc index d888ee7617d3b8..200d5616039813 100644 --- a/paddle/ir/ir_context.cc +++ b/paddle/ir/ir_context.cc @@ -35,8 +35,6 @@ class IrContextImpl { // Some built-in type. Float32Type fp32_type; IntegerType int1Ty; - - Float32TypeBeta fp32_type_beta; }; IrContext *IrContext::ir_context_ = nullptr; @@ -59,14 +57,6 @@ IrContext::IrContext() : impl_(new IrContextImpl()) { int_abstract_type); TypeUniquer::RegisterType(this); impl_->int1Ty = TypeUniquer::get(this, 1, 0); - - VLOG(4) << "==> Register Float32TypeBeta."; - AbstractType *fp32_abstract_type_beta = new AbstractType( - std::move(AbstractType::get(TypeId::get()))); - registed_abstracted_type().emplace(TypeId::get(), - fp32_abstract_type_beta); - TypeUniquer::RegisterType(this); - impl_->fp32_type_beta = TypeUniquer::get(this); } StorageUniquer &IrContext::storage_uniquer() { @@ -92,10 +82,6 @@ const AbstractType &AbstractType::lookup(TypeId type_id, IrContext *ctx) { Float32Type Float32Type::get(IrContext *ctx) { return ctx->impl().fp32_type; } -Float32TypeBeta Float32TypeBeta::get(IrContext *ctx) { - return ctx->impl().fp32_type_beta; -} - static IntegerType GetCachedIntegerType(unsigned width, unsigned signedness, IrContext *context) { @@ -114,7 +100,7 @@ IntegerType IntegerType::get(ir::IrContext *context, unsigned signedness) { if (auto cached = GetCachedIntegerType(width, signedness, context)) return cached; - return Base::get(context, width, signedness); + return IntegerType::create(context, width, signedness); } } // namespace ir diff --git a/paddle/ir/ir_context_test.cc b/paddle/ir/ir_context_test.cc index c508a49c084f1f..70a17b10ae30f8 100644 --- a/paddle/ir/ir_context_test.cc +++ b/paddle/ir/ir_context_test.cc @@ -37,20 +37,3 @@ TEST(ir_context, type) { ir::Type int1_2 = ir::IntegerType::get(ctx, 1, 0); EXPECT_EQ(int1_1 == int1_2, 1); } - -TEST(ir_context, type_beta) { - // Test creation of built-in singleton type. - ir::IrContext *ctx = ir::IrContext::Instance(); - ir::Type fp32_beta_1 = ir::Float32TypeBeta::get(ctx); - - // Test interfaces of class Type - ir::Type fp32_beta_2 = ir::Float32TypeBeta::get(ctx); - EXPECT_EQ(fp32_beta_1 == fp32_beta_2, 1); - EXPECT_EQ(fp32_beta_1 != fp32_beta_2, 0); - EXPECT_EQ(fp32_beta_1.type_id() == fp32_beta_2.type_id(), 1); - EXPECT_EQ(&fp32_beta_1.abstract_type() == - &ir::AbstractType::lookup(fp32_beta_1.type_id(), ctx), - 1); - EXPECT_EQ(ir::Float32TypeBeta::classof(fp32_beta_1), 1); - EXPECT_EQ(ir::Float32Type::classof(fp32_beta_1), 0); -} diff --git a/paddle/ir/type.h b/paddle/ir/type.h index cff21192a5fb2c..85a62332f8a1fb 100644 --- a/paddle/ir/type.h +++ b/paddle/ir/type.h @@ -25,10 +25,6 @@ namespace ir { /// class Type { public: - template - using TypeBase = - ir::StorageUserBase; - using ImplType = TypeStorage; constexpr Type() = default; diff --git a/paddle/ir/type_base.h b/paddle/ir/type_base.h deleted file mode 100644 index 6c337287f321df..00000000000000 --- a/paddle/ir/type_base.h +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved. -// -// 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. - -#pragma once - -#include "paddle/ir/storage_uniquer.h" -#include "paddle/ir/type_id.h" - -namespace ir { -/// -/// \brief A utility class, when defining a concrete type ConcreteT, you need to -/// consider its base class BaseT and the corresponding memory type StorageT. We -/// connect the three by providing a TypeBase template tool class. -/// -template -class StorageUserBase : public BaseT { - public: - using BaseT::BaseT; - - using Base = StorageUserBase; - - using ImplType = StorageT; - - static TypeId type_id() { return TypeId::get(); } - - template - static bool classof(T val) { - return val.type_id() == type_id(); - } - - template - static ConcreteT get(IrContext *ctx, Args... args) { - return UniquerT::template get(ctx, args...); - } - - /// Utility for easy access to the storage instance. - ImplType *impl() const { return static_cast(this->impl_); } -}; - -} // namespace ir diff --git a/paddle/ir/type_support.h b/paddle/ir/type_support.h index 47869a3389cf06..ca3c5d0a478b0d 100644 --- a/paddle/ir/type_support.h +++ b/paddle/ir/type_support.h @@ -16,7 +16,6 @@ #include "paddle/ir/ir_context.h" #include "paddle/ir/storage_uniquer.h" -#include "paddle/ir/type_base.h" namespace ir { /// From 7709d4307e6776c4ebf3ded456f18c456a46e23e Mon Sep 17 00:00:00 2001 From: zhangbo9674 Date: Thu, 16 Feb 2023 09:34:34 +0000 Subject: [PATCH 10/26] rename ImplType to StorageType --- paddle/ir/builtin_type.h | 12 ++++++------ paddle/ir/type.h | 11 ++++++----- paddle/ir/type_support.h | 16 ++++++++-------- 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/paddle/ir/builtin_type.h b/paddle/ir/builtin_type.h index d2086ad00a15d5..d06ac8b21494c6 100644 --- a/paddle/ir/builtin_type.h +++ b/paddle/ir/builtin_type.h @@ -26,10 +26,10 @@ class Float32Type : public ir::Type { // 可以通过宏定义自动生成的(Float32Type, TypeStorage) using Type::Type; // 必须提供 - using ImplType = ir::TypeStorage; // 必须指定ImplType + using StorageType = ir::TypeStorage; // 必须指定StorageType - ImplType *impl() const { - return static_cast(this->impl_); + StorageType *impl() const { + return static_cast(this->impl_); } // 必须提供 static TypeId type_id() { return TypeId::get(); } // 必须提供 @@ -82,10 +82,10 @@ class IntegerType : public ir::Type { // 可以通过宏定义自动生成的(IntegerType, TypeStorage) using Type::Type; // 必须提供 - using ImplType = ir::IntegerTypeStorage; // 必须指定ImplType + using StorageType = ir::IntegerTypeStorage; // 必须指定StorageType - ImplType *impl() const { - return static_cast(this->impl_); + StorageType *impl() const { + return static_cast(this->impl_); } // 必须提供 static TypeId type_id() { return TypeId::get(); } // 必须提供 diff --git a/paddle/ir/type.h b/paddle/ir/type.h index 85a62332f8a1fb..fe559bba33633b 100644 --- a/paddle/ir/type.h +++ b/paddle/ir/type.h @@ -25,11 +25,12 @@ namespace ir { /// class Type { public: - using ImplType = TypeStorage; + using StorageType = TypeStorage; constexpr Type() = default; - Type(const ImplType *impl) : impl_(const_cast(impl)) {} // NOLINT + Type(const StorageType *impl) // NOLINT + : impl_(const_cast(impl)) {} Type(const Type &other) = default; @@ -49,7 +50,7 @@ class Type { const AbstractType &abstract_type() { return impl_->abstract_type(); } - ImplType *impl() const { return impl_; } + StorageType *impl() const { return impl_; } /// /// \brief Enable hashing Type. @@ -57,7 +58,7 @@ class Type { friend struct std::hash; protected: - ImplType *impl_{nullptr}; + StorageType *impl_{nullptr}; }; } // namespace ir @@ -69,7 +70,7 @@ namespace std { template <> struct hash { std::size_t operator()(const ir::Type &obj) const { - return std::hash()(obj.impl_); + return std::hash()(obj.impl_); } }; } // namespace std diff --git a/paddle/ir/type_support.h b/paddle/ir/type_support.h index ca3c5d0a478b0d..80fedb827a4201 100644 --- a/paddle/ir/type_support.h +++ b/paddle/ir/type_support.h @@ -142,9 +142,9 @@ struct TypeUniquer { /// template static std:: - enable_if_t::value, T> + enable_if_t::value, T> GetWithTypeId(IrContext *ctx, TypeId type_id, Args &&...args) { - return ctx->storage_uniquer().get( + return ctx->storage_uniquer().get( [&, type_id](TypeStorage *storage) { storage->initialize(AbstractType::lookup(type_id, ctx)); }, @@ -162,9 +162,9 @@ struct TypeUniquer { /// template static std:: - enable_if_t::value, T> + enable_if_t::value, T> GetWithTypeId(IrContext *ctx, TypeId type_id) { - return ctx->storage_uniquer().get(type_id); + return ctx->storage_uniquer().get(type_id); } /// @@ -185,10 +185,10 @@ struct TypeUniquer { /// template static std::enable_if_t< - !std::is_same::value> + !std::is_same::value> RegisterType(IrContext *ctx, TypeId type_id) { - ctx->storage_uniquer().RegisterParametricStorageType( - type_id); + ctx->storage_uniquer() + .RegisterParametricStorageType(type_id); } /// @@ -199,7 +199,7 @@ struct TypeUniquer { /// template static std::enable_if_t< - std::is_same::value> + std::is_same::value> RegisterType(IrContext *ctx, TypeId type_id) { ctx->storage_uniquer().RegisterSingletonStorageType( type_id, [&ctx, type_id](TypeStorage *storage) { From afd9c26748dcafa8657f1628ee4c4b604873569d Mon Sep 17 00:00:00 2001 From: zhangbo9674 Date: Thu, 16 Feb 2023 09:52:13 +0000 Subject: [PATCH 11/26] rename ImplType to StorageType --- paddle/ir/builtin_type.h | 8 ++++---- paddle/ir/type.h | 22 +++++++++++----------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/paddle/ir/builtin_type.h b/paddle/ir/builtin_type.h index d06ac8b21494c6..292b2a0ee57cab 100644 --- a/paddle/ir/builtin_type.h +++ b/paddle/ir/builtin_type.h @@ -28,8 +28,8 @@ class Float32Type : public ir::Type { using StorageType = ir::TypeStorage; // 必须指定StorageType - StorageType *impl() const { - return static_cast(this->impl_); + StorageType *storage() const { + return static_cast(this->storage_); } // 必须提供 static TypeId type_id() { return TypeId::get(); } // 必须提供 @@ -84,8 +84,8 @@ class IntegerType : public ir::Type { using StorageType = ir::IntegerTypeStorage; // 必须指定StorageType - StorageType *impl() const { - return static_cast(this->impl_); + StorageType *storage() const { + return static_cast(this->storage_); } // 必须提供 static TypeId type_id() { return TypeId::get(); } // 必须提供 diff --git a/paddle/ir/type.h b/paddle/ir/type.h index fe559bba33633b..8586cf8e46ca9f 100644 --- a/paddle/ir/type.h +++ b/paddle/ir/type.h @@ -29,8 +29,8 @@ class Type { constexpr Type() = default; - Type(const StorageType *impl) // NOLINT - : impl_(const_cast(impl)) {} + Type(const StorageType *storage) // NOLINT + : storage_(const_cast(storage)) {} Type(const Type &other) = default; @@ -39,18 +39,18 @@ class Type { /// /// \brief Comparison operations. /// - bool operator==(Type other) const { return impl_ == other.impl_; } - bool operator!=(Type other) const { return impl_ != other.impl_; } + bool operator==(Type other) const { return storage_ == other.storage_; } + bool operator!=(Type other) const { return storage_ != other.storage_; } - explicit operator bool() const { return impl_; } + explicit operator bool() const { return storage_; } - bool operator!() const { return impl_ == nullptr; } + bool operator!() const { return storage_ == nullptr; } - TypeId type_id() { return impl_->abstract_type().type_id(); } + TypeId type_id() { return storage_->abstract_type().type_id(); } - const AbstractType &abstract_type() { return impl_->abstract_type(); } + const AbstractType &abstract_type() { return storage_->abstract_type(); } - StorageType *impl() const { return impl_; } + StorageType *storage() const { return storage_; } /// /// \brief Enable hashing Type. @@ -58,7 +58,7 @@ class Type { friend struct std::hash; protected: - StorageType *impl_{nullptr}; + StorageType *storage_{nullptr}; }; } // namespace ir @@ -70,7 +70,7 @@ namespace std { template <> struct hash { std::size_t operator()(const ir::Type &obj) const { - return std::hash()(obj.impl_); + return std::hash()(obj.storage_); } }; } // namespace std From 5697c4ddb489cd6b950679fd821946bef23f5a9f Mon Sep 17 00:00:00 2001 From: zhangbo9674 Date: Thu, 16 Feb 2023 11:38:19 +0000 Subject: [PATCH 12/26] add macros util for register type --- paddle/ir/builtin_type.h | 64 ++++++++++++---------------------------- 1 file changed, 19 insertions(+), 45 deletions(-) diff --git a/paddle/ir/builtin_type.h b/paddle/ir/builtin_type.h index 292b2a0ee57cab..c343e43947e6fb 100644 --- a/paddle/ir/builtin_type.h +++ b/paddle/ir/builtin_type.h @@ -17,34 +17,31 @@ #include "paddle/ir/type.h" namespace ir { + +#define REGISTER_TYPE_UTILS(concrete_type, storage_type) \ + using Type::Type; \ + using StorageType = storage_type; \ + StorageType *storage() const { \ + return static_cast(this->storage_); \ + } \ + static ir::TypeId type_id() { return ir::TypeId::get(); } \ + template \ + static bool classof(T val) { \ + return val.type_id() == type_id(); \ + } \ + template \ + static concrete_type create(IrContext *ctx, Args... args) { \ + return ir::TypeUniquer::template get(ctx, args...); \ + } + /// /// \brief Interfaces for user-created built-in types. For example: /// Type fp32 = Float32Type::get(ctx); /// class Float32Type : public ir::Type { public: - // 可以通过宏定义自动生成的(Float32Type, TypeStorage) - using Type::Type; // 必须提供 - - using StorageType = ir::TypeStorage; // 必须指定StorageType - - StorageType *storage() const { - return static_cast(this->storage_); - } // 必须提供 - - static TypeId type_id() { return TypeId::get(); } // 必须提供 - - template // 必须提供 - static bool classof(T val) { - return val.type_id() == type_id(); - } - - template // 必须提供 - static Float32Type create(IrContext *ctx, Args... args) { - return ir::TypeUniquer::template get(ctx, args...); - } + REGISTER_TYPE_UTILS(Float32Type, ir::TypeStorage); - // 手动提供的接口 static Float32Type get(ir::IrContext *context); }; @@ -79,30 +76,7 @@ struct IntegerTypeStorage : public TypeStorage { class IntegerType : public ir::Type { public: - // 可以通过宏定义自动生成的(IntegerType, TypeStorage) - using Type::Type; // 必须提供 - - using StorageType = ir::IntegerTypeStorage; // 必须指定StorageType - - StorageType *storage() const { - return static_cast(this->storage_); - } // 必须提供 - - static TypeId type_id() { return TypeId::get(); } // 必须提供 - - template // 必须提供 - static bool classof(T val) { - return val.type_id() == type_id(); - } - - template // 必须提供 - static IntegerType create(IrContext *ctx, Args... args) { - return ir::TypeUniquer::template get(ctx, args...); - } - - /// Integer representation maximal bitwidth. - /// Note: This is aligned with the maximum width of llvm::IntegerType. - static constexpr unsigned kMaxWidth = (1 << 24) - 1; + REGISTER_TYPE_UTILS(IntegerType, ir::IntegerTypeStorage); static IntegerType get(ir::IrContext *context, unsigned width, From 9df086813add5c69cc808ebe9621cfa4d32c34ed Mon Sep 17 00:00:00 2001 From: zhangbo9674 Date: Thu, 16 Feb 2023 11:47:04 +0000 Subject: [PATCH 13/26] add macros util for register type --- paddle/ir/builtin_type.h | 18 +----------------- paddle/ir/type_utils.h | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 17 deletions(-) create mode 100644 paddle/ir/type_utils.h diff --git a/paddle/ir/builtin_type.h b/paddle/ir/builtin_type.h index c343e43947e6fb..b11164709d3ff7 100644 --- a/paddle/ir/builtin_type.h +++ b/paddle/ir/builtin_type.h @@ -15,25 +15,9 @@ #pragma once #include "paddle/ir/type.h" +#include "paddle/ir/type_utils.h" namespace ir { - -#define REGISTER_TYPE_UTILS(concrete_type, storage_type) \ - using Type::Type; \ - using StorageType = storage_type; \ - StorageType *storage() const { \ - return static_cast(this->storage_); \ - } \ - static ir::TypeId type_id() { return ir::TypeId::get(); } \ - template \ - static bool classof(T val) { \ - return val.type_id() == type_id(); \ - } \ - template \ - static concrete_type create(IrContext *ctx, Args... args) { \ - return ir::TypeUniquer::template get(ctx, args...); \ - } - /// /// \brief Interfaces for user-created built-in types. For example: /// Type fp32 = Float32Type::get(ctx); diff --git a/paddle/ir/type_utils.h b/paddle/ir/type_utils.h new file mode 100644 index 00000000000000..51bf774cc05dbe --- /dev/null +++ b/paddle/ir/type_utils.h @@ -0,0 +1,38 @@ +// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved. +// +// 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. + +#pragma once + +namespace ir { +/// +/// \brief This macro definition is used to add some necessary functions to the +/// custom Type class. +/// +#define REGISTER_TYPE_UTILS(concrete_type, storage_type) \ + using Type::Type; \ + using StorageType = storage_type; \ + StorageType *storage() const { \ + return static_cast(this->storage_); \ + } \ + static ir::TypeId type_id() { return ir::TypeId::get(); } \ + template \ + static bool classof(T val) { \ + return val.type_id() == type_id(); \ + } \ + template \ + static concrete_type create(IrContext *ctx, Args... args) { \ + return ir::TypeUniquer::template get(ctx, args...); \ + } + +} // namespace ir From 571cec174bbe394c9362652785e2561cf625d8eb Mon Sep 17 00:00:00 2001 From: zhangbo9674 Date: Thu, 16 Feb 2023 13:03:52 +0000 Subject: [PATCH 14/26] refine name --- paddle/ir/CMakeLists.txt | 4 +- paddle/ir/builtin_type.h | 1 - paddle/ir/ir_context.cc | 2 +- paddle/ir/ir_context_test.cc | 39 ------------------- paddle/ir/type.h | 2 +- paddle/ir/{type_support.h => type_base.h} | 21 ++++++++++ .../ir/{type_support_test.cc => type_test.cc} | 33 +++++++++++++--- paddle/ir/type_utils.h | 38 ------------------ 8 files changed, 51 insertions(+), 89 deletions(-) delete mode 100644 paddle/ir/ir_context_test.cc rename paddle/ir/{type_support.h => type_base.h} (85%) rename paddle/ir/{type_support_test.cc => type_test.cc} (62%) delete mode 100644 paddle/ir/type_utils.h diff --git a/paddle/ir/CMakeLists.txt b/paddle/ir/CMakeLists.txt index 91dd528e781f7b..00abf8536b33c9 100644 --- a/paddle/ir/CMakeLists.txt +++ b/paddle/ir/CMakeLists.txt @@ -12,6 +12,4 @@ cc_library( SRCS ir_context.cc DEPS storage_uniquer) -cc_test_old(type_support_test SRCS type_support_test.cc DEPS gtest) - -cc_test_old(ir_context_test SRCS ir_context_test.cc DEPS ir_context gtest) +cc_test_old(type_test SRCS type_test.cc DEPS ir_context gtest) diff --git a/paddle/ir/builtin_type.h b/paddle/ir/builtin_type.h index b11164709d3ff7..6d3fb66d006723 100644 --- a/paddle/ir/builtin_type.h +++ b/paddle/ir/builtin_type.h @@ -15,7 +15,6 @@ #pragma once #include "paddle/ir/type.h" -#include "paddle/ir/type_utils.h" namespace ir { /// diff --git a/paddle/ir/ir_context.cc b/paddle/ir/ir_context.cc index 200d5616039813..5b8f2e227d5850 100644 --- a/paddle/ir/ir_context.cc +++ b/paddle/ir/ir_context.cc @@ -16,7 +16,7 @@ #include "paddle/ir/builtin_type.h" #include "paddle/ir/ir_context.h" -#include "paddle/ir/type_support.h" +#include "paddle/ir/type_base.h" namespace ir { // The implementation class of the IrContext class diff --git a/paddle/ir/ir_context_test.cc b/paddle/ir/ir_context_test.cc deleted file mode 100644 index 70a17b10ae30f8..00000000000000 --- a/paddle/ir/ir_context_test.cc +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved. -// -// 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 "paddle/ir/builtin_type.h" -#include "paddle/ir/ir_context.h" -#include "paddle/ir/type_support.h" - -TEST(ir_context, type) { - // Test creation of built-in singleton type. - ir::IrContext *ctx = ir::IrContext::Instance(); - ir::Type fp32_1 = ir::Float32Type::get(ctx); - - // Test interfaces of class Type - ir::Type fp32_2 = ir::Float32Type::get(ctx); - EXPECT_EQ(fp32_1 == fp32_2, 1); - EXPECT_EQ(fp32_1 != fp32_2, 0); - EXPECT_EQ(fp32_1.type_id() == fp32_2.type_id(), 1); - EXPECT_EQ(&fp32_1.abstract_type() == - &ir::AbstractType::lookup(fp32_1.type_id(), ctx), - 1); - EXPECT_EQ(ir::Float32Type::classof(fp32_1), 1); - - ir::Type int1_1 = ir::IntegerType::get(ctx, 1, 0); - ir::Type int1_2 = ir::IntegerType::get(ctx, 1, 0); - EXPECT_EQ(int1_1 == int1_2, 1); -} diff --git a/paddle/ir/type.h b/paddle/ir/type.h index 8586cf8e46ca9f..c4c5663dda9db4 100644 --- a/paddle/ir/type.h +++ b/paddle/ir/type.h @@ -14,7 +14,7 @@ #pragma once -#include "paddle/ir/type_support.h" +#include "paddle/ir/type_base.h" namespace ir { /// diff --git a/paddle/ir/type_support.h b/paddle/ir/type_base.h similarity index 85% rename from paddle/ir/type_support.h rename to paddle/ir/type_base.h index 80fedb827a4201..b0981e9eb3cdd5 100644 --- a/paddle/ir/type_support.h +++ b/paddle/ir/type_base.h @@ -16,6 +16,7 @@ #include "paddle/ir/ir_context.h" #include "paddle/ir/storage_uniquer.h" +#include "paddle/ir/type_id.h" namespace ir { /// @@ -208,4 +209,24 @@ struct TypeUniquer { } }; +/// +/// \brief This macro definition is used to add some necessary functions to the +/// custom Type class. +/// +#define REGISTER_TYPE_UTILS(concrete_type, storage_type) \ + using Type::Type; \ + using StorageType = storage_type; \ + StorageType *storage() const { \ + return static_cast(this->storage_); \ + } \ + static ir::TypeId type_id() { return ir::TypeId::get(); } \ + template \ + static bool classof(T val) { \ + return val.type_id() == type_id(); \ + } \ + template \ + static concrete_type create(IrContext *ctx, Args... args) { \ + return ir::TypeUniquer::template get(ctx, args...); \ + } + } // namespace ir diff --git a/paddle/ir/type_support_test.cc b/paddle/ir/type_test.cc similarity index 62% rename from paddle/ir/type_support_test.cc rename to paddle/ir/type_test.cc index dc4c0ac54b0914..88155bf4601f2d 100644 --- a/paddle/ir/type_support_test.cc +++ b/paddle/ir/type_test.cc @@ -15,10 +15,11 @@ #include #include -#include "paddle/ir/type_id.h" -#include "paddle/ir/type_support.h" +#include "paddle/ir/builtin_type.h" +#include "paddle/ir/ir_context.h" +#include "paddle/ir/type_base.h" -TEST(type_support, type_id) { +TEST(type_test, type_id) { class TypeA {}; class TypeB {}; @@ -30,7 +31,7 @@ TEST(type_support, type_id) { EXPECT_NE(a_id, b_id); // (2) Test TypeId hash - std::unordered_map type_id_register; + std::unordered_map type_id_register; type_id_register.emplace(a_id, &a_id); type_id_register.emplace(b_id, &b_id); for (auto kv : type_id_register) { @@ -38,7 +39,7 @@ TEST(type_support, type_id) { } } -TEST(type_support, abstract_type) { +TEST(type_test, abstract_type) { class TypeA {}; ir::TypeId a_id = ir::TypeId::get(); @@ -47,7 +48,7 @@ TEST(type_support, abstract_type) { EXPECT_EQ(abstract_type_a.type_id(), a_id); } -TEST(type_support, type_storage) { +TEST(type_test, type_storage) { class TypeA {}; ir::TypeId a_id = ir::TypeId::get(); @@ -57,3 +58,23 @@ TEST(type_support, type_storage) { EXPECT_EQ(storage_a.abstract_type().type_id(), abstract_type_a.type_id()); } + +TEST(type_test, type) { + // Test creation of built-in singleton type. + ir::IrContext *ctx = ir::IrContext::Instance(); + ir::Type fp32_1 = ir::Float32Type::get(ctx); + + // Test interfaces of class Type + ir::Type fp32_2 = ir::Float32Type::get(ctx); + EXPECT_EQ(fp32_1 == fp32_2, 1); + EXPECT_EQ(fp32_1 != fp32_2, 0); + EXPECT_EQ(fp32_1.type_id() == fp32_2.type_id(), 1); + EXPECT_EQ(&fp32_1.abstract_type() == + &ir::AbstractType::lookup(fp32_1.type_id(), ctx), + 1); + EXPECT_EQ(ir::Float32Type::classof(fp32_1), 1); + + ir::Type int1_1 = ir::IntegerType::get(ctx, 1, 0); + ir::Type int1_2 = ir::IntegerType::get(ctx, 1, 0); + EXPECT_EQ(int1_1 == int1_2, 1); +} diff --git a/paddle/ir/type_utils.h b/paddle/ir/type_utils.h deleted file mode 100644 index 51bf774cc05dbe..00000000000000 --- a/paddle/ir/type_utils.h +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved. -// -// 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. - -#pragma once - -namespace ir { -/// -/// \brief This macro definition is used to add some necessary functions to the -/// custom Type class. -/// -#define REGISTER_TYPE_UTILS(concrete_type, storage_type) \ - using Type::Type; \ - using StorageType = storage_type; \ - StorageType *storage() const { \ - return static_cast(this->storage_); \ - } \ - static ir::TypeId type_id() { return ir::TypeId::get(); } \ - template \ - static bool classof(T val) { \ - return val.type_id() == type_id(); \ - } \ - template \ - static concrete_type create(IrContext *ctx, Args... args) { \ - return ir::TypeUniquer::template get(ctx, args...); \ - } - -} // namespace ir From 41268aaa3809c8f0e2474cfd888750c7e9353a20 Mon Sep 17 00:00:00 2001 From: zhangbo9674 Date: Fri, 17 Feb 2023 03:56:49 +0000 Subject: [PATCH 15/26] refine name --- paddle/ir/CMakeLists.txt | 4 +- paddle/ir/ir_context.cc | 16 ++-- paddle/ir/ir_context.h | 10 +-- ...{storage_uniquer.cc => storage_manager.cc} | 87 ++++++++++--------- .../{storage_uniquer.h => storage_manager.h} | 68 +++++++-------- paddle/ir/type_base.h | 35 ++++---- paddle/ir/type_test.cc | 2 +- 7 files changed, 111 insertions(+), 111 deletions(-) rename paddle/ir/{storage_uniquer.cc => storage_manager.cc} (51%) rename paddle/ir/{storage_uniquer.h => storage_manager.h} (64%) diff --git a/paddle/ir/CMakeLists.txt b/paddle/ir/CMakeLists.txt index 00abf8536b33c9..ba46972e51913a 100644 --- a/paddle/ir/CMakeLists.txt +++ b/paddle/ir/CMakeLists.txt @@ -5,11 +5,11 @@ endif() set(NEWIR_SOURCE_DIR "${PADDLE_SOURCE_DIR}/paddle/ir") set(NEWIR_BINARY_DIR "${PADDLE_BINARY_DIR}/paddle/ir") -cc_library(storage_uniquer SRCS storage_uniquer.cc) +cc_library(storage_manager SRCS storage_manager.cc) cc_library( ir_context SRCS ir_context.cc - DEPS storage_uniquer) + DEPS storage_manager) cc_test_old(type_test SRCS type_test.cc DEPS ir_context gtest) diff --git a/paddle/ir/ir_context.cc b/paddle/ir/ir_context.cc index 5b8f2e227d5850..0d079e415a7376 100644 --- a/paddle/ir/ir_context.cc +++ b/paddle/ir/ir_context.cc @@ -30,7 +30,7 @@ class IrContextImpl { std::unordered_map registed_abstract_types_; // TypeStorage uniquer and cache instances. - StorageUniquer registed_storage_uniquer_; + StorageManager registed_storage_manager_; // Some built-in type. Float32Type fp32_type; @@ -40,27 +40,25 @@ class IrContextImpl { IrContext *IrContext::ir_context_ = nullptr; IrContext::IrContext() : impl_(new IrContextImpl()) { - VLOG(4) << "==> Constructor for IrContext."; - VLOG(4) << "==> Register Float32Type."; AbstractType *fp32_abstract_type = new AbstractType( std::move(AbstractType::get(TypeId::get()))); registed_abstracted_type().emplace(TypeId::get(), fp32_abstract_type); - TypeUniquer::RegisterType(this); - impl_->fp32_type = TypeUniquer::get(this); + TypeManager::RegisterType(this); + impl_->fp32_type = TypeManager::get(this); VLOG(4) << "==> Register IntegerType."; AbstractType *int_abstract_type = new AbstractType( std::move(AbstractType::get(TypeId::get()))); registed_abstracted_type().emplace(TypeId::get(), int_abstract_type); - TypeUniquer::RegisterType(this); - impl_->int1Ty = TypeUniquer::get(this, 1, 0); + TypeManager::RegisterType(this); + impl_->int1Ty = TypeManager::get(this, 1, 0); } -StorageUniquer &IrContext::storage_uniquer() { - return impl().registed_storage_uniquer_; +StorageManager &IrContext::storage_manager() { + return impl().registed_storage_manager_; } std::unordered_map diff --git a/paddle/ir/ir_context.h b/paddle/ir/ir_context.h index 3d17897be704e4..803399a4839ab5 100644 --- a/paddle/ir/ir_context.h +++ b/paddle/ir/ir_context.h @@ -20,20 +20,20 @@ namespace ir { class IrContextImpl; -class StorageUniquer; +class StorageManager; class AbstractType; class TypeId; /// -/// \brief IrContext is a global singleton class used to store and manage Type -/// and its related data structures. +/// \brief IrContext is a global parameterless class used to store and manage +/// Type and its related data structures. /// class IrContext { public: /// /// \brief Initializes a new instance of IrContext. /// - /// \return Global singleton for IrContext. + /// \return Global parameterless for IrContext. /// static IrContext *Instance() { VLOG(4) << "=> Instance called with context (ir_context_ == " << ir_context_ @@ -62,7 +62,7 @@ class IrContext { /// \return The storage uniquer used for constructing TypeStorage /// instances. /// - StorageUniquer &storage_uniquer(); + StorageManager &storage_manager(); /// /// \brief Returns the storage uniquer used for constructing TypeStorage diff --git a/paddle/ir/storage_uniquer.cc b/paddle/ir/storage_manager.cc similarity index 51% rename from paddle/ir/storage_uniquer.cc rename to paddle/ir/storage_manager.cc index 06cc4daa55fd27..580ff4177f0677 100644 --- a/paddle/ir/storage_uniquer.cc +++ b/paddle/ir/storage_manager.cc @@ -15,18 +15,18 @@ #include #include -#include "paddle/ir/storage_uniquer.h" +#include "paddle/ir/storage_manager.h" namespace ir { // This is a structure for creating, caching, and looking up Storage of // parameteric types. -struct ParametricStorageUniquer { - using BaseStorage = StorageUniquer::BaseStorage; +struct ParametricStorageManager { + using StorageBase = StorageManager::StorageBase; - explicit ParametricStorageUniquer(std::function del_func) + explicit ParametricStorageManager(std::function del_func) : del_func_(del_func) {} - ~ParametricStorageUniquer() { + ~ParametricStorageManager() { for (const auto &instance : parametric_instances_) { del_func_(instance.second); } @@ -34,11 +34,11 @@ struct ParametricStorageUniquer { // Get the storage of parametric type, if not in the cache, create and // insert the cache. - BaseStorage *GetOrCreateParametricStorage( + StorageBase *GetOrCreateParametricStorage( std::size_t hash_value, - std::function is_equal_func, - std::function ctor_func) { - BaseStorage *storage = nullptr; + std::function is_equal_func, + std::function ctor_func) { + StorageBase *storage = nullptr; if (parametric_instances_.count(hash_value) == 0) { storage = ctor_func(); parametric_instances_.emplace(hash_value, storage); @@ -59,78 +59,79 @@ struct ParametricStorageUniquer { private: // In order to prevent hash conflicts, the unordered_multimap data structure // is used for storage. - std::unordered_multimap parametric_instances_; + std::unordered_multimap parametric_instances_; - std::function del_func_; + std::function del_func_; }; -/// The implementation class of the StorageUniquer. -struct StorageUniquerImpl { - using BaseStorage = StorageUniquer::BaseStorage; +/// The implementation class of the StorageManager. +struct StorageManagerImpl { + using StorageBase = StorageManager::StorageBase; // Get the storage of parametric type, if not in the cache, create and // insert the cache. - BaseStorage *GetOrCreateParametricStorage( + StorageBase *GetOrCreateParametricStorage( TypeId type_id, std::size_t hash_value, - std::function is_equal_func, - std::function ctor_func) { + std::function is_equal_func, + std::function ctor_func) { if (parametric_uniquers_.find(type_id) == parametric_uniquers_.end()) throw("The input data pointer is null."); - ParametricStorageUniquer ¶metric_storage = + ParametricStorageManager ¶metric_storage = *parametric_uniquers_[type_id]; return parametric_storage.GetOrCreateParametricStorage( hash_value, is_equal_func, ctor_func); } - // Get the storage of singleton type. - BaseStorage *GetSingletonStorage(TypeId type_id) { - VLOG(4) << "==> StorageUniquerImpl::GetSingletonStorage()."; - if (singleton_instances_.find(type_id) == singleton_instances_.end()) + // Get the storage of parameterless type. + StorageBase *GetParameterlessStorage(TypeId type_id) { + VLOG(4) << "==> StorageManagerImpl::GetParameterlessStorage()."; + if (parameterless_instances_.find(type_id) == + parameterless_instances_.end()) throw("TypeId not found in IrContext."); - BaseStorage *singleton_instance = singleton_instances_[type_id]; - return singleton_instance; + StorageBase *parameterless_instance = parameterless_instances_[type_id]; + return parameterless_instance; } // This map is a mapping between type id and parameteric type storage. - std::unordered_map> + std::unordered_map> parametric_uniquers_; - // This map is a mapping between type id and singleton type storage. - std::unordered_map singleton_instances_; + // This map is a mapping between type id and parameterless type storage. + std::unordered_map parameterless_instances_; }; -StorageUniquer::StorageUniquer() : impl_(new StorageUniquerImpl()) {} +StorageManager::StorageManager() : impl_(new StorageManagerImpl()) {} -StorageUniquer::~StorageUniquer() = default; +StorageManager::~StorageManager() = default; -StorageUniquer::BaseStorage *StorageUniquer::GetParametricStorageTypeImpl( +StorageManager::StorageBase *StorageManager::GetParametricStorageTypeImpl( TypeId type_id, std::size_t hash_value, - std::function is_equal_func, - std::function ctor_func) { + std::function is_equal_func, + std::function ctor_func) { return impl_->GetOrCreateParametricStorage( type_id, hash_value, is_equal_func, ctor_func); } -StorageUniquer::BaseStorage *StorageUniquer::GetSingletonStorageTypeImpl( +StorageManager::StorageBase *StorageManager::GetParameterlessStorageTypeImpl( TypeId type_id) { - return impl_->GetSingletonStorage(type_id); + return impl_->GetParameterlessStorage(type_id); } -void StorageUniquer::RegisterParametricStorageTypeImpl( - TypeId type_id, std::function del_func) { +void StorageManager::RegisterParametricStorageTypeImpl( + TypeId type_id, std::function del_func) { impl_->parametric_uniquers_.emplace( - type_id, std::make_unique(del_func)); + type_id, std::make_unique(del_func)); } -void StorageUniquer::RegisterSingletonStorageTypeImpl( - TypeId type_id, std::function ctor_func) { - VLOG(4) << "==> StorageUniquer::RegisterSingletonStorageTypeImpl()"; - if (impl_->singleton_instances_.find(type_id) != - impl_->singleton_instances_.end()) +void StorageManager::RegisterParameterlessStorageTypeImpl( + TypeId type_id, std::function ctor_func) { + VLOG(4) << "==> StorageManager::RegisterParameterlessStorageTypeImpl()"; + if (impl_->parameterless_instances_.find(type_id) != + impl_->parameterless_instances_.end()) throw("storage class already registered"); - impl_->singleton_instances_.emplace(type_id, ctor_func()); + impl_->parameterless_instances_.emplace(type_id, ctor_func()); } } // namespace ir diff --git a/paddle/ir/storage_uniquer.h b/paddle/ir/storage_manager.h similarity index 64% rename from paddle/ir/storage_uniquer.h rename to paddle/ir/storage_manager.h index 297b5cabfacf2c..ac57caac3a0f62 100644 --- a/paddle/ir/storage_uniquer.h +++ b/paddle/ir/storage_manager.h @@ -22,36 +22,36 @@ namespace ir { /// -/// \brief The implementation of the class StorageUniquer. +/// \brief The implementation of the class StorageManager. /// -struct StorageUniquerImpl; +struct StorageManagerImpl; /// /// \brief A utility class for getting or creating Storage class instances. -/// Storage class must be a derived class of StorageUniquer::BaseStorage. +/// Storage class must be a derived class of StorageManager::StorageBase. /// There are two types of Storage class: -/// One is a singleton type, which can directly obtain an instance through the -/// get method; The other is a parameteric type, which needs to comply with the -/// following conditions: (1) Need to define a type alias called ParamKey, it -/// serves as the unique identifier for the Storage class; (2) Need to provide a -/// hash method on the ParamKey for storage and access; (3) Need to provide -/// method 'bool operator==(const ParamKey &) const', used to compare Storage -/// instance and ParamKey instance. +/// One is a parameterless type, which can directly obtain an instance through +/// the get method; The other is a parameteric type, which needs to comply with +/// the following conditions: (1) Need to define a type alias called ParamKey, +/// it serves as the unique identifier for the Storage class; (2) Need to +/// provide a hash method on the ParamKey for storage and access; (3) Need to +/// provide method 'bool operator==(const ParamKey &) const', used to compare +/// Storage instance and ParamKey instance. /// -class StorageUniquer { +class StorageManager { public: /// /// \brief This class is the base class of all storage classes, /// and any type of storage needs to inherit from this class. /// - class BaseStorage { + class StorageBase { protected: - BaseStorage() = default; + StorageBase() = default; }; - StorageUniquer(); + StorageManager(); - ~StorageUniquer(); + ~StorageManager(); /// /// \brief Get a unique storage instance of parametric Type. @@ -67,7 +67,7 @@ class StorageUniquer { Args &&...args) { auto derived_param_key = GetParamKey(std::forward(args)...); std::size_t hash_value = Storage::HashValue(derived_param_key); - auto is_equal_func = [&derived_param_key](const BaseStorage *existing) { + auto is_equal_func = [&derived_param_key](const StorageBase *existing) { return static_cast(*existing) == derived_param_key; }; auto ctor_func = [&]() { @@ -80,14 +80,14 @@ class StorageUniquer { } /// - /// \brief Get a unique storage instance of singleton Type. + /// \brief Get a unique storage instance of parameterless Type. /// /// \param type_id The type id of the AbstractType. /// \return A uniqued instance of Storage. /// template Storage *get(TypeId type_id) { - return static_cast(GetSingletonStorageTypeImpl(type_id)); + return static_cast(GetParameterlessStorageTypeImpl(type_id)); } /// @@ -101,53 +101,53 @@ class StorageUniquer { return RegisterParametricStorageTypeImpl(type_id, nullptr); } else { return RegisterParametricStorageTypeImpl( - type_id, [](BaseStorage *storage) { + type_id, [](StorageBase *storage) { static_cast(storage)->~Storage(); }); } } /// - /// \brief Register a new singleton storage class. + /// \brief Register a new parameterless storage class. /// /// \param type_id The type id of the AbstractType. /// \param init_func Used to initialize a newly inserted storage instance. /// template - void RegisterSingletonStorageType(TypeId type_id, - std::function init_func) { - VLOG(4) << "==> StorageUniquer::RegisterSingletonStorageType()"; + void RegisterParameterlessStorageType( + TypeId type_id, std::function init_func) { + VLOG(4) << "==> StorageManager::RegisterParameterlessStorageType()"; auto ctor_func = [&]() { auto *storage = new Storage(); if (init_func) init_func(storage); return storage; }; - RegisterSingletonStorageTypeImpl(type_id, ctor_func); + RegisterParameterlessStorageTypeImpl(type_id, ctor_func); } private: - BaseStorage *GetParametricStorageTypeImpl( + StorageBase *GetParametricStorageTypeImpl( TypeId type_id, std::size_t hash_value, - std::function is_equal_func, - std::function ctor_func); + std::function is_equal_func, + std::function ctor_func); - BaseStorage *GetSingletonStorageTypeImpl(TypeId type_id); + StorageBase *GetParameterlessStorageTypeImpl(TypeId type_id); void RegisterParametricStorageTypeImpl( - TypeId type_id, std::function del_func); + TypeId type_id, std::function del_func); - void RegisterSingletonStorageTypeImpl( - TypeId type_id, std::function ctor_func); + void RegisterParameterlessStorageTypeImpl( + TypeId type_id, std::function ctor_func); template static typename ImplTy::ParamKey GetParamKey(Args &&...args) { return typename ImplTy::ParamKey(args...); } - /// \brief StorageUniquerImpl is the implementation class of the - /// StorageUniquer. - std::unique_ptr impl_; + /// \brief StorageManagerImpl is the implementation class of the + /// StorageManager. + std::unique_ptr impl_; }; } // namespace ir diff --git a/paddle/ir/type_base.h b/paddle/ir/type_base.h index b0981e9eb3cdd5..cd9353c7f62ebc 100644 --- a/paddle/ir/type_base.h +++ b/paddle/ir/type_base.h @@ -15,15 +15,15 @@ #pragma once #include "paddle/ir/ir_context.h" -#include "paddle/ir/storage_uniquer.h" +#include "paddle/ir/storage_manager.h" #include "paddle/ir/type_id.h" namespace ir { /// /// \brief Abstract the properties and behaviors common to all Type classes into /// an AbstractType class. There are two types in Type system: -/// on-parameter/singleton type and parameter-type. The common attributes of all -/// types is TypeId (and possibly others). Therefore, construct a class with +/// on-parameter/parameterless type and parameter-type. The common attributes of +/// all types is TypeId (and possibly others). Therefore, construct a class with /// TypeId as its member. /// class AbstractType { @@ -64,7 +64,7 @@ class AbstractType { TypeId type_id_; }; -struct TypeUniquer; +struct TypeManager; /// /// \brief TypeStorage is used to store all information of a Type. A Type object @@ -74,9 +74,9 @@ struct TypeUniquer; /// included. So that, non-parameter type can be constructed by TypeStorage /// directly but parameter type should be constructed by Derived TypeStorage. /// -class TypeStorage : public StorageUniquer::BaseStorage { - friend StorageUniquer; - friend TypeUniquer; +class TypeStorage : public StorageManager::StorageBase { + friend StorageManager; + friend TypeManager; public: /// @@ -112,14 +112,15 @@ class TypeStorage : public StorageUniquer::BaseStorage { }; /// -/// \brief TypeUniquer is a utility class that provides interfaces for get or +/// \brief TypeManager is a utility class that provides interfaces for get or /// unique Type instances in IrContext. /// -struct TypeUniquer { +struct TypeManager { /// /// \brief Get a unique instance of Type T from IrContext. Note: For a /// parameteric_type, if not found in IrContext, it will try to create a new - /// instance and register it to IrContext; for a singleton_type, only search. + /// instance and register it to IrContext; for a parameterless type, only + /// search. /// /// \param ctx The IrContext instance. /// \param args Parameters of the wrapped function. @@ -145,7 +146,7 @@ struct TypeUniquer { static std:: enable_if_t::value, T> GetWithTypeId(IrContext *ctx, TypeId type_id, Args &&...args) { - return ctx->storage_uniquer().get( + return ctx->storage_manager().get( [&, type_id](TypeStorage *storage) { storage->initialize(AbstractType::lookup(type_id, ctx)); }, @@ -154,7 +155,7 @@ struct TypeUniquer { } /// - /// \brief Get a unique instance of singleton Type T from IrContext, only + /// \brief Get a unique instance of parameterless Type T from IrContext, only /// search. /// /// \param ctx The IrContext instance. @@ -165,7 +166,7 @@ struct TypeUniquer { static std:: enable_if_t::value, T> GetWithTypeId(IrContext *ctx, TypeId type_id) { - return ctx->storage_uniquer().get(type_id); + return ctx->storage_manager().get(type_id); } /// @@ -188,12 +189,12 @@ struct TypeUniquer { static std::enable_if_t< !std::is_same::value> RegisterType(IrContext *ctx, TypeId type_id) { - ctx->storage_uniquer() + ctx->storage_manager() .RegisterParametricStorageType(type_id); } /// - /// \brief Register a unique instance of singleton Type T to IrContext. + /// \brief Register a unique instance of parameterless Type T to IrContext. /// /// \param ctx The IrContext instance. /// \param type_id The type id of the Type T. @@ -202,7 +203,7 @@ struct TypeUniquer { static std::enable_if_t< std::is_same::value> RegisterType(IrContext *ctx, TypeId type_id) { - ctx->storage_uniquer().RegisterSingletonStorageType( + ctx->storage_manager().RegisterParameterlessStorageType( type_id, [&ctx, type_id](TypeStorage *storage) { storage->initialize(AbstractType::lookup(type_id, ctx)); }); @@ -226,7 +227,7 @@ struct TypeUniquer { } \ template \ static concrete_type create(IrContext *ctx, Args... args) { \ - return ir::TypeUniquer::template get(ctx, args...); \ + return ir::TypeManager::template get(ctx, args...); \ } } // namespace ir diff --git a/paddle/ir/type_test.cc b/paddle/ir/type_test.cc index 88155bf4601f2d..ee3a6c31f970e4 100644 --- a/paddle/ir/type_test.cc +++ b/paddle/ir/type_test.cc @@ -60,7 +60,7 @@ TEST(type_test, type_storage) { } TEST(type_test, type) { - // Test creation of built-in singleton type. + // Test creation of built-in parameterless type. ir::IrContext *ctx = ir::IrContext::Instance(); ir::Type fp32_1 = ir::Float32Type::get(ctx); From d3acb795f7a3b9fe4e053a3ca0d1d9719ab6bc0d Mon Sep 17 00:00:00 2001 From: zhangbo9674 Date: Fri, 17 Feb 2023 15:58:18 +0000 Subject: [PATCH 16/26] change storage manager --- paddle/ir/ir_context.cc | 1 + paddle/ir/storage_manager.cc | 62 ++++++++++-------------------------- paddle/ir/storage_manager.h | 12 ++++--- paddle/ir/type_test.cc | 4 +++ 4 files changed, 30 insertions(+), 49 deletions(-) diff --git a/paddle/ir/ir_context.cc b/paddle/ir/ir_context.cc index 0d079e415a7376..81078aae52bf9a 100644 --- a/paddle/ir/ir_context.cc +++ b/paddle/ir/ir_context.cc @@ -98,6 +98,7 @@ IntegerType IntegerType::get(ir::IrContext *context, unsigned signedness) { if (auto cached = GetCachedIntegerType(width, signedness, context)) return cached; + VLOG(4) << "no cache, create a new"; return IntegerType::create(context, width, signedness); } diff --git a/paddle/ir/storage_manager.cc b/paddle/ir/storage_manager.cc index 580ff4177f0677..1837d96a17be5e 100644 --- a/paddle/ir/storage_manager.cc +++ b/paddle/ir/storage_manager.cc @@ -40,16 +40,19 @@ struct ParametricStorageManager { std::function ctor_func) { StorageBase *storage = nullptr; if (parametric_instances_.count(hash_value) == 0) { + VLOG(4) << "not cache, create a new parameteric storage"; storage = ctor_func(); parametric_instances_.emplace(hash_value, storage); } else { auto pr = parametric_instances_.equal_range(hash_value); while (pr.first != pr.second) { if (is_equal_func(pr.first->second)) { + VLOG(4) << "get cache, parameteric storage"; return pr.first->second; } ++pr.first; } + VLOG(4) << "not cache, create a new parameteric storage"; storage = ctor_func(); parametric_instances_.emplace(hash_value, storage); } @@ -64,44 +67,7 @@ struct ParametricStorageManager { std::function del_func_; }; -/// The implementation class of the StorageManager. -struct StorageManagerImpl { - using StorageBase = StorageManager::StorageBase; - - // Get the storage of parametric type, if not in the cache, create and - // insert the cache. - StorageBase *GetOrCreateParametricStorage( - TypeId type_id, - std::size_t hash_value, - std::function is_equal_func, - std::function ctor_func) { - if (parametric_uniquers_.find(type_id) == parametric_uniquers_.end()) - throw("The input data pointer is null."); - ParametricStorageManager ¶metric_storage = - *parametric_uniquers_[type_id]; - return parametric_storage.GetOrCreateParametricStorage( - hash_value, is_equal_func, ctor_func); - } - - // Get the storage of parameterless type. - StorageBase *GetParameterlessStorage(TypeId type_id) { - VLOG(4) << "==> StorageManagerImpl::GetParameterlessStorage()."; - if (parameterless_instances_.find(type_id) == - parameterless_instances_.end()) - throw("TypeId not found in IrContext."); - StorageBase *parameterless_instance = parameterless_instances_[type_id]; - return parameterless_instance; - } - - // This map is a mapping between type id and parameteric type storage. - std::unordered_map> - parametric_uniquers_; - - // This map is a mapping between type id and parameterless type storage. - std::unordered_map parameterless_instances_; -}; - -StorageManager::StorageManager() : impl_(new StorageManagerImpl()) {} +StorageManager::StorageManager() {} StorageManager::~StorageManager() = default; @@ -110,28 +76,34 @@ StorageManager::StorageBase *StorageManager::GetParametricStorageTypeImpl( std::size_t hash_value, std::function is_equal_func, std::function ctor_func) { - return impl_->GetOrCreateParametricStorage( - type_id, hash_value, is_equal_func, ctor_func); + if (parametric_instance_.find(type_id) == parametric_instance_.end()) + throw("The input data pointer is null."); + ParametricStorageManager ¶metric_storage = *parametric_instance_[type_id]; + return parametric_storage.GetOrCreateParametricStorage( + hash_value, is_equal_func, ctor_func); } StorageManager::StorageBase *StorageManager::GetParameterlessStorageTypeImpl( TypeId type_id) { - return impl_->GetParameterlessStorage(type_id); + VLOG(4) << "==> StorageManagerImpl::GetParameterlessStorage()."; + if (parameterless_instances_.find(type_id) == parameterless_instances_.end()) + throw("TypeId not found in IrContext."); + StorageBase *parameterless_instance = parameterless_instances_[type_id]; + return parameterless_instance; } void StorageManager::RegisterParametricStorageTypeImpl( TypeId type_id, std::function del_func) { - impl_->parametric_uniquers_.emplace( + parametric_instance_.emplace( type_id, std::make_unique(del_func)); } void StorageManager::RegisterParameterlessStorageTypeImpl( TypeId type_id, std::function ctor_func) { VLOG(4) << "==> StorageManager::RegisterParameterlessStorageTypeImpl()"; - if (impl_->parameterless_instances_.find(type_id) != - impl_->parameterless_instances_.end()) + if (parameterless_instances_.find(type_id) != parameterless_instances_.end()) throw("storage class already registered"); - impl_->parameterless_instances_.emplace(type_id, ctor_func()); + parameterless_instances_.emplace(type_id, ctor_func()); } } // namespace ir diff --git a/paddle/ir/storage_manager.h b/paddle/ir/storage_manager.h index ac57caac3a0f62..1f2bb5a759fe6d 100644 --- a/paddle/ir/storage_manager.h +++ b/paddle/ir/storage_manager.h @@ -24,7 +24,8 @@ namespace ir { /// /// \brief The implementation of the class StorageManager. /// -struct StorageManagerImpl; +// struct StorageManagerImpl; +struct ParametricStorageManager; /// /// \brief A utility class for getting or creating Storage class instances. @@ -145,9 +146,12 @@ class StorageManager { return typename ImplTy::ParamKey(args...); } - /// \brief StorageManagerImpl is the implementation class of the - /// StorageManager. - std::unique_ptr impl_; + // This map is a mapping between type id and parameteric type storage. + std::unordered_map> + parametric_instance_; + + // This map is a mapping between type id and parameterless type storage. + std::unordered_map parameterless_instances_; }; } // namespace ir diff --git a/paddle/ir/type_test.cc b/paddle/ir/type_test.cc index ee3a6c31f970e4..4177da14c68f96 100644 --- a/paddle/ir/type_test.cc +++ b/paddle/ir/type_test.cc @@ -77,4 +77,8 @@ TEST(type_test, type) { ir::Type int1_1 = ir::IntegerType::get(ctx, 1, 0); ir::Type int1_2 = ir::IntegerType::get(ctx, 1, 0); EXPECT_EQ(int1_1 == int1_2, 1); + + ir::Type int8_1 = ir::IntegerType::get(ctx, 8, 0); + ir::Type int8_2 = ir::IntegerType::get(ctx, 8, 0); + EXPECT_EQ(int8_1 == int8_2, 1); } From 4900064a2b785ff4aab47167826bfef999698de6 Mon Sep 17 00:00:00 2001 From: zhangbo9674 Date: Mon, 20 Feb 2023 08:25:28 +0000 Subject: [PATCH 17/26] add multi_thread for ir_ctx --- paddle/ir/ir_context.cc | 32 ++++++++--- paddle/ir/rw_lock.h | 102 +++++++++++++++++++++++++++++++++++ paddle/ir/storage_manager.cc | 54 +++++++++++-------- paddle/ir/storage_manager.h | 44 +++++++-------- paddle/ir/type_base.h | 23 ++++---- 5 files changed, 193 insertions(+), 62 deletions(-) create mode 100644 paddle/ir/rw_lock.h diff --git a/paddle/ir/ir_context.cc b/paddle/ir/ir_context.cc index 81078aae52bf9a..67a19e31c474de 100644 --- a/paddle/ir/ir_context.cc +++ b/paddle/ir/ir_context.cc @@ -16,6 +16,7 @@ #include "paddle/ir/builtin_type.h" #include "paddle/ir/ir_context.h" +#include "paddle/ir/rw_lock.h" #include "paddle/ir/type_base.h" namespace ir { @@ -26,6 +27,23 @@ class IrContextImpl { ~IrContextImpl() {} + void RegisterAbstractType(ir::TypeId type_id, AbstractType *abstract_type) { + ir::AutoWRLock lock(®isted_abstract_types_rw_lock_); + registed_abstract_types_.emplace(type_id, abstract_type); + } + + AbstractType *lookup(ir::TypeId type_id) { + ir::AutoRDLock lock(®isted_abstract_types_rw_lock_); + auto iter = registed_abstract_types_.find(type_id); + if (iter == registed_abstract_types_.end()) { + return nullptr; + } else { + return iter->second; + } + } + + ir::RWLock registed_abstract_types_rw_lock_; + // Cached AbstractType instances. std::unordered_map registed_abstract_types_; @@ -43,16 +61,14 @@ IrContext::IrContext() : impl_(new IrContextImpl()) { VLOG(4) << "==> Register Float32Type."; AbstractType *fp32_abstract_type = new AbstractType( std::move(AbstractType::get(TypeId::get()))); - registed_abstracted_type().emplace(TypeId::get(), - fp32_abstract_type); + impl_->RegisterAbstractType(TypeId::get(), fp32_abstract_type); TypeManager::RegisterType(this); impl_->fp32_type = TypeManager::get(this); VLOG(4) << "==> Register IntegerType."; AbstractType *int_abstract_type = new AbstractType( std::move(AbstractType::get(TypeId::get()))); - registed_abstracted_type().emplace(TypeId::get(), - int_abstract_type); + impl_->RegisterAbstractType(TypeId::get(), int_abstract_type); TypeManager::RegisterType(this); impl_->int1Ty = TypeManager::get(this, 1, 0); } @@ -70,11 +86,11 @@ const AbstractType &AbstractType::lookup(TypeId type_id, IrContext *ctx) { VLOG(4) << "==> Get registed abstract type (" << &type_id << ") from IrContext (" << ctx << ")."; auto &impl = ctx->impl(); - auto iter = impl.registed_abstract_types_.find(type_id); - if (iter == impl.registed_abstract_types_.end()) { - throw("Abstract type not found in IrContext."); + AbstractType *abstract_type = impl.lookup(type_id); + if (abstract_type) { + return *abstract_type; } else { - return *(iter->second); + throw("Abstract type not found in IrContext."); } } diff --git a/paddle/ir/rw_lock.h b/paddle/ir/rw_lock.h new file mode 100644 index 00000000000000..a34ba188ae8f45 --- /dev/null +++ b/paddle/ir/rw_lock.h @@ -0,0 +1,102 @@ +/* Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved. + +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. */ + +#pragma once + +#if !defined(_WIN32) +#include +#else +#include // NOLINT +#endif // !_WIN32 + +namespace ir { + +#if !defined(_WIN32) +struct RWLock { + RWLock() { pthread_rwlock_init(&lock_, nullptr); } + + ~RWLock() { pthread_rwlock_destroy(&lock_); } + + inline void RDLock() { + int state = pthread_rwlock_rdlock(&lock_); + if (state != 0) { + throw("The pthread failed to acquire read lock."); + } + } + + inline void WRLock() { + int state = pthread_rwlock_wrlock(&lock_); + if (state != 0) { + throw("The pthread failed to acquire write lock."); + } + } + + inline void UNLock() { + int state = pthread_rwlock_unlock(&lock_); + if (state != 0) { + throw("The pthread failed to unlock."); + } + } + + private: + pthread_rwlock_t lock_; +}; +// TODO(paddle-dev): Support RWLock for WIN32 for correctness. +#else +// https://stackoverflow.com/questions/7125250/making-pthread-rwlock-wrlock-recursive +// In windows, rw_lock seems like a hack. Use empty object and do nothing. +struct RWLock { + // FIXME(minqiyang): use mutex here to do fake lock + inline void RDLock() { mutex_.lock(); } + + inline void WRLock() { mutex_.lock(); } + + inline void UNLock() { mutex_.unlock(); } + + private: + std::mutex mutex_; +}; +#endif + +class AutoWRLock { + public: + explicit AutoWRLock(RWLock* rw_lock) : lock_(rw_lock) { Lock(); } + + ~AutoWRLock() { UnLock(); } + + private: + inline void Lock() { lock_->WRLock(); } + + inline void UnLock() { lock_->UNLock(); } + + private: + RWLock* lock_; +}; + +class AutoRDLock { + public: + explicit AutoRDLock(RWLock* rw_lock) : lock_(rw_lock) { Lock(); } + + ~AutoRDLock() { UnLock(); } + + private: + inline void Lock() { lock_->RDLock(); } + + inline void UnLock() { lock_->UNLock(); } + + private: + RWLock* lock_; +}; + +} // namespace ir diff --git a/paddle/ir/storage_manager.cc b/paddle/ir/storage_manager.cc index 1837d96a17be5e..4ea1ffe67a2d39 100644 --- a/paddle/ir/storage_manager.cc +++ b/paddle/ir/storage_manager.cc @@ -23,37 +23,37 @@ namespace ir { struct ParametricStorageManager { using StorageBase = StorageManager::StorageBase; - explicit ParametricStorageManager(std::function del_func) - : del_func_(del_func) {} + explicit ParametricStorageManager( + std::function destructor) + : destructor_(destructor) {} ~ParametricStorageManager() { for (const auto &instance : parametric_instances_) { - del_func_(instance.second); + destructor_(instance.second); } } // Get the storage of parametric type, if not in the cache, create and // insert the cache. - StorageBase *GetOrCreateParametricStorage( - std::size_t hash_value, - std::function is_equal_func, - std::function ctor_func) { + StorageBase *GetOrCreate(std::size_t hash_value, + std::function equal_func, + std::function constructor) { StorageBase *storage = nullptr; if (parametric_instances_.count(hash_value) == 0) { VLOG(4) << "not cache, create a new parameteric storage"; - storage = ctor_func(); + storage = constructor(); parametric_instances_.emplace(hash_value, storage); } else { auto pr = parametric_instances_.equal_range(hash_value); while (pr.first != pr.second) { - if (is_equal_func(pr.first->second)) { + if (equal_func(pr.first->second)) { VLOG(4) << "get cache, parameteric storage"; return pr.first->second; } ++pr.first; } VLOG(4) << "not cache, create a new parameteric storage"; - storage = ctor_func(); + storage = constructor(); parametric_instances_.emplace(hash_value, storage); } return storage; @@ -64,7 +64,7 @@ struct ParametricStorageManager { // is used for storage. std::unordered_multimap parametric_instances_; - std::function del_func_; + std::function destructor_; }; StorageManager::StorageManager() {} @@ -74,17 +74,21 @@ StorageManager::~StorageManager() = default; StorageManager::StorageBase *StorageManager::GetParametricStorageTypeImpl( TypeId type_id, std::size_t hash_value, - std::function is_equal_func, - std::function ctor_func) { - if (parametric_instance_.find(type_id) == parametric_instance_.end()) - throw("The input data pointer is null."); + std::function equal_func, + std::function constructor) { + { + ir::AutoRDLock lock(¶metric_instance_rw_lock_); + if (parametric_instance_.find(type_id) == parametric_instance_.end()) + throw("The input data pointer is null."); + } + ir::AutoWRLock lock(¶metric_instance_rw_lock_); ParametricStorageManager ¶metric_storage = *parametric_instance_[type_id]; - return parametric_storage.GetOrCreateParametricStorage( - hash_value, is_equal_func, ctor_func); + return parametric_storage.GetOrCreate(hash_value, equal_func, constructor); } StorageManager::StorageBase *StorageManager::GetParameterlessStorageTypeImpl( TypeId type_id) { + ir::AutoRDLock lock(¶meterless_instances_rw_lock_); VLOG(4) << "==> StorageManagerImpl::GetParameterlessStorage()."; if (parameterless_instances_.find(type_id) == parameterless_instances_.end()) throw("TypeId not found in IrContext."); @@ -94,16 +98,22 @@ StorageManager::StorageBase *StorageManager::GetParameterlessStorageTypeImpl( void StorageManager::RegisterParametricStorageTypeImpl( TypeId type_id, std::function del_func) { + ir::AutoWRLock lock(¶metric_instance_rw_lock_); parametric_instance_.emplace( type_id, std::make_unique(del_func)); } void StorageManager::RegisterParameterlessStorageTypeImpl( - TypeId type_id, std::function ctor_func) { - VLOG(4) << "==> StorageManager::RegisterParameterlessStorageTypeImpl()"; - if (parameterless_instances_.find(type_id) != parameterless_instances_.end()) - throw("storage class already registered"); - parameterless_instances_.emplace(type_id, ctor_func()); + TypeId type_id, std::function constructor) { + { + ir::AutoRDLock lock(¶meterless_instances_rw_lock_); + VLOG(4) << "==> StorageManager::RegisterParameterlessStorageTypeImpl()"; + if (parameterless_instances_.find(type_id) != + parameterless_instances_.end()) + throw("storage class already registered"); + } + ir::AutoWRLock lock(¶meterless_instances_rw_lock_); + parameterless_instances_.emplace(type_id, constructor()); } } // namespace ir diff --git a/paddle/ir/storage_manager.h b/paddle/ir/storage_manager.h index 1f2bb5a759fe6d..5aa8857a435495 100644 --- a/paddle/ir/storage_manager.h +++ b/paddle/ir/storage_manager.h @@ -18,6 +18,7 @@ #include #include +#include "paddle/ir/rw_lock.h" #include "paddle/ir/type_id.h" namespace ir { @@ -63,21 +64,23 @@ class StorageManager { /// \return A uniqued instance of Storage. /// template - Storage *get(std::function init_func, - TypeId type_id, - Args &&...args) { - auto derived_param_key = GetParamKey(std::forward(args)...); - std::size_t hash_value = Storage::HashValue(derived_param_key); - auto is_equal_func = [&derived_param_key](const StorageBase *existing) { - return static_cast(*existing) == derived_param_key; + Storage *GetParametricStorageType(std::function init_func, + TypeId type_id, + Args &&...args) { + // auto param = GetParamKey(std::forward(args)...); + typename Storage::ParamKey param = + typename Storage::ParamKey(std::forward(args)...); + std::size_t hash_value = Storage::HashValue(param); + auto equal_func = [¶m](const StorageBase *existing) { + return static_cast(*existing) == param; }; - auto ctor_func = [&]() { - auto *storage = Storage::Construct(derived_param_key); + auto constructor = [&]() { + auto *storage = Storage::Construct(param); if (init_func) init_func(storage); return storage; }; return static_cast(GetParametricStorageTypeImpl( - type_id, hash_value, is_equal_func, ctor_func)); + type_id, hash_value, equal_func, constructor)); } /// @@ -87,7 +90,7 @@ class StorageManager { /// \return A uniqued instance of Storage. /// template - Storage *get(TypeId type_id) { + Storage *GetParameterlessStorageType(TypeId type_id) { return static_cast(GetParameterlessStorageTypeImpl(type_id)); } @@ -118,20 +121,20 @@ class StorageManager { void RegisterParameterlessStorageType( TypeId type_id, std::function init_func) { VLOG(4) << "==> StorageManager::RegisterParameterlessStorageType()"; - auto ctor_func = [&]() { + auto constructor = [&]() { auto *storage = new Storage(); if (init_func) init_func(storage); return storage; }; - RegisterParameterlessStorageTypeImpl(type_id, ctor_func); + RegisterParameterlessStorageTypeImpl(type_id, constructor); } private: StorageBase *GetParametricStorageTypeImpl( TypeId type_id, std::size_t hash_value, - std::function is_equal_func, - std::function ctor_func); + std::function equal_func, + std::function constructor); StorageBase *GetParameterlessStorageTypeImpl(TypeId type_id); @@ -139,19 +142,18 @@ class StorageManager { TypeId type_id, std::function del_func); void RegisterParameterlessStorageTypeImpl( - TypeId type_id, std::function ctor_func); - - template - static typename ImplTy::ParamKey GetParamKey(Args &&...args) { - return typename ImplTy::ParamKey(args...); - } + TypeId type_id, std::function constructor); // This map is a mapping between type id and parameteric type storage. std::unordered_map> parametric_instance_; + ir::RWLock parametric_instance_rw_lock_; + // This map is a mapping between type id and parameterless type storage. std::unordered_map parameterless_instances_; + + ir::RWLock parameterless_instances_rw_lock_; }; } // namespace ir diff --git a/paddle/ir/type_base.h b/paddle/ir/type_base.h index cd9353c7f62ebc..38b07fe55888d2 100644 --- a/paddle/ir/type_base.h +++ b/paddle/ir/type_base.h @@ -128,8 +128,7 @@ struct TypeManager { /// template static T get(IrContext *ctx, Args &&...args) { - return GetWithTypeId( - ctx, T::type_id(), std::forward(args)...); + return get(ctx, T::type_id(), std::forward(args)...); } /// @@ -145,13 +144,14 @@ struct TypeManager { template static std:: enable_if_t::value, T> - GetWithTypeId(IrContext *ctx, TypeId type_id, Args &&...args) { - return ctx->storage_manager().get( - [&, type_id](TypeStorage *storage) { - storage->initialize(AbstractType::lookup(type_id, ctx)); - }, - type_id, - std::forward(args)...); + get(IrContext *ctx, TypeId type_id, Args &&...args) { + return ctx->storage_manager() + .GetParametricStorageType( + [&, type_id](TypeStorage *storage) { + storage->initialize(AbstractType::lookup(type_id, ctx)); + }, + type_id, + std::forward(args)...); } /// @@ -165,8 +165,9 @@ struct TypeManager { template static std:: enable_if_t::value, T> - GetWithTypeId(IrContext *ctx, TypeId type_id) { - return ctx->storage_manager().get(type_id); + get(IrContext *ctx, TypeId type_id) { + return ctx->storage_manager() + .GetParameterlessStorageType(type_id); } /// From 39d69cf7d216870b7a467c5538c5c39f64c349a8 Mon Sep 17 00:00:00 2001 From: zhangbo9674 Date: Tue, 21 Feb 2023 05:35:45 +0000 Subject: [PATCH 18/26] rwlock_2_spinlock, add REGISTER_TYPE_2_IRCONTEXT --- paddle/ir/CMakeLists.txt | 13 ++--- paddle/ir/builtin_type.h | 41 +++----------- paddle/ir/ir_context.cc | 51 +++++------------- paddle/ir/ir_context.h | 8 +++ paddle/ir/rw_lock.h | 102 ----------------------------------- paddle/ir/spin_lock.h | 66 +++++++++++++++++++++++ paddle/ir/storage_manager.cc | 38 +++++-------- paddle/ir/storage_manager.h | 6 +-- paddle/ir/type_base.h | 13 ++++- paddle/ir/type_test.cc | 69 +++++++++++++++++++++--- 10 files changed, 192 insertions(+), 215 deletions(-) delete mode 100644 paddle/ir/rw_lock.h create mode 100644 paddle/ir/spin_lock.h diff --git a/paddle/ir/CMakeLists.txt b/paddle/ir/CMakeLists.txt index ba46972e51913a..f0285a7d4d195f 100644 --- a/paddle/ir/CMakeLists.txt +++ b/paddle/ir/CMakeLists.txt @@ -5,11 +5,12 @@ endif() set(NEWIR_SOURCE_DIR "${PADDLE_SOURCE_DIR}/paddle/ir") set(NEWIR_BINARY_DIR "${PADDLE_BINARY_DIR}/paddle/ir") -cc_library(storage_manager SRCS storage_manager.cc) +file(GLOB IR_SRCS "*.cc") -cc_library( - ir_context - SRCS ir_context.cc - DEPS storage_manager) +file(GLOB IR_TEST_SRCS "*_test.cc") -cc_test_old(type_test SRCS type_test.cc DEPS ir_context gtest) +list(REMOVE_ITEM IR_SRCS ${IR_TEST_SRCS}) + +cc_library(new_ir SRCS ${IR_SRCS}) + +cc_test_old(type_test SRCS type_test.cc DEPS new_ir gtest) diff --git a/paddle/ir/builtin_type.h b/paddle/ir/builtin_type.h index 6d3fb66d006723..7abffa52ee0dd4 100644 --- a/paddle/ir/builtin_type.h +++ b/paddle/ir/builtin_type.h @@ -23,47 +23,20 @@ namespace ir { /// class Float32Type : public ir::Type { public: + using Type::Type; + REGISTER_TYPE_UTILS(Float32Type, ir::TypeStorage); static Float32Type get(ir::IrContext *context); }; -struct IntegerTypeStorage : public TypeStorage { - IntegerTypeStorage(unsigned width, unsigned signedness) - : width_(width), signedness_(signedness) {} - using ParamKey = std::pair; - - static std::size_t HashValue(const ParamKey &key) { - return hash_combine(std::hash()(std::get<0>(key)), - std::hash()(std::get<1>(key))); - } - - bool operator==(const ParamKey &key) const { - return ParamKey(width_, signedness_) == key; - } - - static IntegerTypeStorage *Construct(ParamKey key) { - return new IntegerTypeStorage(key.first, key.second); - } - - ParamKey GetAsKey() const { return ParamKey(width_, signedness_); } - - unsigned width_ : 30; - unsigned signedness_ : 2; - - private: - static std::size_t hash_combine(std::size_t lhs, std::size_t rhs) { - return lhs ^= rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2); - } -}; - -class IntegerType : public ir::Type { +class Int32Type : public ir::Type { public: - REGISTER_TYPE_UTILS(IntegerType, ir::IntegerTypeStorage); + using Type::Type; + + REGISTER_TYPE_UTILS(Int32Type, ir::TypeStorage); - static IntegerType get(ir::IrContext *context, - unsigned width, - unsigned signedness = 0); + static Int32Type get(ir::IrContext *context); }; } // namespace ir diff --git a/paddle/ir/ir_context.cc b/paddle/ir/ir_context.cc index 67a19e31c474de..788322586c5bd9 100644 --- a/paddle/ir/ir_context.cc +++ b/paddle/ir/ir_context.cc @@ -16,7 +16,7 @@ #include "paddle/ir/builtin_type.h" #include "paddle/ir/ir_context.h" -#include "paddle/ir/rw_lock.h" +#include "paddle/ir/spin_lock.h" #include "paddle/ir/type_base.h" namespace ir { @@ -28,12 +28,12 @@ class IrContextImpl { ~IrContextImpl() {} void RegisterAbstractType(ir::TypeId type_id, AbstractType *abstract_type) { - ir::AutoWRLock lock(®isted_abstract_types_rw_lock_); + std::lock_guard guard(registed_abstract_types_lock_); registed_abstract_types_.emplace(type_id, abstract_type); } AbstractType *lookup(ir::TypeId type_id) { - ir::AutoRDLock lock(®isted_abstract_types_rw_lock_); + std::lock_guard guard(registed_abstract_types_lock_); auto iter = registed_abstract_types_.find(type_id); if (iter == registed_abstract_types_.end()) { return nullptr; @@ -42,7 +42,7 @@ class IrContextImpl { } } - ir::RWLock registed_abstract_types_rw_lock_; + ir::SpinLock registed_abstract_types_lock_; // Cached AbstractType instances. std::unordered_map registed_abstract_types_; @@ -52,25 +52,22 @@ class IrContextImpl { // Some built-in type. Float32Type fp32_type; - IntegerType int1Ty; + Int32Type int32_type; }; IrContext *IrContext::ir_context_ = nullptr; IrContext::IrContext() : impl_(new IrContextImpl()) { - VLOG(4) << "==> Register Float32Type."; - AbstractType *fp32_abstract_type = new AbstractType( - std::move(AbstractType::get(TypeId::get()))); - impl_->RegisterAbstractType(TypeId::get(), fp32_abstract_type); - TypeManager::RegisterType(this); + REGISTER_TYPE_2_IRCONTEXT(Float32Type, this); impl_->fp32_type = TypeManager::get(this); - VLOG(4) << "==> Register IntegerType."; - AbstractType *int_abstract_type = new AbstractType( - std::move(AbstractType::get(TypeId::get()))); - impl_->RegisterAbstractType(TypeId::get(), int_abstract_type); - TypeManager::RegisterType(this); - impl_->int1Ty = TypeManager::get(this, 1, 0); + REGISTER_TYPE_2_IRCONTEXT(Int32Type, this); + impl_->int32_type = TypeManager::get(this); +} + +void IrContext::RegisterAbstractType(ir::TypeId type_id, + AbstractType *abstract_type) { + impl().RegisterAbstractType(type_id, abstract_type); } StorageManager &IrContext::storage_manager() { @@ -96,26 +93,6 @@ const AbstractType &AbstractType::lookup(TypeId type_id, IrContext *ctx) { Float32Type Float32Type::get(IrContext *ctx) { return ctx->impl().fp32_type; } -static IntegerType GetCachedIntegerType(unsigned width, - unsigned signedness, - IrContext *context) { - if (signedness != 0) return IntegerType(); - - switch (width) { - case 1: - return context->impl().int1Ty; - default: - return IntegerType(); - } -} - -IntegerType IntegerType::get(ir::IrContext *context, - unsigned width, - unsigned signedness) { - if (auto cached = GetCachedIntegerType(width, signedness, context)) - return cached; - VLOG(4) << "no cache, create a new"; - return IntegerType::create(context, width, signedness); -} +Int32Type Int32Type::get(IrContext *ctx) { return ctx->impl().int32_type; } } // namespace ir diff --git a/paddle/ir/ir_context.h b/paddle/ir/ir_context.h index 803399a4839ab5..9f1c4ae955273d 100644 --- a/paddle/ir/ir_context.h +++ b/paddle/ir/ir_context.h @@ -55,6 +55,14 @@ class IrContext { /// IrContextImpl &impl() { return *impl_; } + /// + /// \brief Register an AbstractType to IrContext + /// + /// \param type_id The type id of the AbstractType. + /// \param abstract_type AbstractType* provided by user. + /// + void RegisterAbstractType(ir::TypeId type_id, AbstractType *abstract_type); + /// /// \brief Returns the storage uniquer used for constructing TypeStorage /// instances. diff --git a/paddle/ir/rw_lock.h b/paddle/ir/rw_lock.h deleted file mode 100644 index a34ba188ae8f45..00000000000000 --- a/paddle/ir/rw_lock.h +++ /dev/null @@ -1,102 +0,0 @@ -/* Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved. - -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. */ - -#pragma once - -#if !defined(_WIN32) -#include -#else -#include // NOLINT -#endif // !_WIN32 - -namespace ir { - -#if !defined(_WIN32) -struct RWLock { - RWLock() { pthread_rwlock_init(&lock_, nullptr); } - - ~RWLock() { pthread_rwlock_destroy(&lock_); } - - inline void RDLock() { - int state = pthread_rwlock_rdlock(&lock_); - if (state != 0) { - throw("The pthread failed to acquire read lock."); - } - } - - inline void WRLock() { - int state = pthread_rwlock_wrlock(&lock_); - if (state != 0) { - throw("The pthread failed to acquire write lock."); - } - } - - inline void UNLock() { - int state = pthread_rwlock_unlock(&lock_); - if (state != 0) { - throw("The pthread failed to unlock."); - } - } - - private: - pthread_rwlock_t lock_; -}; -// TODO(paddle-dev): Support RWLock for WIN32 for correctness. -#else -// https://stackoverflow.com/questions/7125250/making-pthread-rwlock-wrlock-recursive -// In windows, rw_lock seems like a hack. Use empty object and do nothing. -struct RWLock { - // FIXME(minqiyang): use mutex here to do fake lock - inline void RDLock() { mutex_.lock(); } - - inline void WRLock() { mutex_.lock(); } - - inline void UNLock() { mutex_.unlock(); } - - private: - std::mutex mutex_; -}; -#endif - -class AutoWRLock { - public: - explicit AutoWRLock(RWLock* rw_lock) : lock_(rw_lock) { Lock(); } - - ~AutoWRLock() { UnLock(); } - - private: - inline void Lock() { lock_->WRLock(); } - - inline void UnLock() { lock_->UNLock(); } - - private: - RWLock* lock_; -}; - -class AutoRDLock { - public: - explicit AutoRDLock(RWLock* rw_lock) : lock_(rw_lock) { Lock(); } - - ~AutoRDLock() { UnLock(); } - - private: - inline void Lock() { lock_->RDLock(); } - - inline void UnLock() { lock_->UNLock(); } - - private: - RWLock* lock_; -}; - -} // namespace ir diff --git a/paddle/ir/spin_lock.h b/paddle/ir/spin_lock.h new file mode 100644 index 00000000000000..4150f419c31598 --- /dev/null +++ b/paddle/ir/spin_lock.h @@ -0,0 +1,66 @@ +// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved. +// +// 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. + +#pragma once + +#include +#if defined(_M_X64) || defined(__x86_64__) || defined(_M_IX86) || \ + defined(__i386__) +#define __PADDLE_x86__ +#include +#endif +#include +#include + +namespace ir { +static inline void CpuRelax() { +#if defined(__PADDLE_x86__) + _mm_pause(); +#endif +} + +class SpinLock { + public: + SpinLock() : mlock_(false) {} + + void lock() { + for (;;) { + if (!mlock_.exchange(true, std::memory_order_acquire)) { + break; + } + constexpr int kMaxLoop = 32; + for (int loop = 1; mlock_.load(std::memory_order_relaxed);) { + if (loop <= kMaxLoop) { + for (int i = 1; i <= loop; ++i) { + CpuRelax(); + } + loop *= 2; + } else { + std::this_thread::yield(); + } + } + } + } + + void unlock() { mlock_.store(false, std::memory_order_release); } + + private: + SpinLock(const SpinLock&) = delete; + SpinLock(SpinLock&&) = delete; + SpinLock& operator=(const SpinLock&) = delete; + SpinLock& operator=(SpinLock&&) = delete; + std::atomic mlock_; +}; + +} // namespace ir diff --git a/paddle/ir/storage_manager.cc b/paddle/ir/storage_manager.cc index 4ea1ffe67a2d39..71131c6ba81545 100644 --- a/paddle/ir/storage_manager.cc +++ b/paddle/ir/storage_manager.cc @@ -38,12 +38,7 @@ struct ParametricStorageManager { StorageBase *GetOrCreate(std::size_t hash_value, std::function equal_func, std::function constructor) { - StorageBase *storage = nullptr; - if (parametric_instances_.count(hash_value) == 0) { - VLOG(4) << "not cache, create a new parameteric storage"; - storage = constructor(); - parametric_instances_.emplace(hash_value, storage); - } else { + if (parametric_instances_.count(hash_value) != 0) { auto pr = parametric_instances_.equal_range(hash_value); while (pr.first != pr.second) { if (equal_func(pr.first->second)) { @@ -52,10 +47,10 @@ struct ParametricStorageManager { } ++pr.first; } - VLOG(4) << "not cache, create a new parameteric storage"; - storage = constructor(); - parametric_instances_.emplace(hash_value, storage); } + VLOG(4) << "not cache, create a new parameteric storage"; + StorageBase *storage = constructor(); + parametric_instances_.emplace(hash_value, storage); return storage; } @@ -76,19 +71,16 @@ StorageManager::StorageBase *StorageManager::GetParametricStorageTypeImpl( std::size_t hash_value, std::function equal_func, std::function constructor) { - { - ir::AutoRDLock lock(¶metric_instance_rw_lock_); - if (parametric_instance_.find(type_id) == parametric_instance_.end()) - throw("The input data pointer is null."); - } - ir::AutoWRLock lock(¶metric_instance_rw_lock_); + std::lock_guard guard(parametric_instance_lock_); + if (parametric_instance_.find(type_id) == parametric_instance_.end()) + throw("The input data pointer is null."); ParametricStorageManager ¶metric_storage = *parametric_instance_[type_id]; return parametric_storage.GetOrCreate(hash_value, equal_func, constructor); } StorageManager::StorageBase *StorageManager::GetParameterlessStorageTypeImpl( TypeId type_id) { - ir::AutoRDLock lock(¶meterless_instances_rw_lock_); + std::lock_guard guard(parameterless_instances_lock_); VLOG(4) << "==> StorageManagerImpl::GetParameterlessStorage()."; if (parameterless_instances_.find(type_id) == parameterless_instances_.end()) throw("TypeId not found in IrContext."); @@ -98,21 +90,17 @@ StorageManager::StorageBase *StorageManager::GetParameterlessStorageTypeImpl( void StorageManager::RegisterParametricStorageTypeImpl( TypeId type_id, std::function del_func) { - ir::AutoWRLock lock(¶metric_instance_rw_lock_); + std::lock_guard guard(parametric_instance_lock_); parametric_instance_.emplace( type_id, std::make_unique(del_func)); } void StorageManager::RegisterParameterlessStorageTypeImpl( TypeId type_id, std::function constructor) { - { - ir::AutoRDLock lock(¶meterless_instances_rw_lock_); - VLOG(4) << "==> StorageManager::RegisterParameterlessStorageTypeImpl()"; - if (parameterless_instances_.find(type_id) != - parameterless_instances_.end()) - throw("storage class already registered"); - } - ir::AutoWRLock lock(¶meterless_instances_rw_lock_); + std::lock_guard guard(parameterless_instances_lock_); + VLOG(4) << "==> StorageManager::RegisterParameterlessStorageTypeImpl()"; + if (parameterless_instances_.find(type_id) != parameterless_instances_.end()) + throw("storage class already registered"); parameterless_instances_.emplace(type_id, constructor()); } diff --git a/paddle/ir/storage_manager.h b/paddle/ir/storage_manager.h index 5aa8857a435495..8aa87f428afb38 100644 --- a/paddle/ir/storage_manager.h +++ b/paddle/ir/storage_manager.h @@ -18,7 +18,7 @@ #include #include -#include "paddle/ir/rw_lock.h" +#include "paddle/ir/spin_lock.h" #include "paddle/ir/type_id.h" namespace ir { @@ -148,12 +148,12 @@ class StorageManager { std::unordered_map> parametric_instance_; - ir::RWLock parametric_instance_rw_lock_; + ir::SpinLock parametric_instance_lock_; // This map is a mapping between type id and parameterless type storage. std::unordered_map parameterless_instances_; - ir::RWLock parameterless_instances_rw_lock_; + ir::SpinLock parameterless_instances_lock_; }; } // namespace ir diff --git a/paddle/ir/type_base.h b/paddle/ir/type_base.h index 38b07fe55888d2..c657c19b626533 100644 --- a/paddle/ir/type_base.h +++ b/paddle/ir/type_base.h @@ -216,7 +216,6 @@ struct TypeManager { /// custom Type class. /// #define REGISTER_TYPE_UTILS(concrete_type, storage_type) \ - using Type::Type; \ using StorageType = storage_type; \ StorageType *storage() const { \ return static_cast(this->storage_); \ @@ -227,8 +226,18 @@ struct TypeManager { return val.type_id() == type_id(); \ } \ template \ - static concrete_type create(IrContext *ctx, Args... args) { \ + static concrete_type create(ir::IrContext *ctx, Args... args) { \ return ir::TypeManager::template get(ctx, args...); \ } +/// +/// \brief This macro definition is used to register custom Type class. +/// +#define REGISTER_TYPE_2_IRCONTEXT(concrete_type, ir_context) \ + ir::AbstractType *abstract_type_##concrete_type = new ir::AbstractType( \ + std::move(ir::AbstractType::get(ir::TypeId::get()))); \ + ir_context->RegisterAbstractType(ir::TypeId::get(), \ + abstract_type_##concrete_type); \ + ir::TypeManager::RegisterType(ir_context); + } // namespace ir diff --git a/paddle/ir/type_test.cc b/paddle/ir/type_test.cc index 4177da14c68f96..8215fc35d3b629 100644 --- a/paddle/ir/type_test.cc +++ b/paddle/ir/type_test.cc @@ -59,7 +59,7 @@ TEST(type_test, type_storage) { EXPECT_EQ(storage_a.abstract_type().type_id(), abstract_type_a.type_id()); } -TEST(type_test, type) { +TEST(type_test, built_in_type) { // Test creation of built-in parameterless type. ir::IrContext *ctx = ir::IrContext::Instance(); ir::Type fp32_1 = ir::Float32Type::get(ctx); @@ -74,11 +74,68 @@ TEST(type_test, type) { 1); EXPECT_EQ(ir::Float32Type::classof(fp32_1), 1); - ir::Type int1_1 = ir::IntegerType::get(ctx, 1, 0); - ir::Type int1_2 = ir::IntegerType::get(ctx, 1, 0); + ir::Type int32_1 = ir::Int32Type::get(ctx); + ir::Type int32_2 = ir::Int32Type::get(ctx); + EXPECT_EQ(int32_1 == int32_2, 1); + EXPECT_EQ(int32_1.type_id() == int32_2.type_id(), 1); + EXPECT_EQ(&int32_1.abstract_type() == + &ir::AbstractType::lookup(int32_1.type_id(), ctx), + 1); + EXPECT_EQ(ir::Int32Type::classof(int32_1), 1); +} + +struct IntegerTypeStorage : public ir::TypeStorage { + IntegerTypeStorage(unsigned width, unsigned signedness) + : width_(width), signedness_(signedness) {} + using ParamKey = std::pair; + + static std::size_t HashValue(const ParamKey &key) { + return hash_combine(std::hash()(std::get<0>(key)), + std::hash()(std::get<1>(key))); + } + + bool operator==(const ParamKey &key) const { + return ParamKey(width_, signedness_) == key; + } + + static IntegerTypeStorage *Construct(ParamKey key) { + return new IntegerTypeStorage(key.first, key.second); + } + + ParamKey GetAsKey() const { return ParamKey(width_, signedness_); } + + unsigned width_ : 30; + unsigned signedness_ : 2; + + private: + static std::size_t hash_combine(std::size_t lhs, std::size_t rhs) { + return lhs ^= rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2); + } +}; + +class IntegerType : public ir::Type { + public: + using Type::Type; + REGISTER_TYPE_UTILS(IntegerType, IntegerTypeStorage); + + static IntegerType get(ir::IrContext *context, + unsigned width, + unsigned signedness = 0); +}; + +IntegerType IntegerType::get(ir::IrContext *context, + unsigned width, + unsigned signedness) { + return IntegerType::create(context, width, signedness); +} + +TEST(type_test, parameteric_type) { + ir::IrContext *ctx = ir::IrContext::Instance(); + REGISTER_TYPE_2_IRCONTEXT(IntegerType, ctx); + ir::Type int1_1 = IntegerType::get(ctx, 1, 0); + ir::Type int1_2 = IntegerType::get(ctx, 1, 0); EXPECT_EQ(int1_1 == int1_2, 1); - ir::Type int8_1 = ir::IntegerType::get(ctx, 8, 0); - ir::Type int8_2 = ir::IntegerType::get(ctx, 8, 0); - EXPECT_EQ(int8_1 == int8_2, 1); + ir::Type int8 = IntegerType::get(ctx, 8, 0); + EXPECT_EQ(int8 == int1_2, 0); } From 4736b46ccd9706e4a0e17e328644eb53f896f901 Mon Sep 17 00:00:00 2001 From: zhangbo9674 Date: Tue, 21 Feb 2023 06:52:34 +0000 Subject: [PATCH 19/26] DECLARE_TYPE_UTILITY_FUNCTOR --- paddle/fluid/memory/allocation/spin_lock.h | 2 +- paddle/ir/builtin_type.h | 8 ++++---- paddle/ir/type_base.h | 2 +- paddle/ir/type_test.cc | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/paddle/fluid/memory/allocation/spin_lock.h b/paddle/fluid/memory/allocation/spin_lock.h index 2bbe340e7c6912..60d115ab227afd 100644 --- a/paddle/fluid/memory/allocation/spin_lock.h +++ b/paddle/fluid/memory/allocation/spin_lock.h @@ -1,4 +1,4 @@ -// Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved. +// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/paddle/ir/builtin_type.h b/paddle/ir/builtin_type.h index 7abffa52ee0dd4..77159794bf11ed 100644 --- a/paddle/ir/builtin_type.h +++ b/paddle/ir/builtin_type.h @@ -18,14 +18,14 @@ namespace ir { /// -/// \brief Interfaces for user-created built-in types. For example: -/// Type fp32 = Float32Type::get(ctx); +/// \brief Definitions of built-in type classes. The built-in type object get +/// method is as follows: Type fp32 = Float32Type::get(ctx); /// class Float32Type : public ir::Type { public: using Type::Type; - REGISTER_TYPE_UTILS(Float32Type, ir::TypeStorage); + DECLARE_TYPE_UTILITY_FUNCTOR(Float32Type, ir::TypeStorage); static Float32Type get(ir::IrContext *context); }; @@ -34,7 +34,7 @@ class Int32Type : public ir::Type { public: using Type::Type; - REGISTER_TYPE_UTILS(Int32Type, ir::TypeStorage); + DECLARE_TYPE_UTILITY_FUNCTOR(Int32Type, ir::TypeStorage); static Int32Type get(ir::IrContext *context); }; diff --git a/paddle/ir/type_base.h b/paddle/ir/type_base.h index c657c19b626533..0d1799a47c21f3 100644 --- a/paddle/ir/type_base.h +++ b/paddle/ir/type_base.h @@ -215,7 +215,7 @@ struct TypeManager { /// \brief This macro definition is used to add some necessary functions to the /// custom Type class. /// -#define REGISTER_TYPE_UTILS(concrete_type, storage_type) \ +#define DECLARE_TYPE_UTILITY_FUNCTOR(concrete_type, storage_type) \ using StorageType = storage_type; \ StorageType *storage() const { \ return static_cast(this->storage_); \ diff --git a/paddle/ir/type_test.cc b/paddle/ir/type_test.cc index 8215fc35d3b629..089976543e2fd6 100644 --- a/paddle/ir/type_test.cc +++ b/paddle/ir/type_test.cc @@ -116,7 +116,7 @@ struct IntegerTypeStorage : public ir::TypeStorage { class IntegerType : public ir::Type { public: using Type::Type; - REGISTER_TYPE_UTILS(IntegerType, IntegerTypeStorage); + DECLARE_TYPE_UTILITY_FUNCTOR(IntegerType, IntegerTypeStorage); static IntegerType get(ir::IrContext *context, unsigned width, From 183e3a11dabe9661b304170e1fc9c298edb1f0c6 Mon Sep 17 00:00:00 2001 From: zhangbo9674 Date: Tue, 21 Feb 2023 10:53:32 +0000 Subject: [PATCH 20/26] refine ircontext singleton --- paddle/ir/ir_context.cc | 13 +++++++++++-- paddle/ir/ir_context.h | 20 +++----------------- paddle/ir/storage_manager.cc | 1 + paddle/ir/type_test.cc | 4 ++-- 4 files changed, 17 insertions(+), 21 deletions(-) diff --git a/paddle/ir/ir_context.cc b/paddle/ir/ir_context.cc index 788322586c5bd9..01731d9765a9d1 100644 --- a/paddle/ir/ir_context.cc +++ b/paddle/ir/ir_context.cc @@ -25,7 +25,13 @@ class IrContextImpl { public: IrContextImpl() {} - ~IrContextImpl() {} + ~IrContextImpl() { + std::lock_guard guard(registed_abstract_types_lock_); + for (auto abstract_type_map : registed_abstract_types_) { + delete abstract_type_map.second; + } + registed_abstract_types_.clear(); + } void RegisterAbstractType(ir::TypeId type_id, AbstractType *abstract_type) { std::lock_guard guard(registed_abstract_types_lock_); @@ -55,7 +61,10 @@ class IrContextImpl { Int32Type int32_type; }; -IrContext *IrContext::ir_context_ = nullptr; +IrContext &IrContext::Instance() { + static IrContext context; + return context; +} IrContext::IrContext() : impl_(new IrContextImpl()) { REGISTER_TYPE_2_IRCONTEXT(Float32Type, this); diff --git a/paddle/ir/ir_context.h b/paddle/ir/ir_context.h index 9f1c4ae955273d..949de4a6598171 100644 --- a/paddle/ir/ir_context.h +++ b/paddle/ir/ir_context.h @@ -33,19 +33,7 @@ class IrContext { /// /// \brief Initializes a new instance of IrContext. /// - /// \return Global parameterless for IrContext. - /// - static IrContext *Instance() { - VLOG(4) << "=> Instance called with context (ir_context_ == " << ir_context_ - << ")."; - if (ir_context_ == nullptr) { - ir_context_ = new IrContext(); - } - VLOG(4) << " |-> (ir_context_ == " << ir_context_ << ")."; - return ir_context_; - } - - ~IrContext(); + static IrContext &Instance(); /// /// \brief Get an instance of IrContextImpl, a private member of IrContext. @@ -81,14 +69,12 @@ class IrContext { /// std::unordered_map ®isted_abstracted_type(); - private: - IrContext(); - IrContext(const IrContext &) = delete; void operator=(const IrContext &) = delete; - static IrContext *ir_context_; + private: + IrContext(); const std::unique_ptr impl_; }; diff --git a/paddle/ir/storage_manager.cc b/paddle/ir/storage_manager.cc index 71131c6ba81545..84fda55ea7934d 100644 --- a/paddle/ir/storage_manager.cc +++ b/paddle/ir/storage_manager.cc @@ -28,6 +28,7 @@ struct ParametricStorageManager { : destructor_(destructor) {} ~ParametricStorageManager() { + if (!destructor_) return; for (const auto &instance : parametric_instances_) { destructor_(instance.second); } diff --git a/paddle/ir/type_test.cc b/paddle/ir/type_test.cc index 089976543e2fd6..a3af9ce8bbb48b 100644 --- a/paddle/ir/type_test.cc +++ b/paddle/ir/type_test.cc @@ -61,7 +61,7 @@ TEST(type_test, type_storage) { TEST(type_test, built_in_type) { // Test creation of built-in parameterless type. - ir::IrContext *ctx = ir::IrContext::Instance(); + ir::IrContext *ctx = &ir::IrContext::Instance(); ir::Type fp32_1 = ir::Float32Type::get(ctx); // Test interfaces of class Type @@ -130,7 +130,7 @@ IntegerType IntegerType::get(ir::IrContext *context, } TEST(type_test, parameteric_type) { - ir::IrContext *ctx = ir::IrContext::Instance(); + ir::IrContext *ctx = &ir::IrContext::Instance(); REGISTER_TYPE_2_IRCONTEXT(IntegerType, ctx); ir::Type int1_1 = IntegerType::get(ctx, 1, 0); ir::Type int1_2 = IntegerType::get(ctx, 1, 0); From 96cd329eebb490868b34da272787a94abc253aba Mon Sep 17 00:00:00 2001 From: zhangbo9674 Date: Tue, 21 Feb 2023 11:15:04 +0000 Subject: [PATCH 21/26] del destructor for ParametricStorageManager --- paddle/ir/storage_manager.cc | 18 +++++++----------- paddle/ir/storage_manager.h | 12 ++---------- paddle/ir/type_base.h | 6 ++++-- 3 files changed, 13 insertions(+), 23 deletions(-) diff --git a/paddle/ir/storage_manager.cc b/paddle/ir/storage_manager.cc index 84fda55ea7934d..ccee158197ebcb 100644 --- a/paddle/ir/storage_manager.cc +++ b/paddle/ir/storage_manager.cc @@ -23,15 +23,14 @@ namespace ir { struct ParametricStorageManager { using StorageBase = StorageManager::StorageBase; - explicit ParametricStorageManager( - std::function destructor) - : destructor_(destructor) {} + ParametricStorageManager() {} ~ParametricStorageManager() { - if (!destructor_) return; for (const auto &instance : parametric_instances_) { - destructor_(instance.second); + VLOG(4) << "delete parametric_instances"; + delete instance.second; } + parametric_instances_.clear(); } // Get the storage of parametric type, if not in the cache, create and @@ -59,8 +58,6 @@ struct ParametricStorageManager { // In order to prevent hash conflicts, the unordered_multimap data structure // is used for storage. std::unordered_multimap parametric_instances_; - - std::function destructor_; }; StorageManager::StorageManager() {} @@ -89,11 +86,10 @@ StorageManager::StorageBase *StorageManager::GetParameterlessStorageTypeImpl( return parameterless_instance; } -void StorageManager::RegisterParametricStorageTypeImpl( - TypeId type_id, std::function del_func) { +void StorageManager::RegisterParametricStorageTypeImpl(TypeId type_id) { std::lock_guard guard(parametric_instance_lock_); - parametric_instance_.emplace( - type_id, std::make_unique(del_func)); + parametric_instance_.emplace(type_id, + std::make_unique()); } void StorageManager::RegisterParameterlessStorageTypeImpl( diff --git a/paddle/ir/storage_manager.h b/paddle/ir/storage_manager.h index 8aa87f428afb38..b3658f654cc617 100644 --- a/paddle/ir/storage_manager.h +++ b/paddle/ir/storage_manager.h @@ -101,14 +101,7 @@ class StorageManager { /// template void RegisterParametricStorageType(TypeId type_id) { - if (std::is_trivially_destructible::value) { - return RegisterParametricStorageTypeImpl(type_id, nullptr); - } else { - return RegisterParametricStorageTypeImpl( - type_id, [](StorageBase *storage) { - static_cast(storage)->~Storage(); - }); - } + return RegisterParametricStorageTypeImpl(type_id); } /// @@ -138,8 +131,7 @@ class StorageManager { StorageBase *GetParameterlessStorageTypeImpl(TypeId type_id); - void RegisterParametricStorageTypeImpl( - TypeId type_id, std::function del_func); + void RegisterParametricStorageTypeImpl(TypeId type_id); void RegisterParameterlessStorageTypeImpl( TypeId type_id, std::function constructor); diff --git a/paddle/ir/type_base.h b/paddle/ir/type_base.h index 0d1799a47c21f3..47197b8227a502 100644 --- a/paddle/ir/type_base.h +++ b/paddle/ir/type_base.h @@ -128,7 +128,8 @@ struct TypeManager { /// template static T get(IrContext *ctx, Args &&...args) { - return get(ctx, T::type_id(), std::forward(args)...); + return get( + ctx, ir::TypeId::get(), std::forward(args)...); } /// @@ -177,7 +178,8 @@ struct TypeManager { /// template static void RegisterType(IrContext *ctx) { - RegisterType(ctx, T::type_id()); // class Type需要提供type_id接口 + RegisterType(ctx, + ir::TypeId::get()); // class Type需要提供type_id接口 } /// From 73efa4578ddda4061ea8a90002d5a1ccb4abc7eb Mon Sep 17 00:00:00 2001 From: zhangbo9674 Date: Tue, 21 Feb 2023 11:16:37 +0000 Subject: [PATCH 22/26] refine code --- paddle/fluid/memory/allocation/spin_lock.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/paddle/fluid/memory/allocation/spin_lock.h b/paddle/fluid/memory/allocation/spin_lock.h index 60d115ab227afd..2bbe340e7c6912 100644 --- a/paddle/fluid/memory/allocation/spin_lock.h +++ b/paddle/fluid/memory/allocation/spin_lock.h @@ -1,4 +1,4 @@ -// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved. +// Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. From 89c953fc266f6b89762730e07bfc770ef44274e0 Mon Sep 17 00:00:00 2001 From: zhangbo9674 Date: Tue, 21 Feb 2023 11:50:01 +0000 Subject: [PATCH 23/26] Add necessary logs for debugging --- paddle/ir/ir_context.cc | 17 ++++++++++++++--- paddle/ir/storage_manager.cc | 19 ++++++++++++++----- paddle/ir/storage_manager.h | 2 -- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/paddle/ir/ir_context.cc b/paddle/ir/ir_context.cc index 01731d9765a9d1..b8a7a8cfff84f5 100644 --- a/paddle/ir/ir_context.cc +++ b/paddle/ir/ir_context.cc @@ -35,6 +35,9 @@ class IrContextImpl { void RegisterAbstractType(ir::TypeId type_id, AbstractType *abstract_type) { std::lock_guard guard(registed_abstract_types_lock_); + VLOG(4) << "IrContext register an abstract_type of: [TypeId_hash=" + << std::hash()(type_id) + << ", AbstractType_ptr=" << abstract_type << "]."; registed_abstract_types_.emplace(type_id, abstract_type); } @@ -42,8 +45,13 @@ class IrContextImpl { std::lock_guard guard(registed_abstract_types_lock_); auto iter = registed_abstract_types_.find(type_id); if (iter == registed_abstract_types_.end()) { + VLOG(4) << "IrContext not fonund cached abstract_type of: [TypeId_hash=" + << std::hash()(type_id) << "]."; return nullptr; } else { + VLOG(4) << "IrContext fonund a cached abstract_type of: [TypeId_hash=" + << std::hash()(type_id) + << ", AbstractType_ptr=" << iter->second << "]."; return iter->second; } } @@ -67,11 +75,13 @@ IrContext &IrContext::Instance() { } IrContext::IrContext() : impl_(new IrContextImpl()) { + VLOG(4) << "IrContext register built-in type..."; REGISTER_TYPE_2_IRCONTEXT(Float32Type, this); impl_->fp32_type = TypeManager::get(this); - + VLOG(4) << "Float32Type registration complete"; REGISTER_TYPE_2_IRCONTEXT(Int32Type, this); impl_->int32_type = TypeManager::get(this); + VLOG(4) << "Int32Type registration complete"; } void IrContext::RegisterAbstractType(ir::TypeId type_id, @@ -89,8 +99,9 @@ std::unordered_map } const AbstractType &AbstractType::lookup(TypeId type_id, IrContext *ctx) { - VLOG(4) << "==> Get registed abstract type (" << &type_id - << ") from IrContext (" << ctx << ")."; + VLOG(4) << "Lookup abstract type [TypeId_hash=" + << std::hash()(type_id) << "] from IrContext [ptr=" << ctx + << "]."; auto &impl = ctx->impl(); AbstractType *abstract_type = impl.lookup(type_id); if (abstract_type) { diff --git a/paddle/ir/storage_manager.cc b/paddle/ir/storage_manager.cc index ccee158197ebcb..991077e8777c46 100644 --- a/paddle/ir/storage_manager.cc +++ b/paddle/ir/storage_manager.cc @@ -27,7 +27,6 @@ struct ParametricStorageManager { ~ParametricStorageManager() { for (const auto &instance : parametric_instances_) { - VLOG(4) << "delete parametric_instances"; delete instance.second; } parametric_instances_.clear(); @@ -42,15 +41,18 @@ struct ParametricStorageManager { auto pr = parametric_instances_.equal_range(hash_value); while (pr.first != pr.second) { if (equal_func(pr.first->second)) { - VLOG(4) << "get cache, parameteric storage"; + VLOG(4) << "Found a cached parameteric storage of: [param_hash=" + << hash_value << ", storage_ptr=" << pr.first->second << "]."; return pr.first->second; } ++pr.first; } } - VLOG(4) << "not cache, create a new parameteric storage"; StorageBase *storage = constructor(); parametric_instances_.emplace(hash_value, storage); + VLOG(4) << "No cache found, construct and cache a new parameteric storage " + "of: [param_hash=" + << hash_value << ", storage_ptr=" << storage << "]."; return storage; } @@ -70,6 +72,9 @@ StorageManager::StorageBase *StorageManager::GetParametricStorageTypeImpl( std::function equal_func, std::function constructor) { std::lock_guard guard(parametric_instance_lock_); + VLOG(4) << "StorageManager get parameteretric storage of: [TypeId_hash=" + << std::hash()(type_id) << ", param_hash=" << hash_value + << "]."; if (parametric_instance_.find(type_id) == parametric_instance_.end()) throw("The input data pointer is null."); ParametricStorageManager ¶metric_storage = *parametric_instance_[type_id]; @@ -79,7 +84,8 @@ StorageManager::StorageBase *StorageManager::GetParametricStorageTypeImpl( StorageManager::StorageBase *StorageManager::GetParameterlessStorageTypeImpl( TypeId type_id) { std::lock_guard guard(parameterless_instances_lock_); - VLOG(4) << "==> StorageManagerImpl::GetParameterlessStorage()."; + VLOG(4) << "StorageManager get parameterless storage of: [TypeId_hash=" + << std::hash()(type_id) << "]."; if (parameterless_instances_.find(type_id) == parameterless_instances_.end()) throw("TypeId not found in IrContext."); StorageBase *parameterless_instance = parameterless_instances_[type_id]; @@ -88,6 +94,8 @@ StorageManager::StorageBase *StorageManager::GetParameterlessStorageTypeImpl( void StorageManager::RegisterParametricStorageTypeImpl(TypeId type_id) { std::lock_guard guard(parametric_instance_lock_); + VLOG(4) << "StorageManager register parameteric storage of: [TypeId_hash=" + << std::hash()(type_id) << "]."; parametric_instance_.emplace(type_id, std::make_unique()); } @@ -95,7 +103,8 @@ void StorageManager::RegisterParametricStorageTypeImpl(TypeId type_id) { void StorageManager::RegisterParameterlessStorageTypeImpl( TypeId type_id, std::function constructor) { std::lock_guard guard(parameterless_instances_lock_); - VLOG(4) << "==> StorageManager::RegisterParameterlessStorageTypeImpl()"; + VLOG(4) << "StorageManager register parameterless storage of: [TypeId_hash=" + << std::hash()(type_id) << "]."; if (parameterless_instances_.find(type_id) != parameterless_instances_.end()) throw("storage class already registered"); parameterless_instances_.emplace(type_id, constructor()); diff --git a/paddle/ir/storage_manager.h b/paddle/ir/storage_manager.h index b3658f654cc617..f94174586bc97e 100644 --- a/paddle/ir/storage_manager.h +++ b/paddle/ir/storage_manager.h @@ -67,7 +67,6 @@ class StorageManager { Storage *GetParametricStorageType(std::function init_func, TypeId type_id, Args &&...args) { - // auto param = GetParamKey(std::forward(args)...); typename Storage::ParamKey param = typename Storage::ParamKey(std::forward(args)...); std::size_t hash_value = Storage::HashValue(param); @@ -113,7 +112,6 @@ class StorageManager { template void RegisterParameterlessStorageType( TypeId type_id, std::function init_func) { - VLOG(4) << "==> StorageManager::RegisterParameterlessStorageType()"; auto constructor = [&]() { auto *storage = new Storage(); if (init_func) init_func(storage); From 5451cbaed31f0d078ba11d6ee5921f53884cedc2 Mon Sep 17 00:00:00 2001 From: zhangbo9674 Date: Wed, 22 Feb 2023 02:57:41 +0000 Subject: [PATCH 24/26] refine ir_context instance --- paddle/ir/ir_context.cc | 4 ++-- paddle/ir/ir_context.h | 2 +- paddle/ir/type_test.cc | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/paddle/ir/ir_context.cc b/paddle/ir/ir_context.cc index b8a7a8cfff84f5..6aed600903438e 100644 --- a/paddle/ir/ir_context.cc +++ b/paddle/ir/ir_context.cc @@ -69,9 +69,9 @@ class IrContextImpl { Int32Type int32_type; }; -IrContext &IrContext::Instance() { +IrContext *IrContext::Instance() { static IrContext context; - return context; + return &context; } IrContext::IrContext() : impl_(new IrContextImpl()) { diff --git a/paddle/ir/ir_context.h b/paddle/ir/ir_context.h index 949de4a6598171..146497e6c6c949 100644 --- a/paddle/ir/ir_context.h +++ b/paddle/ir/ir_context.h @@ -33,7 +33,7 @@ class IrContext { /// /// \brief Initializes a new instance of IrContext. /// - static IrContext &Instance(); + static IrContext *Instance(); /// /// \brief Get an instance of IrContextImpl, a private member of IrContext. diff --git a/paddle/ir/type_test.cc b/paddle/ir/type_test.cc index a3af9ce8bbb48b..089976543e2fd6 100644 --- a/paddle/ir/type_test.cc +++ b/paddle/ir/type_test.cc @@ -61,7 +61,7 @@ TEST(type_test, type_storage) { TEST(type_test, built_in_type) { // Test creation of built-in parameterless type. - ir::IrContext *ctx = &ir::IrContext::Instance(); + ir::IrContext *ctx = ir::IrContext::Instance(); ir::Type fp32_1 = ir::Float32Type::get(ctx); // Test interfaces of class Type @@ -130,7 +130,7 @@ IntegerType IntegerType::get(ir::IrContext *context, } TEST(type_test, parameteric_type) { - ir::IrContext *ctx = &ir::IrContext::Instance(); + ir::IrContext *ctx = ir::IrContext::Instance(); REGISTER_TYPE_2_IRCONTEXT(IntegerType, ctx); ir::Type int1_1 = IntegerType::get(ctx, 1, 0); ir::Type int1_2 = IntegerType::get(ctx, 1, 0); From c7cf04fc36c72bdf5ddd68a01869b94587d0a1b9 Mon Sep 17 00:00:00 2001 From: zhangbo9674 Date: Wed, 22 Feb 2023 03:30:06 +0000 Subject: [PATCH 25/26] refine type get interface --- paddle/ir/type_base.h | 2 +- paddle/ir/type_test.cc | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/paddle/ir/type_base.h b/paddle/ir/type_base.h index 47197b8227a502..f68d3e51bd3559 100644 --- a/paddle/ir/type_base.h +++ b/paddle/ir/type_base.h @@ -228,7 +228,7 @@ struct TypeManager { return val.type_id() == type_id(); \ } \ template \ - static concrete_type create(ir::IrContext *ctx, Args... args) { \ + static concrete_type get(ir::IrContext *ctx, Args... args) { \ return ir::TypeManager::template get(ctx, args...); \ } diff --git a/paddle/ir/type_test.cc b/paddle/ir/type_test.cc index 089976543e2fd6..504236344318df 100644 --- a/paddle/ir/type_test.cc +++ b/paddle/ir/type_test.cc @@ -118,16 +118,16 @@ class IntegerType : public ir::Type { using Type::Type; DECLARE_TYPE_UTILITY_FUNCTOR(IntegerType, IntegerTypeStorage); - static IntegerType get(ir::IrContext *context, - unsigned width, - unsigned signedness = 0); + // static IntegerType get(ir::IrContext *context, + // unsigned width, + // unsigned signedness = 0); }; -IntegerType IntegerType::get(ir::IrContext *context, - unsigned width, - unsigned signedness) { - return IntegerType::create(context, width, signedness); -} +// IntegerType IntegerType::get(ir::IrContext *context, +// unsigned width, +// unsigned signedness) { +// return IntegerType::get(context, width, signedness); +// } TEST(type_test, parameteric_type) { ir::IrContext *ctx = ir::IrContext::Instance(); From 85f3cd4255415e6ac5d96dc1279ecd6e5bbc071a Mon Sep 17 00:00:00 2001 From: zhangbo9674 Date: Thu, 23 Feb 2023 07:44:53 +0000 Subject: [PATCH 26/26] refine code by comment --- paddle/ir/CMakeLists.txt | 9 +++------ paddle/ir/tests/CMakeLists.txt | 1 + paddle/ir/{ => tests}/type_test.cc | 10 ---------- paddle/ir/type_base.h | 8 +++++++- 4 files changed, 11 insertions(+), 17 deletions(-) create mode 100644 paddle/ir/tests/CMakeLists.txt rename paddle/ir/{ => tests}/type_test.cc (91%) diff --git a/paddle/ir/CMakeLists.txt b/paddle/ir/CMakeLists.txt index f0285a7d4d195f..5e6af70335a107 100644 --- a/paddle/ir/CMakeLists.txt +++ b/paddle/ir/CMakeLists.txt @@ -5,12 +5,9 @@ endif() set(NEWIR_SOURCE_DIR "${PADDLE_SOURCE_DIR}/paddle/ir") set(NEWIR_BINARY_DIR "${PADDLE_BINARY_DIR}/paddle/ir") -file(GLOB IR_SRCS "*.cc") - -file(GLOB IR_TEST_SRCS "*_test.cc") +# ir tests +add_subdirectory(tests) -list(REMOVE_ITEM IR_SRCS ${IR_TEST_SRCS}) +file(GLOB IR_SRCS "*.cc") cc_library(new_ir SRCS ${IR_SRCS}) - -cc_test_old(type_test SRCS type_test.cc DEPS new_ir gtest) diff --git a/paddle/ir/tests/CMakeLists.txt b/paddle/ir/tests/CMakeLists.txt new file mode 100644 index 00000000000000..a1200519faff6f --- /dev/null +++ b/paddle/ir/tests/CMakeLists.txt @@ -0,0 +1 @@ +cc_test_old(type_test SRCS type_test.cc DEPS new_ir gtest) diff --git a/paddle/ir/type_test.cc b/paddle/ir/tests/type_test.cc similarity index 91% rename from paddle/ir/type_test.cc rename to paddle/ir/tests/type_test.cc index 504236344318df..85deb51b694d58 100644 --- a/paddle/ir/type_test.cc +++ b/paddle/ir/tests/type_test.cc @@ -117,18 +117,8 @@ class IntegerType : public ir::Type { public: using Type::Type; DECLARE_TYPE_UTILITY_FUNCTOR(IntegerType, IntegerTypeStorage); - - // static IntegerType get(ir::IrContext *context, - // unsigned width, - // unsigned signedness = 0); }; -// IntegerType IntegerType::get(ir::IrContext *context, -// unsigned width, -// unsigned signedness) { -// return IntegerType::get(context, width, signedness); -// } - TEST(type_test, parameteric_type) { ir::IrContext *ctx = ir::IrContext::Instance(); REGISTER_TYPE_2_IRCONTEXT(IntegerType, ctx); diff --git a/paddle/ir/type_base.h b/paddle/ir/type_base.h index f68d3e51bd3559..aa800498f6eadb 100644 --- a/paddle/ir/type_base.h +++ b/paddle/ir/type_base.h @@ -108,7 +108,7 @@ class TypeStorage : public StorageManager::StorageBase { abstract_type_ = const_cast(&abstract_type); } - AbstractType *abstract_type_{nullptr}; + AbstractType *abstract_type_{nullptr}; // not owned }; /// @@ -219,14 +219,18 @@ struct TypeManager { /// #define DECLARE_TYPE_UTILITY_FUNCTOR(concrete_type, storage_type) \ using StorageType = storage_type; \ + \ StorageType *storage() const { \ return static_cast(this->storage_); \ } \ + \ static ir::TypeId type_id() { return ir::TypeId::get(); } \ + \ template \ static bool classof(T val) { \ return val.type_id() == type_id(); \ } \ + \ template \ static concrete_type get(ir::IrContext *ctx, Args... args) { \ return ir::TypeManager::template get(ctx, args...); \ @@ -238,8 +242,10 @@ struct TypeManager { #define REGISTER_TYPE_2_IRCONTEXT(concrete_type, ir_context) \ ir::AbstractType *abstract_type_##concrete_type = new ir::AbstractType( \ std::move(ir::AbstractType::get(ir::TypeId::get()))); \ + \ ir_context->RegisterAbstractType(ir::TypeId::get(), \ abstract_type_##concrete_type); \ + \ ir::TypeManager::RegisterType(ir_context); } // namespace ir