mindspore2022/mindspore/ccsrc/transform/graph_runner.cc

214 lines
6.9 KiB
C++

/**
* Copyright 2019 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* Limitations under the License.
*/
#include "transform/graph_runner.h"
#include <algorithm>
#include <string>
#include <memory>
#include "utils/log_adapter.h"
#include "utils/config_manager.h"
#include "sys/time.h"
#include "utils/callbacks.h"
#include "utils/utils.h"
#include "./common.h"
#ifdef ENABLE_GE
#include "utils/callbacks_ge.h"
#endif
#ifdef NO_GE_CLIENT
namespace ge {
Session::Session(const std::map<std::string, std::string>& options) {
if (options.empty()) {
MS_LOG(ERROR) << "session input options is empty";
}
sessionId_ = 0;
}
Session::~Session() {}
} // namespace ge
#endif
namespace mindspore {
namespace transform {
std::shared_ptr<ge::Session> GraphRunner::NewSession(const SessionOptions& sess_options) {
std::shared_ptr<ge::Session> ret = std::make_shared<ge::Session>(sess_options);
if (ret == nullptr) {
MS_LOG(ERROR) << "Create GE session failed";
return nullptr;
}
MS_LOG(INFO) << "Create new GE session success";
return ret;
}
GraphRunner::GraphRunner(const GraphRunnerOptions& options)
: options_(options), graph_manager_(DfGraphManager::GetInstance()) {
if (ConfigManager::GetInstance().parallel_strategy() == ParallelStrategy::ONE_DEVICE) {
MS_LOG(INFO) << "ME run in ONE_DEVICE strategy mode";
}
if (options.sess_ptr != nullptr) {
sess_ = options.sess_ptr;
} else {
sess_ = NewSession(options.options);
if (sess_ == nullptr) {
MS_LOG(EXCEPTION) << "GraphRunner initialize failed!!";
return;
}
}
#if (defined ENABLE_GE)
// register the callback function
if (sess_->RegisterCallBackFunc(callbacks::kCheckPoint, callbacks::CheckpointSaveCallback) != ge::GRAPH_SUCCESS) {
MS_LOG(EXCEPTION) << "register callback failed!";
return;
}
if (sess_->RegisterCallBackFunc(callbacks::kSummary, callbacks::SummarySaveCallback) != ge::GRAPH_SUCCESS) {
MS_LOG(EXCEPTION) << "register summary callback failed!";
return;
}
#endif
std::vector<DfGraphWrapperPtr> wrappers = graph_manager_.GetAllGraphs();
if (wrappers.empty()) {
MS_LOG(INFO) << "The GraphManager is empty!!";
return;
}
#ifdef ENABLE_GE
for (auto& it : wrappers) {
std::set<string> saved_graph = graph_manager_.GetSavedGraphs();
auto iter_find = saved_graph.find(std::to_string(it->id_));
if (iter_find != saved_graph.end()) {
continue;
}
MS_LOG(INFO) << "Add the graph " << (*it).name_ << " to GE, it's id is: " << (*it).id_;
graph_manager_.AddSavedGraphs(std::to_string(it->id_));
(void)sess_->AddGraph(it->id_, *(it->graph_ptr_), it->options_);
}
#endif
}
Status GraphRunner::RunGraph(const RunOptions& options, const std::vector<GeTensorPtr>& inputs,
std::vector<GeTensorPtr>* outputs) {
std::string name = options.name;
if (name.empty()) {
MS_LOG(ERROR) << "The graph name is null";
return Status::INVALID_ARGUMENT;
}
DfGraphWrapperPtr wrap_ptr = graph_manager_.GetGraphByName(name);
if (wrap_ptr == nullptr) {
MS_LOG(ERROR) << "Get graph form DfGraphManager failed!";
return Status::NOT_FOUND;
}
if (wrap_ptr->graph_ptr_ == nullptr) {
MS_LOG(WARNING) << "The graph is null";
return Status::NOT_FOUND;
}
// call ge::RunGraph() to exec a graph;
std::vector<GeTensor> ge_inputs;
std::vector<GeTensor> ge_outputs;
(void)std::transform(inputs.begin(), inputs.end(), std::back_inserter(ge_inputs),
[](const GeTensorPtr& i) { return *i; });
MS_LOG(INFO) << "Run the graph in GE with " << ge_inputs.size() << " inputs";
struct timeval start_time, end_time;
(void)gettimeofday(&start_time, nullptr);
#ifdef ENABLE_GE
if (sess_ == nullptr) {
MS_LOG(ERROR) << "The GE session is null, can't run the graph!";
return Status::FAILED;
}
// The information of some nodes could be changed after fusion in some cases
// Therefore a graph needs to be rebuilt in above situation
if (sess_->IsGraphNeedRebuild(wrap_ptr->id_)) {
sess_->RemoveGraph(wrap_ptr->id_);
sess_->AddGraph(wrap_ptr->id_, *(wrap_ptr->graph_ptr_), wrap_ptr->options_);
}
ge::Status ret = sess_->RunGraph(wrap_ptr->id_, ge_inputs, ge_outputs);
if (ret != ge::GRAPH_SUCCESS) {
MS_LOG(ERROR) << "Call GE RunGraph Failed, ret is: " << ret;
return Status::FAILED;
}
#else
ge_outputs.swap(ge_inputs);
#endif
(void)gettimeofday(&end_time, nullptr);
const uint64_t kUSecondInSecond = 1000000;
uint64_t cost = kUSecondInSecond * static_cast<uint64_t>(end_time.tv_sec - start_time.tv_sec);
cost += static_cast<uint64_t>(end_time.tv_usec - start_time.tv_usec);
MS_LOG(INFO) << "Call GE RunGraph Success in " << cost << " us, the GE outputs num is: " << ge_outputs.size();
(void)std::transform(ge_outputs.begin(), ge_outputs.end(), std::back_inserter(*outputs),
[](const GeTensor& ge_tensor) { return std::make_shared<GeTensor>(ge_tensor); });
return Status::SUCCESS;
}
Status GraphRunner::RunGraph(const RunOptions& options, const std::vector<MeTensorPtr>& inputs,
std::vector<MeTensorPtr>* const outputs) {
std::vector<GeTensorPtr> ge_inputs;
for (auto it : inputs) {
MS_LOG(INFO) << "inputs tensor's data size is: " << (*it).DataSize();
auto shape = (*it).shape();
std::string shape_str;
for (const auto& elem : shape) {
shape_str += std::to_string(elem);
shape_str += " ";
}
MS_LOG(INFO) << "inputs tensor's shape is: { " << shape_str << "}";
auto ge_tensor_ptr = TransformUtil::ConvertTensor(it, kOpFormat_NCHW);
if (ge_tensor_ptr != nullptr) {
ge_inputs.emplace_back(ge_tensor_ptr);
} else {
MS_LOG(INFO) << "Convert input Me tensor to Ge tensor failed. Abort this graph";
return Status::FAILED;
}
}
std::vector<GeTensorPtr> ge_outputs;
Status ret;
{
// Release GIL before calling into (potentially long-running) C++ code
py::gil_scoped_release release;
ret = RunGraph(options, ge_inputs, &ge_outputs);
}
if (ret != Status::SUCCESS) {
return ret;
} else {
// conver GeTensor to MeTensor
for (auto& it : ge_outputs) {
auto tensor = TransformUtil::ConvertGeTensor(it);
if (tensor != nullptr) {
outputs->emplace_back(tensor);
}
}
MS_LOG(INFO) << "Return Me tensor outputs num is: " << outputs->size();
return Status::SUCCESS;
}
}
} // namespace transform
} // namespace mindspore