@@ -54,17 +54,24 @@ std::string num2str(T a) {
54
54
}
55
55
} // namespace
56
56
57
- bool NativePaddlePredictor::Init () {
57
+ bool NativePaddlePredictor::Init (
58
+ std::shared_ptr<framework::Scope> parent_scope) {
58
59
VLOG (3 ) << " Predictor::init()" ;
59
60
60
61
if (config_.use_gpu ) {
61
62
place_ = paddle::platform::CUDAPlace (config_.device );
62
63
} else {
63
64
place_ = paddle::platform::CPUPlace ();
64
65
}
65
- paddle::framework::InitDevices (false );
66
+ if (parent_scope) {
67
+ scope_ = parent_scope;
68
+ sub_scope_ = &(parent_scope->NewScope ());
69
+ } else {
70
+ paddle::framework::InitDevices (false );
71
+ scope_.reset (new paddle::framework::Scope ());
72
+ }
73
+
66
74
executor_.reset (new paddle::framework::Executor (place_));
67
- scope_.reset (new paddle::framework::Scope ());
68
75
69
76
// Initialize the inference program
70
77
if (!config_.model_dir .empty ()) {
@@ -83,20 +90,22 @@ bool NativePaddlePredictor::Init() {
83
90
return false ;
84
91
}
85
92
ctx_ = executor_->Prepare (*inference_program_, 0 );
86
-
87
- // Create temporary variables first, so that the first batch do not need to
88
- // create variables in the runtime. This is the logics of the old inference
89
- // API.
90
- // TODO(Superjomn) this should be modified when `Clone` is valid for
91
- // multi-thread application.
92
- executor_->CreateVariables (*inference_program_, scope_.get (), 0 );
93
+ executor_->CreateVariables (
94
+ *inference_program_, sub_scope_ ? sub_scope_ : scope_.get (), 0 );
93
95
94
96
// Get the feed_target_names and fetch_target_names
95
97
feed_target_names_ = inference_program_->GetFeedTargetNames ();
96
98
fetch_target_names_ = inference_program_->GetFetchTargetNames ();
97
99
return true ;
98
100
}
99
101
102
+ NativePaddlePredictor::~NativePaddlePredictor () {
103
+ if (sub_scope_) {
104
+ PADDLE_ENFORCE_NOT_NULL (scope_, " Should have parent scope!" );
105
+ scope_->DeleteScope (sub_scope_);
106
+ }
107
+ };
108
+
100
109
bool NativePaddlePredictor::Run (const std::vector<PaddleTensor> &inputs,
101
110
std::vector<PaddleTensor> *output_data) {
102
111
VLOG (3 ) << " Predictor::predict" ;
@@ -121,11 +130,12 @@ bool NativePaddlePredictor::Run(const std::vector<PaddleTensor> &inputs,
121
130
}
122
131
// Run the inference program
123
132
// if share variables, we need not create variables
124
- executor_->RunPreparedContext (ctx_.get (),
125
- scope_.get (),
126
- &feed_targets,
127
- &fetch_targets,
128
- false /* don't create variable eatch time */ );
133
+ executor_->RunPreparedContext (
134
+ ctx_.get (),
135
+ sub_scope_ != nullptr ? sub_scope_ : scope_.get (),
136
+ &feed_targets,
137
+ &fetch_targets,
138
+ false /* don't create variable eatch time */ );
129
139
if (!GetFetch (fetchs, output_data)) {
130
140
LOG (ERROR) << " fail to get fetchs" ;
131
141
return false ;
@@ -138,7 +148,7 @@ std::unique_ptr<PaddlePredictor> NativePaddlePredictor::Clone() {
138
148
VLOG (3 ) << " Predictor::clone" ;
139
149
std::unique_ptr<PaddlePredictor> cls (new NativePaddlePredictor (config_));
140
150
141
- if (!dynamic_cast <NativePaddlePredictor *>(cls.get ())->Init ()) {
151
+ if (!dynamic_cast <NativePaddlePredictor *>(cls.get ())->Init (scope_ )) {
142
152
LOG (ERROR) << " fail to call Init" ;
143
153
return nullptr ;
144
154
}
@@ -266,7 +276,7 @@ CreatePaddlePredictor<NativeConfig, PaddleEngineKind::kNative>(
266
276
}
267
277
268
278
std::unique_ptr<PaddlePredictor> predictor (new NativePaddlePredictor (config));
269
- if (!dynamic_cast <NativePaddlePredictor *>(predictor.get ())->Init ()) {
279
+ if (!dynamic_cast <NativePaddlePredictor *>(predictor.get ())->Init (nullptr )) {
270
280
return nullptr ;
271
281
}
272
282
return std::move (predictor);
0 commit comments