Skip to content

Commit 5988d0c

Browse files
authored
Merge pull request #11733 from reyoung/feature/refactor_op
Refactor Operator.cc, and clean code
2 parents 02e521e + 5e23a5e commit 5988d0c

File tree

6 files changed

+112
-60
lines changed

6 files changed

+112
-60
lines changed

doc/fluid/design/multi_devices/kernel_selection.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,10 @@ void OperatorWithKernel::Run(
7474
auto kernel_type_for_var = this->GetKernelTypeForVar(...);
7575
if (kernel_type_for_var.place_ != expected_kernel_key.place_) {
7676
auto* trans_var = new_scope.Var(var_name);
77-
auto* out = DataTransform(expected_kernel_key,
77+
auto* out = TransformData(expected_kernel_key,
7878
kernel_type_for_var,
7979
*tensor_in);
80-
CopyVariableWithTensor(...);
80+
SetTensorToVariable(...);
8181
}
8282
}
8383

paddle/fluid/framework/data_transform.cc

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,14 @@ limitations under the License. */
2121
namespace paddle {
2222
namespace framework {
2323

24-
static void PassTensorData(Tensor* from, Tensor* to) {
24+
static void PassTensorData(Tensor *from, Tensor *to) {
2525
to->ShareDataWith(*from);
2626
*from = Tensor();
2727
}
2828

29-
void DataTransform(const OpKernelType& expected_kernel_type,
30-
const OpKernelType& kernel_type_for_var,
31-
const Tensor& input_tensor, Tensor* output_tensor) {
29+
void TransformData(const OpKernelType &expected_kernel_type,
30+
const OpKernelType &kernel_type_for_var,
31+
const Tensor &input_tensor, Tensor *output_tensor) {
3232
bool transformed = false;
3333
Tensor in;
3434
in.ShareDataWith(input_tensor);
@@ -89,17 +89,17 @@ void DataTransform(const OpKernelType& expected_kernel_type,
8989
output_tensor->ShareDataWith(in);
9090
}
9191

92-
void CopyVariableWithTensor(const Variable& in_var, const Tensor& tensor,
93-
Variable* out_var) {
92+
void SetTensorToVariable(const Variable &in_var, const Tensor &tensor,
93+
Variable *out_var) {
9494
if (in_var.IsType<LoDTensor>()) {
95-
auto& in_lod_tensor = in_var.Get<LoDTensor>();
96-
auto* tran_lod_tensor = out_var->GetMutable<LoDTensor>();
95+
auto &in_lod_tensor = in_var.Get<LoDTensor>();
96+
auto *tran_lod_tensor = out_var->GetMutable<LoDTensor>();
9797
tran_lod_tensor->set_lod(in_lod_tensor.lod());
9898
tran_lod_tensor->set_layout(in_lod_tensor.layout());
9999
tran_lod_tensor->ShareDataWith(tensor);
100100
} else if (in_var.IsType<SelectedRows>()) {
101-
auto& in_selected_rows = in_var.Get<SelectedRows>();
102-
auto* trans_selected_rows = out_var->GetMutable<SelectedRows>();
101+
auto &in_selected_rows = in_var.Get<SelectedRows>();
102+
auto *trans_selected_rows = out_var->GetMutable<SelectedRows>();
103103
trans_selected_rows->set_height(in_selected_rows.height());
104104
trans_selected_rows->set_rows(in_selected_rows.rows());
105105
trans_selected_rows->mutable_value()->ShareDataWith(tensor);

paddle/fluid/framework/data_transform.h

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,15 @@ limitations under the License. */
3030
namespace paddle {
3131
namespace framework {
3232

33-
void DataTransform(const OpKernelType& expected_kernel_type,
34-
const OpKernelType& kernel_type_for_var,
35-
const Tensor& input_tensor, Tensor* out);
36-
37-
void CopyVariableWithTensor(const Variable& in_var, const Tensor& tensor,
38-
Variable* out_var);
33+
void TransformData(const OpKernelType &expected_kernel_type,
34+
const OpKernelType &kernel_type_for_var,
35+
const Tensor &input_tensor, Tensor *out);
36+
37+
/**
38+
* Set OutVar from InVar, except the tensor is shared with `tensor`
39+
*/
40+
void SetTensorToVariable(const Variable &in_var, const Tensor &tensor,
41+
Variable *out_var);
3942

4043
} // namespace framework
4144
} // namespace paddle

paddle/fluid/framework/op_kernel_type.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ inline bool NeedTransformLayout(const DataLayout& l, const DataLayout& r) {
9797
return ret;
9898
}
9999

100-
inline bool TransFromNeeded(const OpKernelType& l, const OpKernelType& r) {
100+
inline bool NeedTransform(const OpKernelType& l, const OpKernelType& r) {
101101
return (!platform::places_are_same_class(l.place_, r.place_)) ||
102102
(l.data_type_ != r.data_type_) ||
103103
NeedTransformLayout(l.data_layout_, r.data_layout_);

paddle/fluid/framework/operator.cc

Lines changed: 76 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -620,8 +620,6 @@ void OperatorWithKernel::RunImpl(const Scope& scope,
620620
"There are no kernels which are registered in the %s operator.", type_);
621621
}
622622

623-
ExecutionContext ctx(*this, scope, *dev_ctx);
624-
625623
OpKernelMap& kernels = kernels_iter->second;
626624

627625
// TODO(dzhwinter) : kernel fallback mechanism will be added when all the
@@ -631,7 +629,8 @@ void OperatorWithKernel::RunImpl(const Scope& scope,
631629
// Do selection
632630
// }
633631

634-
auto expected_kernel_key = this->GetExpectedKernelType(ctx);
632+
auto expected_kernel_key =
633+
this->GetExpectedKernelType(ExecutionContext(*this, scope, *dev_ctx));
635634
VLOG(3) << "expected_kernel_key:" << expected_kernel_key;
636635

637636
auto kernel_iter = kernels.find(expected_kernel_key);
@@ -640,63 +639,99 @@ void OperatorWithKernel::RunImpl(const Scope& scope,
640639
KernelTypeToString(expected_kernel_key));
641640
}
642641

643-
// do data transform
644-
Scope& new_scope = scope.NewScope();
642+
// do data transformScope &transfer_scope;
643+
std::vector<std::string> transfered_inplace_vars;
644+
auto* transfer_scope =
645+
TryTransferData(scope, expected_kernel_key, &transfered_inplace_vars);
645646

646-
std::vector<std::string> inplace_vars;
647-
for (auto& var_name_item : this->Inputs()) {
648-
for (auto& var_name : var_name_item.second) {
649-
auto* var = scope.FindVar(var_name);
650-
if (var && VarIsTensor(var)) {
651-
auto* tensor_in = GetTensorFromVar(var);
652-
if (tensor_in->IsInitialized()) {
653-
auto kernel_type_for_var = this->GetKernelTypeForVar(
654-
var_name_item.first, *tensor_in, expected_kernel_key);
655-
if (TransFromNeeded(kernel_type_for_var, expected_kernel_key)) {
656-
auto out_var_names = OutputVars(true);
657-
if (std::find(out_var_names.begin(), out_var_names.end(),
658-
var_name) != out_var_names.end()) {
659-
inplace_vars.push_back(var_name);
660-
}
661-
VLOG(3) << "Transform Variable " << var_name << " from "
662-
<< kernel_type_for_var << " to " << expected_kernel_key;
663-
auto* trans_var = new_scope.Var(var_name);
664-
std::shared_ptr<Tensor> out(new Tensor);
665-
DataTransform(expected_kernel_key, kernel_type_for_var, *tensor_in,
666-
out.get());
667-
CopyVariableWithTensor(*var, *(out.get()), trans_var);
668-
}
669-
}
670-
}
671-
}
647+
// exec scope is the scope that kernel actually executed on.
648+
const Scope& exec_scope =
649+
(transfer_scope == nullptr ? scope : *transfer_scope);
650+
651+
if (!(expected_kernel_key.place_ == dev_ctx->GetPlace())) {
652+
dev_ctx = pool.Get(expected_kernel_key.place_);
672653
}
673654

674-
auto* new_dev_ctx = pool.Get(expected_kernel_key.place_);
675-
kernel_iter->second->Compute(
676-
ExecutionContext(*this, new_scope, *new_dev_ctx));
655+
kernel_iter->second->Compute(ExecutionContext(*this, exec_scope, *dev_ctx));
677656

678-
for (auto& var_name : inplace_vars) {
679-
VLOG(3) << "share inplace var " + var_name + " back to it's original scope";
680-
auto* original_tensor = GetMutableTensorFromVar(scope.FindVar(var_name));
681-
auto* transformed_tensor = GetTensorFromVar(new_scope.FindVar(var_name));
682-
original_tensor->ShareDataWith(*transformed_tensor);
657+
if (!transfered_inplace_vars.empty()) {
658+
// there is inplace variable has been transfered.
659+
TransferInplaceVarsBack(scope, transfered_inplace_vars, *transfer_scope);
683660
}
684661

685662
/*For profiling/benchmark only*/
686663
if (FLAGS_benchmark) {
687-
new_dev_ctx->Wait();
664+
dev_ctx->Wait();
688665
}
689666

690667
if (FLAGS_check_nan_inf) {
691668
for (auto& vname : OutputVars(true)) {
692-
auto* var = new_scope.FindVar(vname);
669+
auto* var = exec_scope.FindVar(vname);
693670
if (var == nullptr) continue;
694671
if (var->IsType<framework::LoDTensor>()) {
695672
CheckTensorNANOrInf(vname, var->Get<framework::LoDTensor>());
696673
}
697674
}
698675
}
699676
}
677+
void OperatorWithKernel::TransferInplaceVarsBack(
678+
const Scope& scope, const std::vector<std::string>& inplace_vars,
679+
const Scope& transfer_scope) const {
680+
for (auto& var_name : inplace_vars) {
681+
VLOG(3) << "share inplace var " + var_name + " back to it's original scope";
682+
auto* original_tensor = GetMutableTensorFromVar(scope.FindVar(var_name));
683+
auto* transformed_tensor =
684+
GetTensorFromVar(transfer_scope.FindVar(var_name));
685+
original_tensor->ShareDataWith(*transformed_tensor);
686+
}
687+
}
688+
689+
Scope* OperatorWithKernel::TryTransferData(
690+
const Scope& scope, const OpKernelType& expected_kernel_key,
691+
std::vector<std::string>* transfered_inplace_vars) const {
692+
Scope* new_scope = nullptr;
693+
for (auto& var_name_item : Inputs()) {
694+
for (auto& var_name : var_name_item.second) {
695+
auto* var = scope.FindVar(var_name);
696+
// Only tensor can be tranfer to another device.
697+
if (var == nullptr || !VarIsTensor(var)) {
698+
continue;
699+
}
700+
701+
auto* tensor_in = GetTensorFromVar(var);
702+
if (!tensor_in->IsInitialized()) {
703+
continue;
704+
}
705+
706+
auto kernel_type_for_var = GetKernelTypeForVar(
707+
var_name_item.first, *tensor_in, expected_kernel_key);
708+
709+
if (!NeedTransform(kernel_type_for_var, expected_kernel_key)) {
710+
continue;
711+
}
712+
713+
auto out_var_names = OutputVars(true);
714+
if (std::find(out_var_names.begin(), out_var_names.end(), var_name) !=
715+
out_var_names.end()) {
716+
transfered_inplace_vars->emplace_back(var_name);
717+
}
718+
719+
VLOG(3) << "Transform Variable " << var_name << " from "
720+
<< kernel_type_for_var << " to " << expected_kernel_key;
721+
722+
if (new_scope == nullptr) {
723+
new_scope = &scope.NewScope();
724+
}
725+
726+
auto* trans_var = new_scope->Var(var_name);
727+
Tensor out;
728+
TransformData(expected_kernel_key, kernel_type_for_var, *tensor_in, &out);
729+
SetTensorToVariable(*var, out, trans_var);
730+
}
731+
}
732+
733+
return new_scope;
734+
}
700735

701736
proto::VarType::Type OperatorWithKernel::IndicateDataType(
702737
const ExecutionContext& ctx) const {

paddle/fluid/framework/operator.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,20 @@ class OperatorWithKernel : public OperatorBase {
384384
// same.
385385
proto::VarType::Type IndicateDataType(const ExecutionContext& ctx) const;
386386
void RunImpl(const Scope& scope, const platform::Place& place) const final;
387+
388+
/**
389+
* Transfer data from scope to a transfered scope. If there is no data need to
390+
* be tranfered, it returns nullptr.
391+
*
392+
* * transfered_inplace_vars is a output vector.
393+
*/
394+
Scope* TryTransferData(
395+
const Scope& scope, const OpKernelType& expected_kernel_key,
396+
std::vector<std::string>* transfered_inplace_vars) const;
397+
398+
void TransferInplaceVarsBack(const Scope& scope,
399+
const std::vector<std::string>& inplace_vars,
400+
const Scope& exec_scope) const;
387401
};
388402

389403
extern bool OpSupportGPU(const std::string& op_type);

0 commit comments

Comments
 (0)