diff --git a/cmake/version.cmake b/cmake/version.cmake index dd57d4ab9969ce530f93ca1694350b1a26b5b543..417c6d6739b3d6c7ccf62275ae97a911872b593a 100644 --- a/cmake/version.cmake +++ b/cmake/version.cmake @@ -59,5 +59,13 @@ while ("${PADDLE_VERSION}" STREQUAL "") endif() endwhile() +string(REPLACE "." ";" PADDLE_VER_LIST ${PADDLE_VERSION}) +list(GET PADDLE_VER_LIST 0 PADDLE_MAJOR_VER) +list(GET PADDLE_VER_LIST 1 PADDLE_MINOR_VER) +list(GET PADDLE_VER_LIST 2 PADDLE_PATCH_VER) +math(EXPR PADDLE_VERSION_INTEGER "${PADDLE_MAJOR_VER} * 1000000 + + ${PADDLE_MINOR_VER} * 1000 + ${PADDLE_PATCH_VER}") + add_definitions(-DPADDLE_VERSION=${PADDLE_VERSION}) +add_definitions(-DPADDLE_VERSION_INTEGER=${PADDLE_VERSION_INTEGER}) message(STATUS "Paddle version is ${PADDLE_VERSION}") diff --git a/paddle/fluid/framework/CMakeLists.txt b/paddle/fluid/framework/CMakeLists.txt index 51efe60c90121e3e3c50a31b5a3e8972ee5a0202..86de21d65a19715cc895a174df85d74c713219a3 100644 --- a/paddle/fluid/framework/CMakeLists.txt +++ b/paddle/fluid/framework/CMakeLists.txt @@ -224,7 +224,7 @@ cc_library(dlpack_tensor SRCS dlpack_tensor.cc DEPS tensor dlpack) cc_test(dlpack_tensor_test SRCS dlpack_tensor_test.cc DEPS dlpack_tensor glog) cc_library(op_compatible_info SRCS op_compatible_info DEPS string_helper) -cc_test(op_compatible_info_test SRCS op_compatible_info_test.cc DEPS op_compatible_info string_helper glog) +cc_test(op_compatible_info_test SRCS op_compatible_info_test.cc DEPS op_compatible_info proto_desc string_helper glog) # Get the current working branch execute_process( diff --git a/paddle/fluid/framework/framework.proto b/paddle/fluid/framework/framework.proto index 2c1296d5ca630b434424573289f2e164c2967813..5adf2a18b98c2a2d3e2f6e8f7dd5688150674dc6 100644 --- a/paddle/fluid/framework/framework.proto +++ b/paddle/fluid/framework/framework.proto @@ -179,13 +179,39 @@ message BlockDesc { optional int32 forward_block_idx = 5 [ default = -1 ]; } +// CompatibleInfo is used to determine if a feature is compatible and +// provides the information. +message CompatibleInfo { + enum Type { + COMPATIBLE = 0; + DEFINITELY_NOT = 1; + POSSIBLE = 2; + BUG_FIX = 3; + PRECISION_CHANGE = 4; + } + required string version = 1; + required Type type = 2; +} + +// In some cases, Paddle Fluid may perform operator definition iterations, +// and the operator uses OpCompatibleMap for compatibility testing. +message OpCompatibleMap { + message OpCompatiblePair { + required string op_name = 1; + required CompatibleInfo compatible_info = 2; + } + repeated OpCompatiblePair pair = 1; + optional string default_required_version = 2; +} + // Please refer to // https://github.com/PaddlePaddle/Paddle/blob/develop/doc/design/program.md // for more details. // TODO(panyx0718): A model can have multiple programs. Need a // way to distinguish them. Maybe ID or name? message ProgramDesc { + reserved 2; // For backward compatibility. repeated BlockDesc blocks = 1; - - optional Version version = 2; + optional Version version = 4; + optional OpCompatibleMap op_compatible_map = 3; } diff --git a/paddle/fluid/framework/op_compatible_info.cc b/paddle/fluid/framework/op_compatible_info.cc index bf2f85e6f817100fb405f14ceafcffebd63e462e..627e807fc8882600888bb00862860c01715a34bd 100644 --- a/paddle/fluid/framework/op_compatible_info.cc +++ b/paddle/fluid/framework/op_compatible_info.cc @@ -14,6 +14,7 @@ #include "paddle/fluid/framework/op_compatible_info.h" #include +#include #include #include "paddle/fluid/platform/enforce.h" #include "paddle/fluid/string/string_helper.h" @@ -72,7 +73,7 @@ void OpCompatibleMap::InitOpCompatibleMap() { op_compatible_map_["layer_norm"] = {"1.6.0", OpCompatibleType::bug_fix}; } -CompatibleInfo OpCompatibleMap::GetOpCompatibleInfo(std::string op_name) { +CompatibleInfo OpCompatibleMap::GetOpCompatibleInfo(std::string op_name) const { auto it = op_compatible_map_.find(op_name); if (it != op_compatible_map_.end()) { return it->second; @@ -82,7 +83,7 @@ CompatibleInfo OpCompatibleMap::GetOpCompatibleInfo(std::string op_name) { } OpCompatibleType OpCompatibleMap::IsRequireMiniVersion( - std::string op_name, std::string str_current_version) { + std::string op_name, std::string str_current_version) const { auto it = op_compatible_map_.find(op_name); if (it != op_compatible_map_.end()) { if (CompareVersion(str_current_version, it->second.required_version_)) { @@ -100,5 +101,40 @@ OpCompatibleType OpCompatibleMap::IsRequireMiniVersion( } } +bool OpCompatibleMap::ConvertToProto(proto::OpCompatibleMap* desc) const { + desc->Clear(); + desc->set_default_required_version(default_required_version_); + for (auto pair : op_compatible_map_) { + const CompatibleInfo& info = pair.second; + auto* pair_desc = desc->add_pair(); + pair_desc->set_op_name(pair.first); + auto* info_desc = pair_desc->mutable_compatible_info(); + info_desc->set_version(info.required_version_); + info_desc->set_type( + static_cast(info.compatible_type_)); + } + return true; +} + +bool OpCompatibleMap::ReadFromProto(const proto::OpCompatibleMap& desc) { + std::string version = desc.default_required_version(); + if (version.empty()) { + LOG(INFO) << "The default operator required version is missing." + " Please update the model version."; + return false; + } + op_compatible_map_.clear(); + default_required_version_ = desc.default_required_version(); + for (int i = 0; i < desc.pair_size(); ++i) { + const auto& pair_desc = desc.pair(i); + auto info_desc = pair_desc.compatible_info(); + CompatibleInfo info(info_desc.version(), + static_cast(info_desc.type())); + std::pair pair(pair_desc.op_name(), info); + op_compatible_map_.insert(pair); + } + return true; +} + } // namespace framework } // namespace paddle diff --git a/paddle/fluid/framework/op_compatible_info.h b/paddle/fluid/framework/op_compatible_info.h index 03d47c82d9c75ec330bb22a2bb48db9acfe93f9a..08b5734b5bfe33d4269c06d639448eefd26fcb06 100644 --- a/paddle/fluid/framework/op_compatible_info.h +++ b/paddle/fluid/framework/op_compatible_info.h @@ -14,6 +14,7 @@ #include #include +#include "paddle/fluid/framework/program_desc.h" #pragma once @@ -44,24 +45,28 @@ class OpCompatibleMap { OpCompatibleMap() : default_required_version_("1.5.0") {} void InitOpCompatibleMap(); - CompatibleInfo GetOpCompatibleInfo(std::string op_name); + CompatibleInfo GetOpCompatibleInfo(std::string op_name) const; /* IsRequireMiniVersion * return type OpCompatibleType */ OpCompatibleType IsRequireMiniVersion(std::string op_name, - std::string current_version); + std::string current_version) const; - void SerializeToStr(std::string& str) {} /* NOLINT */ - void UnSerialize(const std::string& str) {} + // Convert the entire OpCompatibleMap to Proto, which can be serialized + // to the model file as part of the ProgramDesc. + bool ConvertToProto(proto::OpCompatibleMap* desc) const; - const std::string& GetDefaultRequiredVersion() { + // Read and reset the entire object from proto, which can be read from + // the model file as part of the program. + bool ReadFromProto(const proto::OpCompatibleMap& desc); + + const std::string& GetDefaultRequiredVersion() const { return default_required_version_; } private: std::map op_compatible_map_; - std::string default_required_version_; }; diff --git a/paddle/fluid/framework/op_compatible_info_test.cc b/paddle/fluid/framework/op_compatible_info_test.cc index 2a50a8302b384694cf6fbbdfeb1d8c5ee846863a..43959c8b2abd868a705b5e21950cdca2faaebe5c 100644 --- a/paddle/fluid/framework/op_compatible_info_test.cc +++ b/paddle/fluid/framework/op_compatible_info_test.cc @@ -15,21 +15,31 @@ #include "paddle/fluid/framework/op_compatible_info.h" #include #include "gtest/gtest.h" +#include "paddle/fluid/framework/program_desc.h" #include "paddle/fluid/platform/macros.h" namespace paddle { namespace framework { + TEST(test_op_compatible_info, test_op_compatible) { auto comp_map = OpCompatibleMap(); comp_map.InitOpCompatibleMap(); - auto default_req_version = comp_map.GetDefaultRequiredVersion(); - - auto seq_pad = comp_map.GetOpCompatibleInfo("sequence_pad"); - auto reshape = comp_map.GetOpCompatibleInfo("reshape"); - auto layer_norm = comp_map.GetOpCompatibleInfo("layer_norm"); + // Ensure save-load consistency. + auto program_desc = ProgramDesc(); + proto::OpCompatibleMap* proto_map = program_desc.OpCompatibleMap(); + comp_map.ConvertToProto(proto_map); + comp_map.ReadFromProto(*proto_map); - auto deafult_info = comp_map.GetOpCompatibleInfo("layer_xx"); + ASSERT_NE(comp_map.GetDefaultRequiredVersion(), std::string()); + ASSERT_NE(comp_map.GetOpCompatibleInfo("sequence_pad").required_version_, + std::string()); + ASSERT_NE(comp_map.GetOpCompatibleInfo("reshape").required_version_, + std::string()); + ASSERT_NE(comp_map.GetOpCompatibleInfo("layer_norm").required_version_, + std::string()); + ASSERT_NE(comp_map.GetOpCompatibleInfo("layer_xx").required_version_, + std::string()); auto comp_1 = comp_map.IsRequireMiniVersion("sequence_pad", "1.5.0"); ASSERT_EQ(comp_1, OpCompatibleType::DEFIN_NOT); @@ -54,5 +64,6 @@ TEST(test_op_compatible_info, test_op_compatible) { ASSERT_EQ(comp_map.IsRequireMiniVersion("slice", "1.6.0"), OpCompatibleType::compatible); } + } // namespace framework } // namespace paddle diff --git a/paddle/fluid/framework/program_desc.cc b/paddle/fluid/framework/program_desc.cc index 4b9667113bc7918c1323f0213213a6ffdb7eed8e..37349631a699ca62ee918b3d3d9f16ac6f6e5fd1 100644 --- a/paddle/fluid/framework/program_desc.cc +++ b/paddle/fluid/framework/program_desc.cc @@ -39,10 +39,18 @@ proto::ProgramDesc *ProgramDesc::Proto() { return &desc_; } +proto::OpCompatibleMap *ProgramDesc::OpCompatibleMap() { + return desc_.mutable_op_compatible_map(); +} + int64_t ProgramDesc::Version() const { return desc_.version().version(); } +void ProgramDesc::SetVersion(const int64_t version) { + desc_.mutable_version()->set_version(version); +} + ProgramDesc::ProgramDesc() { - desc_.mutable_version()->set_version(kCurProgramVersion); + SetVersion(kCurProgramVersion); auto *block = desc_.mutable_blocks()->Add(); block->set_idx(kRootBlockIndex); block->set_parent_idx(kNoneBlockIndex); diff --git a/paddle/fluid/framework/program_desc.h b/paddle/fluid/framework/program_desc.h index 2ec0e9d7a0969d44f88c7407bfb8cd4646530147..d5e9c755f1298bcd31ea9093b5912a46133d0228 100644 --- a/paddle/fluid/framework/program_desc.h +++ b/paddle/fluid/framework/program_desc.h @@ -57,8 +57,12 @@ class ProgramDesc { proto::ProgramDesc *Proto(); + proto::OpCompatibleMap *OpCompatibleMap(); + int64_t Version() const; + void SetVersion(const int64_t version); + // The output variable of feed_op is referenced as feed_target. // This function is used to collect the output variable's name of all // feed_ops. diff --git a/paddle/fluid/framework/version.cc b/paddle/fluid/framework/version.cc index 81c0392bf3cc7378cec06a9de3ae81f2b221ecec..7ba00f52e67f5431bb0dc70dbd5b743ca611fff8 100644 --- a/paddle/fluid/framework/version.cc +++ b/paddle/fluid/framework/version.cc @@ -14,23 +14,38 @@ limitations under the License. */ #include "paddle/fluid/framework/version.h" #include +#include namespace paddle { namespace framework { + bool IsProgramVersionSupported(int64_t version) { - static int num_supported = - sizeof(kSupportedProgramVersion) / sizeof(kSupportedProgramVersion[0]); - return std::find(kSupportedProgramVersion, - kSupportedProgramVersion + num_supported, - version) != kSupportedProgramVersion + num_supported; + /* So far, all old versions of Tensor are supported in the + * new version. The compatibility judgment cannot be made only + * by the version number. Please do not use this interface, + * it may be discarded because backward compatibility. + */ + return true; } bool IsTensorVersionSupported(uint32_t version) { - static int num_supported = - sizeof(kSupportedTensorVersion) / sizeof(kSupportedTensorVersion[0]); - return std::find(kSupportedTensorVersion, - kSupportedTensorVersion + num_supported, - version) != kSupportedTensorVersion + num_supported; + /* So far, all old versions of Tensor are supported in the + * new version. The compatibility judgment cannot be made only + * by the version number. Please do not use this interface, + * it may be discarded because backward compatibility. + */ + return true; +} + +std::string DumpVersion(const int64_t version) { + std::stringstream buffer; + const int major = version / MAJOR_COEFF; + const int minor = (version - major * MAJOR_COEFF) / MINOR_COEFF; + const int patch = + (version - major * MAJOR_COEFF - minor * MINOR_COEFF) / PATCH_COEFF; + buffer << major << "." << minor << "." << patch; + return buffer.str(); } + } // namespace framework } // namespace paddle diff --git a/paddle/fluid/framework/version.h b/paddle/fluid/framework/version.h index 9945bc58c69df8456ff3d1aa0c777970bdbdbf98..1bb627775942a8dd9a93148c9faaa0a1998dbcc3 100644 --- a/paddle/fluid/framework/version.h +++ b/paddle/fluid/framework/version.h @@ -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 - #pragma once +#include +#include + namespace paddle { namespace framework { @@ -24,8 +25,16 @@ namespace framework { // be supported by the current codes. Otherwise, it's a compatibility // bug. +constexpr int MAJOR_COEFF = 1000000; +constexpr int MINOR_COEFF = 1000; +constexpr int PATCH_COEFF = 1; + // The program version the current codes generate. +#ifdef PADDLE_VERSION_INTEGER +constexpr int64_t kCurProgramVersion = PADDLE_VERSION_INTEGER; +#else constexpr int64_t kCurProgramVersion = 0; +#endif // The program version that was generated by previous or current codes // and supported by current codes. @@ -39,9 +48,12 @@ constexpr uint32_t kCurTensorVersion = 0; // and supported by current codes. constexpr uint32_t kSupportedTensorVersion[] = {0}; +// WARNING: DO NOT use this interface, it may be discarded. bool IsProgramVersionSupported(int64_t version); - +// WARNING: DO NOT use this interface, it may be discarded. bool IsTensorVersionSupported(uint32_t version); +std::string DumpVersion(const int64_t version); + } // namespace framework } // namespace paddle diff --git a/paddle/fluid/framework/version_test.cc b/paddle/fluid/framework/version_test.cc index e8c5f256000522af976bbf487741a586f1abc439..ec5a340ee6ef3bb7b3360640db8fe5b75840a63f 100644 --- a/paddle/fluid/framework/version_test.cc +++ b/paddle/fluid/framework/version_test.cc @@ -19,12 +19,12 @@ namespace paddle { namespace framework { TEST(Version, Basic) { EXPECT_TRUE(IsProgramVersionSupported(0)); - EXPECT_FALSE(IsProgramVersionSupported(1)); - EXPECT_FALSE(IsProgramVersionSupported(-1)); + EXPECT_TRUE(IsProgramVersionSupported(1)); + EXPECT_TRUE(IsProgramVersionSupported(-1)); EXPECT_TRUE(IsTensorVersionSupported(0)); - EXPECT_FALSE(IsTensorVersionSupported(1)); - EXPECT_FALSE(IsTensorVersionSupported(-1)); + EXPECT_TRUE(IsTensorVersionSupported(1)); + EXPECT_TRUE(IsTensorVersionSupported(-1)); } } // namespace framework } // namespace paddle diff --git a/paddle/fluid/inference/api/CMakeLists.txt b/paddle/fluid/inference/api/CMakeLists.txt index 344d12dd0b12a0378f68b3de91c84ca11253c502..9aaea73f25106b29acf2000cf3c5c60f567b1e89 100755 --- a/paddle/fluid/inference/api/CMakeLists.txt +++ b/paddle/fluid/inference/api/CMakeLists.txt @@ -50,7 +50,7 @@ else(WITH_NGRAPH) cc_library(paddle_pass_builder SRCS paddle_pass_builder.cc) endif(WITH_NGRAPH) cc_library(analysis_predictor SRCS analysis_predictor.cc ${mkldnn_quantizer_src} DEPS paddle_inference_api zero_copy_tensor - reset_tensor_array analysis_config paddle_pass_builder ir_pass_manager ${inference_deps}) + reset_tensor_array analysis_config paddle_pass_builder ir_pass_manager op_compatible_info ${inference_deps}) cc_library(paddle_inference_api SRCS api.cc api_impl.cc helper.cc DEPS lod_tensor scope paddle_pass_builder reset_tensor_array analysis_config paddle_pass_builder zero_copy_tensor diff --git a/paddle/fluid/inference/api/analysis_predictor.cc b/paddle/fluid/inference/api/analysis_predictor.cc index d47bde32de65d7db60f7dd308a67f9e443289bb5..cc841640370ac8cb37028332438f90fc315c0c94 100644 --- a/paddle/fluid/inference/api/analysis_predictor.cc +++ b/paddle/fluid/inference/api/analysis_predictor.cc @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -27,6 +28,7 @@ #include "paddle/fluid/framework/naive_executor.h" #include "paddle/fluid/framework/scope.h" #include "paddle/fluid/framework/var_type_traits.h" +#include "paddle/fluid/framework/version.h" #include "paddle/fluid/inference/analysis/helper.h" #include "paddle/fluid/inference/analysis/passes/memory_optimize_pass.h" #include "paddle/fluid/inference/api/helper.h" @@ -142,6 +144,10 @@ bool AnalysisPredictor::PrepareProgram( // If config_.ir_optim() is False, parameters is loaded in LoadParameters(), // still need to create other persistable variables. // So in both case, create persistable variables at first. + if (!CheckOperatorCompatible()) { + LOG(WARNING) << "WARNING: Results may be DIFF! " + "Using same versions between model and lib."; + } executor_->CreateVariables(*inference_program_, 0, true, sub_scope_); // if enable_ir_optim_ is false, @@ -823,6 +829,37 @@ std::string AnalysisPredictor::GetSerializedProgram() const { return inference_program_->Proto()->SerializeAsString(); } +bool AnalysisPredictor::CheckOperatorCompatible() { + if (!inference_program_) { + LOG(FATAL) << "Inference program version check failed because the program " + "does not exist."; + return false; + } + bool res = true; + op_compatible_map_.ReadFromProto(*inference_program_->OpCompatibleMap()); + const auto &version = framework::DumpVersion(framework::kCurProgramVersion); + LOG(INFO) << "MODEL VERSION: " + << framework::DumpVersion(inference_program_->Version()); + LOG(INFO) << "PREDICTOR VERSION: " << version; + std::set op_types; + for (size_t i = 0; i < inference_program_->Size(); ++i) { + const auto &block = inference_program_->Block(i); + for (const auto *op : block.AllOps()) { + op_types.insert(op->Type()); + } + } + for (const auto type : op_types) { + auto compatible_type = + op_compatible_map_.IsRequireMiniVersion(type, version); + if (compatible_type != framework::OpCompatibleType::compatible) { + LOG(WARNING) << " - Version incompatible (" + << static_cast(compatible_type) << ") " << type; + res = false; + } + } + return res; +} + // Add SaveOptimModel void AnalysisPredictor::SaveOptimModel(const std::string &dir) { // save model diff --git a/paddle/fluid/inference/api/analysis_predictor.h b/paddle/fluid/inference/api/analysis_predictor.h index 33a2e62303af776f608c3d9e272e9cd73b0d12b4..3f192bc0545a2678e76a4bbfb1b24cad6fcae37f 100644 --- a/paddle/fluid/inference/api/analysis_predictor.h +++ b/paddle/fluid/inference/api/analysis_predictor.h @@ -19,6 +19,7 @@ #include #include #include "paddle/fluid/framework/naive_executor.h" +#include "paddle/fluid/framework/op_compatible_info.h" #include "paddle/fluid/inference/analysis/analyzer.h" #include "paddle/fluid/inference/api/api_impl.h" #include "paddle/fluid/inference/api/details/reset_tensor_array.h" @@ -111,6 +112,7 @@ class AnalysisPredictor : public PaddlePredictor { // AnalysisPredictor::ZeroRun() now. void MkldnnPreSet(const std::vector &inputs); void MkldnnPostReset(); + bool CheckOperatorCompatible(); #if PADDLE_WITH_TENSORRT // When we use Paddle-TRT INT8 engine, we need to generate calibration table @@ -143,6 +145,7 @@ class AnalysisPredictor : public PaddlePredictor { std::shared_ptr scope_; framework::Scope *sub_scope_{nullptr}; std::shared_ptr inference_program_; + framework::OpCompatibleMap op_compatible_map_; std::vector feeds_; std::map feed_names_; // Sorted according to the idx. diff --git a/paddle/fluid/inference/api/analysis_predictor_tester.cc b/paddle/fluid/inference/api/analysis_predictor_tester.cc index e990b2c7736ae51a1ac2ba2fd15362012288b9bb..0c1ea3e3c7249c145a9dc2a68f7336c9d5339561 100644 --- a/paddle/fluid/inference/api/analysis_predictor_tester.cc +++ b/paddle/fluid/inference/api/analysis_predictor_tester.cc @@ -71,6 +71,9 @@ TEST(AnalysisPredictor, analysis_on) { auto _predictor = CreatePaddlePredictor(config); auto* predictor = static_cast(_predictor.get()); + if (predictor->inference_program_->Version() == 0) { + ASSERT_FALSE(predictor->CheckOperatorCompatible()); + } ASSERT_TRUE(predictor->scope_); ASSERT_TRUE(predictor->sub_scope_); ASSERT_EQ(predictor->scope_->parent(), nullptr); diff --git a/paddle/fluid/pybind/protobuf.cc b/paddle/fluid/pybind/protobuf.cc index 7c6e2f2414d16830d8f87a3c5571f23cee4e4b9d..68d01eb4a2cf55bdf64b15b3a1961f57cbdb9eae 100644 --- a/paddle/fluid/pybind/protobuf.cc +++ b/paddle/fluid/pybind/protobuf.cc @@ -22,6 +22,7 @@ limitations under the License. */ #include "paddle/fluid/framework/op_desc.h" #include "paddle/fluid/framework/program_desc.h" #include "paddle/fluid/framework/var_desc.h" +#include "paddle/fluid/framework/version.h" #include "paddle/fluid/pybind/pybind_boost_headers.h" @@ -69,9 +70,13 @@ void BindProgramDesc(pybind11::module *m) { "Fail to parse ProgramDesc from string. This could " "be a bug of Paddle."); }) - .def("_version", [](pd::ProgramDesc &self) -> int64_t { - return self.Proto()->version().version(); - }); + .def("_set_version", + [](pd::ProgramDesc &self, int64_t version) { + return self.SetVersion(version); + }, + pybind11::arg("version") = pd::kCurProgramVersion) + .def("_version", + [](pd::ProgramDesc &self) -> int64_t { return self.Version(); }); } void BindBlockDesc(pybind11::module *m) { diff --git a/paddle/fluid/pybind/pybind.cc b/paddle/fluid/pybind/pybind.cc index 4c6174f25ba4570abb3ca8dfc73957ea4fbead8c..d96d59edfb03212e698b8ed47e17342b2013a6f3 100644 --- a/paddle/fluid/pybind/pybind.cc +++ b/paddle/fluid/pybind/pybind.cc @@ -32,6 +32,7 @@ limitations under the License. */ #include "paddle/fluid/framework/lod_rank_table.h" #include "paddle/fluid/framework/lod_tensor.h" #include "paddle/fluid/framework/lod_tensor_array.h" +#include "paddle/fluid/framework/op_compatible_info.h" #include "paddle/fluid/framework/op_info.h" #include "paddle/fluid/framework/op_registry.h" #include "paddle/fluid/framework/parallel_executor.h" @@ -171,6 +172,12 @@ PYBIND11_MODULE(core_noavx, m) { m.def("set_num_threads", &platform::SetNumThreads); + m.def("save_op_compatible_info", [](framework::ProgramDesc &desc) { + framework::OpCompatibleMap op_compatible_map; + op_compatible_map.InitOpCompatibleMap(); + return op_compatible_map.ConvertToProto(desc.OpCompatibleMap()); + }); + m.def( "_append_python_callable_object_and_return_id", [](py::object py_obj) -> size_t { diff --git a/python/paddle/fluid/io.py b/python/paddle/fluid/io.py index 7d864cfbb433db79f508c9760d224fefb853f912..0866320a1cdc09f84fae7e63febaba620c845184 100644 --- a/python/paddle/fluid/io.py +++ b/python/paddle/fluid/io.py @@ -1103,6 +1103,8 @@ def save_inference_model(dirname, prepend_feed_ops(main_program, feeded_var_names) append_fetch_ops(main_program, fetch_var_names) + main_program.desc._set_version() + paddle.fluid.core.save_op_compatible_info(main_program.desc) with open(model_basename, "wb") as f: f.write(main_program.desc.serialize_to_string()) else: