Skip to content

Commit 2ee3202

Browse files
authored
Add dependency for read op in standalone executor (#44362)
* Add dependency for read op in standalone executor * Fix CI errors * Add UT * add_dependency -> dependency_utils * Fix CI errors
1 parent 3ed5328 commit 2ee3202

File tree

8 files changed

+199
-48
lines changed

8 files changed

+199
-48
lines changed

paddle/fluid/framework/new_executor/CMakeLists.txt

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
add_subdirectory(workqueue)
21
add_subdirectory(garbage_collector)
2+
add_subdirectory(interpreter)
3+
add_subdirectory(workqueue)
34

45
set(STANDALONE_EXECUTOR_SRCS
56
data_transfer.cc
@@ -11,8 +12,9 @@ set(STANDALONE_EXECUTOR_SRCS
1112
standalone_executor.cc)
1213

1314
set(STANDALONE_EXECUTOR_DEPS
14-
op_registry
15+
dependency_utils
1516
device_context
17+
op_registry
1618
scope
1719
framework_proto
1820
data_feed_proto
@@ -36,9 +38,6 @@ set(STANDALONE_EXECUTOR_DEPS
3638
enforce
3739
scope
3840
glog
39-
enforce
40-
glog
41-
scope
4241
workqueue
4342
interpretercore_event_garbage_collector
4443
${DEVICE_EVENT_LIBS}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
cc_library(
2+
dependency_utils
3+
SRCS dependency_utils.cc
4+
DEPS operator)
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "paddle/fluid/framework/new_executor/interpreter/dependency_utils.h"
16+
17+
#include <queue>
18+
19+
namespace paddle {
20+
namespace framework {
21+
namespace interpreter {
22+
23+
void AddDownstreamOp(int prior_op_idx,
24+
int posterior_op_idx,
25+
std::map<int, std::list<int>>* op_downstream_map,
26+
const std::vector<std::vector<bool>>* op_happens_before) {
27+
if (op_downstream_map->find(prior_op_idx) == op_downstream_map->end()) {
28+
op_downstream_map->emplace(std::make_pair(prior_op_idx, std::list<int>()));
29+
} else {
30+
if (op_happens_before != nullptr) {
31+
for (int op_idx : op_downstream_map->at(prior_op_idx)) {
32+
if (op_happens_before->at(op_idx).at(posterior_op_idx)) {
33+
VLOG(7) << "Find dependencies " << prior_op_idx << "->" << op_idx
34+
<< "->" << posterior_op_idx << ", skip adding "
35+
<< prior_op_idx << "->" << posterior_op_idx;
36+
return;
37+
}
38+
}
39+
}
40+
}
41+
42+
op_downstream_map->at(prior_op_idx).push_back(posterior_op_idx);
43+
}
44+
45+
// check whether exists prior_op -> ... -> posterior_op to avoid building loops
46+
bool IsDependency(int prior_op_idx,
47+
int posterior_op_idx,
48+
const std::map<int, std::list<int>>& downstream_map) {
49+
std::queue<int> q;
50+
q.push(prior_op_idx);
51+
52+
while (!q.empty()) {
53+
int op_idx = q.front();
54+
q.pop();
55+
56+
auto it = downstream_map.find(op_idx);
57+
if (it != downstream_map.end()) {
58+
for (int downstream_op_idx : it->second) {
59+
if (downstream_op_idx == posterior_op_idx) {
60+
return true;
61+
}
62+
63+
// no need for double enqueue checking since DAG is assumed
64+
q.push(downstream_op_idx);
65+
}
66+
}
67+
}
68+
69+
return false;
70+
}
71+
72+
void AddDependencyForReadOp(
73+
const std::vector<Instruction>& vec_instruction,
74+
std::map<int, std::list<int>>* downstream_map,
75+
const std::vector<std::vector<bool>>* op_happens_before) {
76+
size_t op_num = vec_instruction.size();
77+
std::vector<bool> is_startup_ops(op_num, true);
78+
for (size_t op_idx = 0; op_idx < op_num; ++op_idx) {
79+
auto it = downstream_map->find(op_idx);
80+
if (it != downstream_map->end()) {
81+
for (size_t downstream_op_idx : it->second) {
82+
is_startup_ops[downstream_op_idx] = false;
83+
}
84+
}
85+
}
86+
87+
std::vector<size_t> read_ops;
88+
std::vector<size_t> startup_ops;
89+
for (size_t op_idx = 0; op_idx < op_num; ++op_idx) {
90+
if (vec_instruction[op_idx].OpBase()->Type() == "read") {
91+
read_ops.push_back(op_idx);
92+
}
93+
94+
if (is_startup_ops[op_idx]) {
95+
startup_ops.push_back(op_idx);
96+
}
97+
}
98+
99+
for (size_t read_op_idx : read_ops) {
100+
for (size_t downstream_op_idx : startup_ops) {
101+
if (read_op_idx != downstream_op_idx &&
102+
!IsDependency(downstream_op_idx, read_op_idx, *downstream_map))
103+
AddDownstreamOp(
104+
read_op_idx, downstream_op_idx, downstream_map, op_happens_before);
105+
VLOG(4) << "Add depend from "
106+
<< vec_instruction[read_op_idx].OpBase()->Type() << "("
107+
<< read_op_idx << ") to "
108+
<< vec_instruction[downstream_op_idx].OpBase()->Type() << "("
109+
<< downstream_op_idx << ")";
110+
}
111+
}
112+
}
113+
114+
} // namespace interpreter
115+
} // namespace framework
116+
} // namespace paddle
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
// This file provides some dependency adding function to handle the implicit
16+
// dependency that cannot be explicitly expresed by a Program. It is a
17+
// compromise of the incomplete expression ability of the Program. Do not add
18+
// too many functions here at will, that will bring great burden to the
19+
// Interpretercore.
20+
21+
// TODO(Ruibiao):
22+
// 1. Move other dependency adding codes from interpretercore_util.cc to
23+
// dependency_utils.cc
24+
// 2. Move other Interpretercore related codes to directory
25+
// new_executor/interpreter
26+
// 3. Try to remove parameter op_happens_before from the dependency adding
27+
// function
28+
29+
#pragma once
30+
31+
#include <map>
32+
#include <vector>
33+
34+
#include "paddle/fluid/framework/new_executor/new_executor_defs.h"
35+
36+
namespace paddle {
37+
namespace framework {
38+
namespace interpreter {
39+
40+
// equivalent to add_reader_dependency_pass
41+
void AddDependencyForReadOp(
42+
const std::vector<Instruction>& vec_instruction,
43+
std::map<int, std::list<int>>* downstream_map,
44+
const std::vector<std::vector<bool>>* op_happens_before = nullptr);
45+
46+
void AddDownstreamOp(
47+
int prior_op_idx,
48+
int posterior_op_idx,
49+
std::map<int, std::list<int>>* op_downstream_map,
50+
const std::vector<std::vector<bool>>* op_happens_before = nullptr);
51+
52+
} // namespace interpreter
53+
} // namespace framework
54+
} // namespace paddle

paddle/fluid/framework/new_executor/interpretercore_util.cc

Lines changed: 12 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "paddle/fluid/framework/details/nan_inf_utils.h"
1919
#include "paddle/fluid/framework/executor_gc_helper.h"
2020
#include "paddle/fluid/framework/new_executor/data_transfer.h"
21+
#include "paddle/fluid/framework/new_executor/interpreter/dependency_utils.h"
2122
#include "paddle/fluid/operators/controlflow/conditional_block_op_helper.h"
2223
#include "paddle/fluid/operators/controlflow/recurrent_op_helper.h"
2324
#include "paddle/fluid/operators/controlflow/while_op_helper.h"
@@ -704,33 +705,6 @@ void update_var_min_rw_op(const std::map<int, std::set<int>>& op2dependences,
704705
var2min_rw_op->at(rw_var).push_back(cur_op);
705706
}
706707

707-
void AddDownstreamOp(int prior_op_idx,
708-
int posterior_op_idx,
709-
std::map<int, std::list<int>>* op_downstream_map) {
710-
if (op_downstream_map->find(prior_op_idx) == op_downstream_map->end()) {
711-
op_downstream_map->emplace(std::make_pair(prior_op_idx, std::list<int>()));
712-
}
713-
op_downstream_map->at(prior_op_idx).push_back(posterior_op_idx);
714-
}
715-
716-
void AddDownstreamOp(int prior_op_idx,
717-
int posterior_op_idx,
718-
std::map<int, std::list<int>>* op_downstream_map,
719-
const std::vector<std::vector<bool>>& op_happens_before) {
720-
if (op_downstream_map->find(prior_op_idx) != op_downstream_map->end()) {
721-
for (int op_idx : op_downstream_map->at(prior_op_idx)) {
722-
if (op_happens_before[op_idx][posterior_op_idx]) {
723-
VLOG(7) << "Find dependencies " << prior_op_idx << "->" << op_idx
724-
<< "->" << posterior_op_idx << ", skip adding " << prior_op_idx
725-
<< "->" << posterior_op_idx;
726-
return;
727-
}
728-
}
729-
}
730-
731-
AddDownstreamOp(prior_op_idx, posterior_op_idx, op_downstream_map);
732-
}
733-
734708
size_t CountDownstreamMap(const std::map<int, std::list<int>>& downstream_map) {
735709
size_t count = 0;
736710
for (auto pair : downstream_map) {
@@ -972,7 +946,7 @@ std::map<int, std::list<int>> build_op_downstream_map(
972946
if (random_op_set.count(vec_instruction[op_idx].OpBase()->Type())) {
973947
if (dependence_op_idx != -1) {
974948
AddDownstreamOp(
975-
dependence_op_idx, op_idx, &op_downstream_map, *op_happens_before);
949+
dependence_op_idx, op_idx, &op_downstream_map, op_happens_before);
976950
}
977951
dependence_op_idx = op_idx;
978952
}
@@ -999,7 +973,7 @@ std::map<int, std::list<int>> build_op_downstream_map(
999973
if (is_comm_op(vec_instruction[op_idx].OpBase()->Type())) {
1000974
if (dependence_op_idx != -1) {
1001975
AddDownstreamOp(
1002-
dependence_op_idx, op_idx, &op_downstream_map, *op_happens_before);
976+
dependence_op_idx, op_idx, &op_downstream_map, op_happens_before);
1003977
VLOG(4) << "Add depend from "
1004978
<< vec_instruction[dependence_op_idx].OpBase()->Type() << " to "
1005979
<< vec_instruction[op_idx].OpBase()->Type();
@@ -1028,7 +1002,7 @@ std::map<int, std::list<int>> build_op_downstream_map(
10281002
<< vec_instruction[dependence_op_idx].OpBase()->Type() << " to "
10291003
<< vec_instruction[op_idx].OpBase()->Type();
10301004
AddDownstreamOp(
1031-
dependence_op_idx, op_idx, &op_downstream_map, *op_happens_before);
1005+
dependence_op_idx, op_idx, &op_downstream_map, op_happens_before);
10321006
}
10331007
}
10341008
}
@@ -1088,7 +1062,7 @@ std::map<int, std::list<int>> build_op_downstream_map(
10881062
AddDownstreamOp(j,
10891063
first_read_fused_out_op,
10901064
&op_downstream_map,
1091-
*op_happens_before);
1065+
op_happens_before);
10921066
VLOG(4) << j << " -> " << first_read_fused_out_op;
10931067
VLOG(4)
10941068
<< "Add depend from " << vec_instruction[j].OpBase()->Type()
@@ -1121,7 +1095,7 @@ std::map<int, std::list<int>> build_op_downstream_map(
11211095

11221096
for (auto var_id : outputs) {
11231097
if (is_read(vec_instruction[j], var_id)) {
1124-
AddDownstreamOp(target, j, &op_downstream_map, *op_happens_before);
1098+
AddDownstreamOp(target, j, &op_downstream_map, op_happens_before);
11251099
VLOG(4) << target << " -> " << j;
11261100
VLOG(4) << "Add depend from "
11271101
<< vec_instruction[target].OpBase()->Type() << " to "
@@ -1137,10 +1111,8 @@ std::map<int, std::list<int>> build_op_downstream_map(
11371111
for (size_t op_idx = 0; op_idx < op_num; ++op_idx) {
11381112
if (!IsCpuOp(vec_instruction[op_idx])) {
11391113
if (dependence_op_idx != -1) {
1140-
AddDownstreamOp(dependence_op_idx,
1141-
op_idx,
1142-
&op_downstream_map,
1143-
*op_happens_before);
1114+
AddDownstreamOp(
1115+
dependence_op_idx, op_idx, &op_downstream_map, op_happens_before);
11441116
VLOG(4) << "Add depend from "
11451117
<< vec_instruction[dependence_op_idx].OpBase()->Type() << "("
11461118
<< dependence_op_idx << ") to "
@@ -1152,6 +1124,10 @@ std::map<int, std::list<int>> build_op_downstream_map(
11521124
}
11531125
}
11541126

1127+
AddDependencyForReadOp(
1128+
vec_instruction, &op_downstream_map, op_happens_before);
1129+
1130+
VLOG(8) << "build_op_downstream_map finished";
11551131
VLOG(8) << "downstream count: " << CountDownstreamMap(op_downstream_map);
11561132
VLOG(8) << "downstream_map: " << std::endl
11571133
<< StringizeDownstreamMap(op_downstream_map);

paddle/fluid/framework/new_executor/interpretercore_util.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,6 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
/*************************************************************************
16-
> File Name: interpretercore_util.h
17-
> Author: guanshanshan@baidu.com
18-
> Created Time: Fri 23 Jul 2021 06:19:19 AM UTC
19-
************************************************************************/
20-
2115
#pragma once
2216

2317
#include <chrono>
@@ -48,7 +42,6 @@ using AtomicVectorSizeT = std::vector<std::atomic<size_t>>;
4842

4943
namespace paddle {
5044
namespace framework {
51-
5245
namespace interpreter {
5346

5447
class AsyncWorkQueue {

python/paddle/fluid/tests/unittests/CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1713,3 +1713,10 @@ if(WITH_CINN AND WITH_TESTING)
17131713
FLAGS_allow_cinn_ops="conv2d;conv2d_grad;elementwise_add;elementwise_add_grad;relu;relu_grad;sum"
17141714
)
17151715
endif()
1716+
1717+
py_test_modules(
1718+
test_add_reader_dependency_for_interpretercore MODULES
1719+
test_add_reader_dependency ENVS FLAGS_CONVERT_GRAPH_TO_PROGRAM=true)
1720+
1721+
set_tests_properties(test_add_reader_dependency_for_interpretercore
1722+
PROPERTIES TIMEOUT 120)

tools/windows/run_unittests.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
disable_wingpu_test="^test_model$|\
1919
^test_dataloader_early_reset$|\
2020
^test_add_reader_dependency$|\
21+
^test_add_reader_dependency_for_interpretercore$|\
2122
^test_decoupled_py_reader$|\
2223
^test_generator_dataloader$|\
2324
^test_parallel_dygraph_sync_batch_norm$|\
@@ -152,6 +153,7 @@ disable_win_inference_test="^trt_quant_int8_yolov3_r50_test$|\
152153
^test_multiprocess_dataloader_iterable_dataset_dynamic$|\
153154
^test_multiprocess_dataloader_iterable_dataset_static$|\
154155
^test_add_reader_dependency$|\
156+
^test_add_reader_dependency_for_interpretercore$|\
155157
^test_compat$|\
156158
^test_decoupled_py_reader$|\
157159
^test_generator_dataloader$|\

0 commit comments

Comments
 (0)