Skip to content

Commit 08295f9

Browse files
committed
Add build strategy
1 parent c06b448 commit 08295f9

File tree

10 files changed

+162
-77
lines changed

10 files changed

+162
-77
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright (c) 2018 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+
#pragma once
16+
17+
namespace paddle {
18+
namespace framework {
19+
namespace details {
20+
21+
struct BuildStrategy {
22+
enum class ReduceStrategy { kAllReduce = 0, kReduce = 1 };
23+
24+
enum class GradientScaleStrategy {
25+
kCoeffNumDevice = 0,
26+
kOne = 1,
27+
kCustomized = 2,
28+
};
29+
30+
ReduceStrategy reduce_{ReduceStrategy::kReduce};
31+
GradientScaleStrategy gradient_scale_{GradientScaleStrategy::kCoeffNumDevice};
32+
};
33+
34+
} // namespace details
35+
} // namespace framework
36+
} // namespace paddle

paddle/fluid/framework/details/multi_devices_graph_builder.cc

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -37,31 +37,26 @@ MultiDevSSAGraphBuilder::MultiDevSSAGraphBuilder(
3737
const std::string &loss_var_name,
3838
const std::unordered_set<std::string> &params,
3939
const std::vector<Scope *> &local_scopes,
40-
platform::NCCLContextMap *nccl_ctxs, bool use_default_grad_scale,
41-
bool balance_parameter_opt_between_cards)
40+
platform::NCCLContextMap *nccl_ctxs, const BuildStrategy &strategy)
4241
: loss_var_name_(loss_var_name),
4342
places_(places),
4443
local_scopes_(local_scopes),
4544
nccl_ctxs_(nccl_ctxs),
46-
balance_parameter_opt_between_cards_(
47-
balance_parameter_opt_between_cards) {
45+
strategy_(strategy) {
4846
#else
4947
MultiDevSSAGraphBuilder::MultiDevSSAGraphBuilder(
5048
const std::vector<platform::Place> &places,
5149
const std::string &loss_var_name,
5250
const std::unordered_set<std::string> &params,
53-
const std::vector<Scope *> &local_scopes, bool use_default_grad_scale,
54-
bool balance_parameter_opt_between_cards)
51+
const std::vector<Scope *> &local_scopes, const BuildStrategy &strategy)
5552
: loss_var_name_(loss_var_name),
5653
places_(places),
5754
local_scopes_(local_scopes),
58-
balance_parameter_opt_between_cards_(
59-
balance_parameter_opt_between_cards) {
55+
strategy_(strategy) {
6056
#endif
6157
for (auto &p : params) {
6258
grad_names_.insert(GradVarName(p));
6359
}
64-
use_default_grad_scale_ = use_default_grad_scale;
6560
}
6661

6762
void MultiDevSSAGraphBuilder::CreateOpHandleIOs(SSAGraph *result,
@@ -146,7 +141,8 @@ std::unique_ptr<SSAGraph> MultiDevSSAGraphBuilder::Build(
146141
CreateComputationalOps(&result, *op, 1);
147142
} else if (IsScaleLossOp(*op)) {
148143
// user can customize loss@grad if not use_default_grad_scale_
149-
if (use_default_grad_scale_) {
144+
if (strategy_.gradient_scale_ !=
145+
BuildStrategy::GradientScaleStrategy::kCustomized) {
150146
CreateScaleLossGradOp(&result);
151147
}
152148
is_forwarding = false;
@@ -165,19 +161,22 @@ std::unique_ptr<SSAGraph> MultiDevSSAGraphBuilder::Build(
165161
// broadcast, and each gradient is only broadcast once.
166162
for (auto &og : op->OutputArgumentNames()) {
167163
if (IsParameterGradientOnce(og, &og_has_been_broadcast)) {
168-
if (balance_parameter_opt_between_cards_) {
169-
CreateReduceOp(&result, og, cur_device_id);
170-
var_name_on_devices[cur_device_id].emplace(og);
171-
bcast_var_name_set[cur_device_id].emplace(
172-
og.substr(0, og.size() - strlen(kGradVarSuffix)));
173-
cur_device_id = (cur_device_id + 1) % places_.size();
174-
} else {
175-
if (IsSparseGradient(var_types, og)) {
176-
CreateReduceOp(&result, og, 0);
177-
CreateBroadcastOp(&result, og, 0);
178-
} else {
179-
InsertNCCLAllReduceOp(&result, og);
180-
}
164+
switch (strategy_.reduce_) {
165+
case BuildStrategy::ReduceStrategy::kReduce:
166+
CreateReduceOp(&result, og, cur_device_id);
167+
var_name_on_devices[cur_device_id].emplace(og);
168+
bcast_var_name_set[cur_device_id].emplace(
169+
og.substr(0, og.size() - strlen(kGradVarSuffix)));
170+
cur_device_id = (cur_device_id + 1) % places_.size();
171+
break;
172+
case BuildStrategy::ReduceStrategy::kAllReduce:
173+
if (IsSparseGradient(var_types, og)) {
174+
CreateReduceOp(&result, og, 0);
175+
CreateBroadcastOp(&result, og, 0);
176+
} else {
177+
InsertNCCLAllReduceOp(&result, og);
178+
}
179+
break;
181180
}
182181
}
183182
}
@@ -303,7 +302,7 @@ bool MultiDevSSAGraphBuilder::IsParameterGradientOnce(
303302
int MultiDevSSAGraphBuilder::GetOpDeviceID(
304303
const std::vector<std::unordered_set<std::string>> &var_name_on_devices,
305304
const OpDesc &op) const {
306-
if (!balance_parameter_opt_between_cards_) {
305+
if (strategy_.reduce_ != BuildStrategy::ReduceStrategy::kReduce) {
307306
return -1;
308307
}
309308

paddle/fluid/framework/details/multi_devices_graph_builder.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <utility>
1818
#include <vector>
1919

20+
#include "paddle/fluid/framework/details/build_strategy.h"
2021
#include "paddle/fluid/framework/details/ssa_graph_builder.h"
2122

2223
namespace paddle {
@@ -36,15 +37,13 @@ class MultiDevSSAGraphBuilder : public SSAGraphBuilder {
3637
const std::unordered_set<std::string> &params,
3738
const std::vector<Scope *> &local_scopes,
3839
platform::NCCLContextMap *nccl_ctxs,
39-
bool use_default_grad_scale,
40-
bool balance_parameter_opt_between_cards);
40+
const BuildStrategy &strategy);
4141
#else
4242
MultiDevSSAGraphBuilder(const std::vector<platform::Place> &places,
4343
const std::string &loss_var_name,
4444
const std::unordered_set<std::string> &params,
4545
const std::vector<Scope *> &local_scopes,
46-
bool use_default_grad_scale,
47-
bool balance_parameter_opt_between_cards);
46+
const BuildStrategy &strategy);
4847
#endif
4948

5049
std::unique_ptr<SSAGraph> Build(const ProgramDesc &program) const override;
@@ -62,8 +61,6 @@ class MultiDevSSAGraphBuilder : public SSAGraphBuilder {
6261
#ifdef PADDLE_WITH_CUDA
6362
platform::NCCLContextMap *nccl_ctxs_;
6463
#endif
65-
bool balance_parameter_opt_between_cards_;
66-
bool use_default_grad_scale_;
6764

6865
bool IsScaleLossOp(const OpDesc &op) const;
6966

@@ -105,6 +102,9 @@ class MultiDevSSAGraphBuilder : public SSAGraphBuilder {
105102
bool IsSparseGradient(
106103
const std::unordered_map<std::string, proto::VarType::Type> &var_types,
107104
const std::string &og) const;
105+
106+
private:
107+
BuildStrategy strategy_;
108108
};
109109
} // namespace details
110110
} // namespace framework

paddle/fluid/framework/parallel_executor.cc

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,7 @@ ParallelExecutor::ParallelExecutor(
5757
const std::unordered_set<std::string> &bcast_vars,
5858
const ProgramDesc &main_program, const std::string &loss_var_name,
5959
Scope *scope, const std::vector<Scope *> &local_scopes,
60-
bool use_default_grad_scale, bool balance_parameter_opt_between_cards,
61-
const ExecutionStrategy &exec_strategy)
60+
const ExecutionStrategy &exec_strategy, const BuildStrategy &build_strategy)
6261
: member_(new ParallelExecutorPrivate(places)) {
6362
member_->global_scope_ = scope;
6463

@@ -93,12 +92,11 @@ ParallelExecutor::ParallelExecutor(
9392
#ifdef PADDLE_WITH_CUDA
9493
details::MultiDevSSAGraphBuilder builder(
9594
member_->places_, loss_var_name, params, member_->local_scopes_,
96-
member_->nccl_ctxs_.get(), use_default_grad_scale,
97-
balance_parameter_opt_between_cards);
95+
member_->nccl_ctxs_.get(), build_strategy);
9896
#else
99-
details::MultiDevSSAGraphBuilder builder(
100-
member_->places_, loss_var_name, params, member_->local_scopes_,
101-
use_default_grad_scale, balance_parameter_opt_between_cards);
97+
details::MultiDevSSAGraphBuilder builder(member_->places_, loss_var_name,
98+
params, member_->local_scopes_,
99+
build_strategy);
102100
#endif
103101
auto graph = builder.Build(main_program);
104102

paddle/fluid/framework/parallel_executor.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ limitations under the License. */
1414

1515
#pragma once
1616

17+
#include <paddle/fluid/framework/details/build_strategy.h>
1718
#include <string>
1819
#include <unordered_set>
1920
#include <vector>
@@ -29,6 +30,7 @@ namespace framework {
2930

3031
class ParallelExecutorPrivate;
3132

33+
using details::BuildStrategy;
3234
using details::ExecutionStrategy;
3335

3436
class ParallelExecutor {
@@ -41,9 +43,8 @@ class ParallelExecutor {
4143
const ProgramDesc &main_program,
4244
const std::string &loss_var_name, Scope *scope,
4345
const std::vector<Scope *> &local_scopes,
44-
bool use_default_grad_scale,
45-
bool balance_parameter_opt_between_cards,
46-
const ExecutionStrategy &exec_strategy);
46+
const ExecutionStrategy &exec_strategy,
47+
const BuildStrategy &build_strategy);
4748

4849
~ParallelExecutor();
4950

paddle/fluid/platform/nccl_helper.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class NCCLGroupGuard {
5050
}
5151

5252
inline ~NCCLGroupGuard() {
53-
PADDLE_ENFORCE(dynload::ncclGroupEnd());
53+
CHECK_EQ(dynload::ncclGroupEnd(), ncclSuccess);
5454
NCCLMutex().unlock();
5555
}
5656
};

paddle/fluid/pybind/pybind.cc

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,7 @@ All parameter, weight, gradient are variables in Paddle.
494494
m.def("disable_profiler", platform::DisableProfiler);
495495
m.def("reset_profiler", platform::ResetProfiler);
496496

497+
// -- python binds for parallel executor.
497498
py::class_<ParallelExecutor> pe(m, "ParallelExecutor");
498499
py::class_<ExecutionStrategy>(pe, "ExecutionStrategy")
499500
.def(py::init())
@@ -515,12 +516,38 @@ All parameter, weight, gradient are variables in Paddle.
515516
[](ExecutionStrategy &self, bool allow_op_delay) {
516517
self.allow_op_delay_ = allow_op_delay;
517518
});
519+
py::class_<BuildStrategy> build_strategy(pe, "BuildStrategy");
520+
521+
py::enum_<BuildStrategy::ReduceStrategy>(build_strategy, "ReduceStrategy")
522+
.value("Reduce", BuildStrategy::ReduceStrategy::kReduce)
523+
.value("AllReduce", BuildStrategy::ReduceStrategy::kAllReduce);
524+
py::enum_<BuildStrategy::GradientScaleStrategy>(build_strategy,
525+
"GradientScaleStrategy")
526+
.value("CoeffNumDevice",
527+
BuildStrategy::GradientScaleStrategy::kCoeffNumDevice)
528+
.value("One", BuildStrategy::GradientScaleStrategy::kOne)
529+
.value("Customized", BuildStrategy::GradientScaleStrategy::kCustomized);
530+
531+
build_strategy.def(py::init())
532+
.def_property(
533+
"reduce_strategy",
534+
[](const BuildStrategy &self) { return self.reduce_; },
535+
[](BuildStrategy &self, BuildStrategy::ReduceStrategy strategy) {
536+
self.reduce_ = strategy;
537+
})
538+
.def_property(
539+
"gradient_scale_strategy",
540+
[](const BuildStrategy &self) { return self.gradient_scale_; },
541+
[](BuildStrategy &self,
542+
BuildStrategy::GradientScaleStrategy strategy) {
543+
self.gradient_scale_ = strategy;
544+
});
518545

519546
pe.def(py::init<const std::vector<platform::Place> &,
520547
const std::unordered_set<std::string> &,
521548
const std::unordered_set<std::string> &, const ProgramDesc &,
522-
const std::string &, Scope *, std::vector<Scope *> &, bool,
523-
bool, const ExecutionStrategy &>())
549+
const std::string &, Scope *, std::vector<Scope *> &,
550+
const ExecutionStrategy &, const BuildStrategy &>())
524551
.def("bcast_params", &ParallelExecutor::BCastParamsToGPUs)
525552
// NOTE: even we return a vec<Scope*>* to Python use reference policy.
526553
// We still cannot get local_scope from this vector, since the element

python/paddle/fluid/__init__.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,14 @@
5252
import profiler
5353
import unique_name
5454
import recordio_writer
55-
from parallel_executor import ParallelExecutor, ExecutionStrategy
55+
import parallel_executor
56+
from parallel_executor import *
5657

5758
Tensor = LoDTensor
5859

5960
__all__ = framework.__all__ + executor.__all__ + concurrency.__all__ + \
60-
trainer.__all__ + inferencer.__all__ + transpiler.__all__ + [
61+
trainer.__all__ + inferencer.__all__ + transpiler.__all__ + \
62+
parallel_executor.__all__ + [
6163
'io',
6264
'initializer',
6365
'layers',
@@ -79,8 +81,6 @@
7981
'profiler',
8082
'unique_name',
8183
'recordio_writer',
82-
'ParallelExecutor',
83-
'ExecutionStrategy',
8484
]
8585

8686

python/paddle/fluid/parallel_executor.py

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,10 @@
1919
import warnings
2020
import sys
2121

22-
__all__ = ['ParallelExecutor', 'ExecutionStrategy']
22+
__all__ = ['ParallelExecutor', 'ExecutionStrategy', 'BuildStrategy']
2323

2424
ExecutionStrategy = core.ParallelExecutor.ExecutionStrategy
25+
BuildStrategy = core.ParallelExecutor.BuildStrategy
2526

2627

2728
class ParallelExecutor(object):
@@ -30,9 +31,8 @@ def __init__(self,
3031
loss_name=None,
3132
main_program=None,
3233
share_vars_from=None,
33-
use_default_grad_scale=True,
34-
balance_parameter_opt_between_cards=False,
3534
exec_strategy=None,
35+
build_strategy=None,
3636
**kwargs):
3737
"""
3838
ParallelExecutor can run program in parallel.
@@ -81,7 +81,16 @@ def __init__(self,
8181
"Setting {0} by constructor is deprecated. Use " \
8282
"strategy=ExecutionStrategy(); strategy.{0}=xxx; " \
8383
"pe=ParallelExecutor(exec_strategy=strategy) " \
84-
"instead.\n "
84+
"instead.\n ".format(key)
85+
elif key in dir(BuildStrategy):
86+
err_msg += \
87+
"Setting {0} by constructor is deprecated. Use " \
88+
"strategy=BuildStrategy(); See help(" \
89+
"paddle.fluid.ParallelExecutor.BuildStrategy) \n".format(
90+
key)
91+
else:
92+
err_msg += "Setting {0} by constructor is deprecated. Use strategy.\n".format(
93+
key)
8594
raise ValueError(err_msg)
8695

8796
self._places = []
@@ -116,6 +125,9 @@ def __init__(self,
116125
exec_strategy.num_threads = min(
117126
len(self._places) * 2, multiprocessing.cpu_count())
118127

128+
if build_strategy is None:
129+
build_strategy = BuildStrategy()
130+
119131
main = main_program
120132
main = main if main else framework.default_main_program()
121133
scope = executor.global_scope()
@@ -139,9 +151,8 @@ def __init__(self,
139151
p.name for p in main.global_block().iter_parameters()
140152
if not p.stop_gradient
141153
]),
142-
set(self.persistable_vars), main.desc, loss_name
143-
if loss_name else '', scope, local_scopes, use_default_grad_scale,
144-
balance_parameter_opt_between_cards, exec_strategy)
154+
set(self.persistable_vars), main.desc, loss_name if loss_name else
155+
'', scope, local_scopes, exec_strategy, build_strategy)
145156

146157
self.scope = scope
147158

0 commit comments

Comments
 (0)