add unused input vars check for OpWithKernel, test=develop (#21169)
* add unused input vars check for OpWithKernel, test=develop * remove unused vars in some ops, test=develop * fix batch_norm, test=develop * add white list, test=develop * add CI check for white list, test=develop * :ove white list to c++, test=develop * solve failure of CI, test=develop * add unittest for unused_var_check, test=develop * refine code, enable check in operator_test, test=develop * skip mkldnn, test=develop * extend white list, test=develop * refine condition of mkldnn, test=develop * fix paddle_build, test=develop * follow comments, test=develop * fix GetExpectedKernelType * add wiki ref to err_msg, test=develop * follow comment, test=developrevert-21172-masked_select_api
parent
664f958a02
commit
e0c9d856fb
@ -0,0 +1,130 @@
|
|||||||
|
/* Copyright (c) 2016 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 <gflags/gflags.h>
|
||||||
|
#include <glog/logging.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_set>
|
||||||
|
#include <vector>
|
||||||
|
#include "paddle/fluid/framework/operator.h"
|
||||||
|
#include "paddle/fluid/framework/unused_var_check.h"
|
||||||
|
#include "paddle/fluid/platform/enforce.h"
|
||||||
|
|
||||||
|
DEFINE_bool(enable_unused_var_check, false,
|
||||||
|
"Checking whether operator contains unused inputs, "
|
||||||
|
"especially for grad operator. It should be in unittest.");
|
||||||
|
|
||||||
|
const std::unordered_set<std::string> op_has_unsed_vars_white_list = {
|
||||||
|
"auc",
|
||||||
|
"batch_norm",
|
||||||
|
"batch_norm_grad",
|
||||||
|
"sync_batch_norm_grad",
|
||||||
|
"center_loss_grad",
|
||||||
|
"crop",
|
||||||
|
"cvm",
|
||||||
|
"cos_sim_grad",
|
||||||
|
"dgc_momentum",
|
||||||
|
"fake_quantize_range_abs_max",
|
||||||
|
"fill_zeros_like",
|
||||||
|
"fusion_seqpool_cvm_concat",
|
||||||
|
"reshape2_grad_grad",
|
||||||
|
"reshape2_grad",
|
||||||
|
"gru_grad",
|
||||||
|
"hierarchical_sigmoid_grad",
|
||||||
|
"nce_grad",
|
||||||
|
"roi_perspective_transform_grad",
|
||||||
|
"sequence_conv_grad",
|
||||||
|
"gru_unit_grad",
|
||||||
|
"affine_grid_grad",
|
||||||
|
"fill_any_like",
|
||||||
|
"precision_recall",
|
||||||
|
"unsqueeze_grad",
|
||||||
|
"kldiv_loss_grad",
|
||||||
|
"cvm_grad",
|
||||||
|
"stack_grad",
|
||||||
|
"warpctc_grad",
|
||||||
|
"sync_batch_norm",
|
||||||
|
"match_matrix_tensor_grad",
|
||||||
|
"ngraph_engine"};
|
||||||
|
|
||||||
|
namespace paddle {
|
||||||
|
namespace framework {
|
||||||
|
|
||||||
|
std::unordered_set<std::string> *GetThreadLocalUsedVarNameSet() {
|
||||||
|
thread_local std::unordered_set<std::string> used_var_name_set;
|
||||||
|
return &used_var_name_set;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LogVarUsageIfUnusedVarCheckEnabled(const std::string &name) {
|
||||||
|
if (FLAGS_enable_unused_var_check) {
|
||||||
|
VLOG(6) << "Variable used:" << name;
|
||||||
|
GetThreadLocalUsedVarNameSet()->insert(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckUnusedVar(const OperatorBase &op, const Scope &scope) {
|
||||||
|
// skip op in white list and it should be fixed in the future.
|
||||||
|
if (op_has_unsed_vars_white_list.count(op.Type()) != 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto *used_set = GetThreadLocalUsedVarNameSet();
|
||||||
|
std::vector<std::string> unsed_input_var_names;
|
||||||
|
auto &inferer = op.Info().NoNeedBufferVarsInferer();
|
||||||
|
std::unordered_set<std::string> no_need_buffer_ins = {};
|
||||||
|
if (inferer) {
|
||||||
|
no_need_buffer_ins = inferer(op.Inputs(), op.Outputs(), op.Attrs());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto &pair : op.Inputs()) {
|
||||||
|
// skip no need buffer vars declared
|
||||||
|
if (no_need_buffer_ins.count(pair.first) != 0) {
|
||||||
|
VLOG(6) << op.Type() << " " << pair.first;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (used_set->count(pair.first) == 0) {
|
||||||
|
for (auto &in_var_name : pair.second) {
|
||||||
|
auto *in_var = scope.FindVar(in_var_name);
|
||||||
|
if (in_var != nullptr && in_var->IsInitialized()) {
|
||||||
|
auto *tensor = &in_var->Get<LoDTensor>();
|
||||||
|
if (tensor != nullptr && tensor->IsInitialized()) {
|
||||||
|
unsed_input_var_names.emplace_back(pair.first);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!unsed_input_var_names.empty()) {
|
||||||
|
std::string err_msg = "Operator " + op.Type() + " has input(s) not uesed: ";
|
||||||
|
for (auto &in_var_name : unsed_input_var_names) {
|
||||||
|
err_msg += in_var_name;
|
||||||
|
err_msg += ", ";
|
||||||
|
}
|
||||||
|
err_msg +=
|
||||||
|
"please make sure it(they) is(are) needed. If not, remove it(them) "
|
||||||
|
"from inputs of the operator; if yes, register "
|
||||||
|
"NoNeedBufferVarsInference or add "
|
||||||
|
"the operator to "
|
||||||
|
"white list in unused_var_check.cc. See more details at "
|
||||||
|
"[https://github.com/PaddlePaddle/Paddle/wiki/"
|
||||||
|
"OP-Should-Not-Have-Unused-Input]";
|
||||||
|
PADDLE_ENFORCE_EQ(unsed_input_var_names.size(), 0,
|
||||||
|
platform::errors::PermissionDenied(
|
||||||
|
"Unused input variables check failed: %s", err_msg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace framework
|
||||||
|
} // namespace paddle
|
@ -0,0 +1,33 @@
|
|||||||
|
/* Copyright (c) 2016 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 <gflags/gflags.h>
|
||||||
|
#include <glog/logging.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_set>
|
||||||
|
#include "paddle/fluid/framework/operator.h"
|
||||||
|
|
||||||
|
namespace paddle {
|
||||||
|
namespace framework {
|
||||||
|
|
||||||
|
std::unordered_set<std::string>* GetThreadLocalUsedVarNameSet();
|
||||||
|
|
||||||
|
void LogVarUsageIfUnusedVarCheckEnabled(const std::string& name);
|
||||||
|
void CheckUnusedVar(const OperatorBase& op, const Scope& scope);
|
||||||
|
|
||||||
|
} // namespace framework
|
||||||
|
} // namespace paddle
|
Loading…
Reference in new issue