Skip to content
This repository was archived by the owner on Sep 9, 2025. It is now read-only.

Commit d1aa750

Browse files
authored
improve optimizer support (PaddlePaddle#641) (PaddlePaddle#649)
* update GetOptPrePostfix
1 parent 84df0d7 commit d1aa750

File tree

6 files changed

+167
-113
lines changed

6 files changed

+167
-113
lines changed

paddle/fluid/platform/device/ipu/ipu_compiler.cc

Lines changed: 35 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -285,42 +285,43 @@ void Compiler::LowerConstants(const Scope* scope) {
285285

286286
void Compiler::LowerWeights(const Scope* scope) {
287287
VLOG(10) << "enter Compiler::LowerWeights";
288-
// at this step, the graph doesn't contains optimizer related states
288+
// At this step, the graph doesn't contains optimizer related states
289289
for (auto id : graph_helper_->sorted_vars_id) {
290290
auto* node = graph_helper_->nodes_id_map[id];
291-
if (node->IsVar() && !node->IsCtrlVar() && node->Var()) {
292-
if (node->Var()->Persistable() && node->inputs.empty()) {
293-
auto var_name = node->Var()->Name();
294-
if (resources_->tensors.count(var_name) != 0) {
295-
VLOG(10) << "found existed one, skip lowering Weight: " << var_name;
296-
continue;
297-
}
298-
if (var_name.rfind("learning_rate", 0) == 0) {
299-
VLOG(10) << "skip learning_rate_var: " << var_name;
300-
continue;
301-
}
302-
VLOG(10) << "lowering weight: " << var_name;
303-
304-
auto var = scope->FindVar(var_name);
305-
if (var) {
306-
auto tensor = var->Get<framework::LoDTensor>();
307-
auto dtype = PdDataType2PopartType(tensor.dtype());
308-
auto shape = std::vector<int64_t>();
309-
for (size_t i = 0; i < tensor.dims().size(); ++i) {
310-
shape.push_back(tensor.dims().at(i));
311-
}
312-
popart::TensorInfo tensor_info(dtype, shape);
313-
popart::ConstVoidData const_data{tensor.data(), tensor_info};
314-
if (!node->outputs.empty()) {
315-
auto op_node = node->outputs[0];
316-
PushNameScope(op_node->Op());
317-
popart::TensorId result =
318-
builder_->addInitializedInputTensor(const_data, var_name);
319-
PopNameScope(op_node->Op());
320-
resources_->tensors.emplace(var_name, result);
321-
resources_->weights.push_back(var_name);
322-
}
323-
}
291+
// Weights are var node and Persistable
292+
if (node->IsVar() && !node->IsCtrlVar() && node->Var() &&
293+
node->Var()->Persistable()) {
294+
// Weights are Parameter in training mode
295+
if (ipu_strategy_->is_training && !node->Var()->IsParameter()) {
296+
continue;
297+
}
298+
auto var_name = node->Var()->Name();
299+
// Some op has same input and output tensor, like batchnorm
300+
if (resources_->tensors.count(var_name) != 0) {
301+
VLOG(10) << "found existed one, skip lowering Weight: " << var_name;
302+
continue;
303+
}
304+
VLOG(10) << "lowering weight: " << var_name;
305+
auto var = scope->FindVar(var_name);
306+
PADDLE_ENFORCE_NOT_NULL(
307+
var, platform::errors::NotFound("Tensor %s is not found in the scope",
308+
var_name));
309+
auto tensor = var->Get<framework::LoDTensor>();
310+
auto dtype = PdDataType2PopartType(tensor.dtype());
311+
auto shape = std::vector<int64_t>();
312+
for (size_t i = 0; i < tensor.dims().size(); ++i) {
313+
shape.push_back(tensor.dims().at(i));
314+
}
315+
popart::TensorInfo tensor_info(dtype, shape);
316+
popart::ConstVoidData const_data{tensor.data(), tensor_info};
317+
if (!node->outputs.empty()) {
318+
auto op_node = node->outputs[0];
319+
PushNameScope(op_node->Op());
320+
popart::TensorId result =
321+
builder_->addInitializedInputTensor(const_data, var_name);
322+
PopNameScope(op_node->Op());
323+
resources_->tensors.emplace(var_name, result);
324+
resources_->weights.push_back(var_name);
324325
}
325326
}
326327
}

paddle/fluid/platform/device/ipu/ipu_executor.cc

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,40 @@ namespace paddle {
2020
namespace platform {
2121
namespace ipu {
2222

23+
// Get paddle prefix and popart postfix of weight states
24+
// Format: {popart_postfix, paddle_prefix}
25+
std::vector<std::pair<std::string, std::string>> GetOptPrePostfix(
26+
const std::string &opt_type) {
27+
std::vector<std::pair<std::string, std::string>> pre_post_fix;
28+
// Weight self
29+
pre_post_fix.push_back(std::make_pair("", ""));
30+
31+
// Weight states
32+
// TODO(alleng) support pair("Accl1___", "_moment1_{id!=0}")
33+
if (opt_type == "adam" || opt_type == "lamb" || opt_type == "adamw") {
34+
pre_post_fix.push_back(std::make_pair("Accl1___", "_moment1_0"));
35+
pre_post_fix.push_back(std::make_pair("Accl2___", "_moment2_0"));
36+
pre_post_fix.push_back(std::make_pair("Step___", "_beta1_pow_acc_0"));
37+
} else if (opt_type == "momentum") {
38+
pre_post_fix.push_back(std::make_pair("Accl___", "_velocity_0"));
39+
} else if (opt_type == "adamax") {
40+
pre_post_fix.push_back(std::make_pair("Accl1___", "_moment_0"));
41+
pre_post_fix.push_back(std::make_pair("Accl2___", "_inf_norm__0"));
42+
pre_post_fix.push_back(std::make_pair("Step___", "_beta1_pow_acc_0"));
43+
} else if (opt_type == "adagrad") {
44+
pre_post_fix.push_back(std::make_pair("Accl1___", "_moment_0"));
45+
} else if (opt_type == "adadelta") {
46+
pre_post_fix.push_back(std::make_pair("Accl1___", "__avg_squared_grad_0"));
47+
pre_post_fix.push_back(
48+
std::make_pair("Accl2___", "__avg_squared_update_0"));
49+
} else if (opt_type == "rmsprop") {
50+
pre_post_fix.push_back(std::make_pair("Accl1___", "_mean_square_0"));
51+
pre_post_fix.push_back(std::make_pair("Accl2___", "_mean_grad_0"));
52+
pre_post_fix.push_back(std::make_pair("Accl3___", "_momentum__0"));
53+
}
54+
return pre_post_fix;
55+
}
56+
2357
Executor::~Executor() {
2458
Detach();
2559
session_.reset();

paddle/fluid/platform/device/ipu/ipu_utils.cc

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -184,27 +184,6 @@ bool GetBoolEnv(std::string str) {
184184
}
185185
}
186186

187-
std::vector<std::pair<std::string, std::string>> GetOptPrePostfix(
188-
const std::string& opt_type) {
189-
// format: {popart_tensor_id, paddle_tensor_id}, ...
190-
std::vector<std::pair<std::string, std::string>> pre_post_fix;
191-
192-
if (opt_type == "adam" || opt_type == "lamb") {
193-
pre_post_fix.push_back(std::make_pair("", ""));
194-
pre_post_fix.push_back(std::make_pair("Accl1___", "_moment1_0"));
195-
pre_post_fix.push_back(std::make_pair("Accl2___", "_moment2_0"));
196-
pre_post_fix.push_back(std::make_pair("Step___", "_beta1_pow_acc_0"));
197-
} else if (opt_type == "sgd" || opt_type == "momentum") {
198-
// sgd
199-
pre_post_fix.push_back(std::make_pair("", ""));
200-
} else {
201-
pre_post_fix.push_back(std::make_pair("", ""));
202-
//
203-
}
204-
205-
return pre_post_fix;
206-
}
207-
208187
int RequestIpus(const int num_ipus) {
209188
// num_ipus must be pow(2, n);
210189
return std::pow(2, ceil(log2(num_ipus)));

paddle/fluid/platform/device/ipu/ipu_utils.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -229,9 +229,6 @@ struct ConstantOpAttrVisitor : public boost::static_visitor<void> {
229229
void operator()(boost::blank) const { RaiseError(); }
230230
};
231231

232-
std::vector<std::pair<std::string, std::string>> GetOptPrePostfix(
233-
const std::string& opt_type);
234-
235232
int RequestIpus(const int num_ipus);
236233

237234
} // namespace ipu

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,5 @@ if(WITH_IPU)
1111
set_tests_properties(test_conv_op_ipu PROPERTIES TIMEOUT 300)
1212
set_tests_properties(test_elemetwise_x_op_ipu PROPERTIES TIMEOUT 300)
1313
set_tests_properties(test_reduce_x_op_ipu PROPERTIES TIMEOUT 600)
14+
set_tests_properties(test_save_load_ipu PROPERTIES TIMEOUT 600)
1415
endif()

python/paddle/fluid/tests/unittests/ipu/test_save_load_ipu.py

Lines changed: 97 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@
1414

1515
import tempfile
1616
import unittest
17+
from functools import partial
1718

1819
import numpy as np
1920
import paddle
21+
import paddle.optimizer
2022
import paddle.static
2123
from paddle.fluid.tests.unittests.ipu.op_test_ipu import IPUOpTest
2224

@@ -28,7 +30,8 @@ def setUp(self):
2830
self.set_atol()
2931
self.set_data_feed()
3032
self.set_feed_attr()
31-
self.set_op_attrs()
33+
self.set_attrs()
34+
self.set_optimizer()
3235

3336
def set_data_feed(self):
3437
data = np.random.uniform(size=[1, 3, 10, 10])
@@ -39,15 +42,16 @@ def set_feed_attr(self):
3942
self.feed_shape = [x.shape for x in self.feed_fp32.values()]
4043
self.feed_list = list(self.feed_fp32.keys())
4144

42-
def set_op_attrs(self):
45+
def set_attrs(self):
4346
self.attrs = {}
4447
self.attrs['steps'] = 100
4548
self.attrs['save_at_step'] = 20
46-
self.attrs['is_training'] = True
47-
self.attrs['opt_type'] = 'sgd'
4849
self.attrs['enable_fp16'] = False
4950
self.attrs['model_path'] = tempfile.TemporaryDirectory()
5051

52+
def set_optimizer(self):
53+
self.optimizer = partial(paddle.optimizer.SGD, learning_rate=1e-1)
54+
5155
def _test_base(self, save_otherwise_load):
5256
scope = paddle.static.Scope()
5357
main_prog = paddle.static.Program()
@@ -71,16 +75,8 @@ def _test_base(self, save_otherwise_load):
7175
name='conv2d')
7276
loss = paddle.mean(conv1)
7377

74-
if self.attrs['is_training']:
75-
if self.attrs['opt_type'] == 'sgd':
76-
sgd = paddle.optimizer.SGD(learning_rate=1e-2)
77-
sgd.minimize(loss)
78-
elif self.attrs['opt_type'] == 'adam':
79-
adam = paddle.optimizer.Adam(learning_rate=1e-2)
80-
adam.minimize(loss)
81-
elif self.attrs['opt_type'] == 'lamb':
82-
lamb = paddle.optimizer.Lamb(learning_rate=1e-2)
83-
lamb.minimize(loss)
78+
# apply optimizer
79+
self.optimizer().minimize(loss)
8480
fetch_list = [loss.name]
8581

8682
place = paddle.IPUPlace()
@@ -91,8 +87,7 @@ def _test_base(self, save_otherwise_load):
9187
paddle.static.load(main_prog, self.attrs['model_path'].name)
9288

9389
ipu_strategy = paddle.static.IpuStrategy()
94-
ipu_strategy.set_graph_config(
95-
is_training=self.attrs['is_training'])
90+
ipu_strategy.set_graph_config(is_training=True)
9691
ipu_strategy.set_precision_config(
9792
enable_fp16=self.attrs['enable_fp16'])
9893
ipu_program = paddle.static.IpuCompiledProgram(
@@ -131,62 +126,109 @@ def test_base(self):
131126
self.attrs['model_path'].cleanup()
132127

133128

129+
class TestMomentum(TestBase):
130+
def set_optimizer(self):
131+
self.optimizer = partial(paddle.optimizer.Momentum, learning_rate=1e-1)
132+
133+
134134
class TestAdam(TestBase):
135-
def set_op_attrs(self):
136-
self.attrs = {}
137-
self.attrs['steps'] = 100
138-
self.attrs['save_at_step'] = 20
139-
self.attrs['is_training'] = True
140-
self.attrs['opt_type'] = 'adam'
141-
self.attrs['enable_fp16'] = False
142-
self.attrs['model_path'] = tempfile.TemporaryDirectory()
135+
def set_optimizer(self):
136+
self.optimizer = partial(paddle.optimizer.Adam, learning_rate=1e-1)
143137

144138

145139
class TestLamb(TestBase):
146-
def set_op_attrs(self):
147-
self.attrs = {}
148-
self.attrs['steps'] = 100
149-
self.attrs['save_at_step'] = 20
150-
self.attrs['is_training'] = True
151-
self.attrs['opt_type'] = 'lamb'
152-
self.attrs['enable_fp16'] = False
153-
self.attrs['model_path'] = tempfile.TemporaryDirectory()
140+
def set_optimizer(self):
141+
self.optimizer = partial(paddle.optimizer.Lamb, learning_rate=1e-1)
142+
143+
144+
class TestAdamW(TestBase):
145+
def set_optimizer(self):
146+
self.optimizer = partial(paddle.optimizer.AdamW, learning_rate=1e-1)
147+
148+
149+
class TestAdamax(TestBase):
150+
def set_optimizer(self):
151+
self.optimizer = partial(paddle.optimizer.Adamax, learning_rate=1e-1)
152+
153+
154+
class TestAdagrad(TestBase):
155+
def set_optimizer(self):
156+
self.optimizer = partial(paddle.optimizer.Adagrad, learning_rate=1e-1)
157+
158+
159+
class TestAdadelta(TestBase):
160+
def set_optimizer(self):
161+
self.optimizer = partial(paddle.optimizer.Adagrad, learning_rate=1e-1)
162+
163+
164+
class TestRMSProp(TestBase):
165+
def set_optimizer(self):
166+
self.optimizer = partial(paddle.optimizer.RMSProp, learning_rate=1e-1)
167+
168+
169+
class TestCenteredRMSProp(TestBase):
170+
def set_optimizer(self):
171+
self.optimizer = partial(
172+
paddle.optimizer.RMSProp, learning_rate=1e-1, centered=True)
154173

155174

156175
@unittest.skipIf(IPUOpTest.use_ipumodel(), "skip for ipumodel")
157176
class TestSGDFP16(TestBase):
158-
def set_op_attrs(self):
177+
def set_attrs(self):
159178
self.attrs = {}
160179
self.attrs['steps'] = 100
161180
self.attrs['save_at_step'] = 20
162-
self.attrs['is_training'] = True
163-
self.attrs['opt_type'] = 'sgd'
164181
self.attrs['enable_fp16'] = True
165182
self.attrs['model_path'] = tempfile.TemporaryDirectory()
166183

184+
def set_optimizer(self):
185+
self.optimizer = partial(paddle.optimizer.SGD, learning_rate=1e-1)
167186

168-
@unittest.skipIf(IPUOpTest.use_ipumodel(), "skip for ipumodel")
169-
class TestAdamFP16(TestBase):
170-
def set_op_attrs(self):
171-
self.attrs = {}
172-
self.attrs['steps'] = 100
173-
self.attrs['save_at_step'] = 20
174-
self.attrs['is_training'] = True
175-
self.attrs['opt_type'] = 'adam'
176-
self.attrs['enable_fp16'] = True
177-
self.attrs['model_path'] = tempfile.TemporaryDirectory()
178187

188+
class TestMomentumFp16(TestSGDFP16):
189+
def set_optimizer(self):
190+
self.optimizer = partial(paddle.optimizer.Momentum, learning_rate=1e-1)
179191

180-
@unittest.skipIf(IPUOpTest.use_ipumodel(), "skip for ipumodel")
181-
class TestLambFP16(TestBase):
182-
def set_op_attrs(self):
183-
self.attrs = {}
184-
self.attrs['steps'] = 100
185-
self.attrs['save_at_step'] = 20
186-
self.attrs['is_training'] = True
187-
self.attrs['opt_type'] = 'lamb'
188-
self.attrs['enable_fp16'] = True
189-
self.attrs['model_path'] = tempfile.TemporaryDirectory()
192+
193+
class TestAdamFP16(TestSGDFP16):
194+
def set_optimizer(self):
195+
self.optimizer = partial(paddle.optimizer.Adam, learning_rate=1e-1)
196+
197+
198+
class TestLambFP16(TestSGDFP16):
199+
def set_optimizer(self):
200+
self.optimizer = partial(paddle.optimizer.Lamb, learning_rate=1e-1)
201+
202+
203+
class TestAdamWFP16FP16(TestSGDFP16):
204+
def set_optimizer(self):
205+
self.optimizer = partial(paddle.optimizer.AdamW, learning_rate=1e-1)
206+
207+
208+
class TestAdamaxFP16(TestSGDFP16):
209+
def set_optimizer(self):
210+
self.optimizer = partial(paddle.optimizer.Adamax, learning_rate=1e-1)
211+
212+
213+
class TestAdagradFP16(TestSGDFP16):
214+
def set_optimizer(self):
215+
self.optimizer = partial(paddle.optimizer.Adagrad, learning_rate=1e-1)
216+
217+
218+
class TestAdadeltaFP16(TestSGDFP16):
219+
def set_optimizer(self):
220+
self.optimizer = partial(paddle.optimizer.Adagrad, learning_rate=1e-1)
221+
222+
223+
class TestRMSPropFP16(TestSGDFP16):
224+
def set_optimizer(self):
225+
self.optimizer = partial(paddle.optimizer.RMSProp, learning_rate=1e-1)
226+
227+
228+
class TestCenteredRMSPropFP16(TestSGDFP16):
229+
def set_optimizer(self):
230+
self.optimizer = partial(
231+
paddle.optimizer.RMSProp, learning_rate=1e-1, centered=True)
190232

191233

192234
if __name__ == "__main__":

0 commit comments

Comments
 (0)