Skip to content

Commit 109ee92

Browse files
panyx0718Superjomn
authored andcommitted
add tests and polish infer impl (#11009)
1 parent 1490551 commit 109ee92

File tree

4 files changed

+128
-68
lines changed

4 files changed

+128
-68
lines changed

paddle/contrib/inference/CMakeLists.txt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
# limitations under the License.
1414
#
1515

16-
function(inference_api_test TARGET_NAME TEST_SRC DEP_TEST)
16+
function(inference_api_test TARGET_NAME TEST_SRC)
1717
set(options "")
1818
set(oneValueArgs "")
1919
set(multiValueArgs ARGS)
@@ -34,6 +34,8 @@ function(inference_api_test TARGET_NAME TEST_SRC DEP_TEST)
3434
SRCS ${TEST_SRC}
3535
DEPS paddle_fluid_api paddle_inference_api paddle_inference_api_impl
3636
ARGS --dirname=${PYTHON_TESTS_DIR}/book/)
37+
# TODO(panyx0178): Figure out how to add word2vec and image_classification
38+
# as deps.
3739
# set_tests_properties(${TARGET_NAME}
3840
# PROPERTIES DEPENDS ${DEP_TEST})
3941
endforeach()
@@ -53,5 +55,4 @@ cc_test(test_paddle_inference_api
5355
DEPS paddle_inference_api)
5456

5557
inference_api_test(test_paddle_inference_api_impl
56-
test_paddle_inference_api_impl.cc
57-
test_word2vec)
58+
test_paddle_inference_api_impl.cc)

paddle/contrib/inference/paddle_inference_api_impl.cc

Lines changed: 26 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,8 @@ bool PaddlePredictorImpl::Run(const std::vector<PaddleTensor> &inputs,
102102
Timer timer;
103103
timer.tic();
104104
// set feed variable
105-
std::map<std::string, const paddle::framework::LoDTensor *> feed_targets;
106-
std::vector<paddle::framework::LoDTensor> feeds;
105+
std::map<std::string, const framework::LoDTensor *> feed_targets;
106+
std::vector<framework::LoDTensor> feeds;
107107
if (!SetFeed(inputs, &feeds)) {
108108
LOG(ERROR) << "fail to set feed";
109109
return false;
@@ -112,8 +112,8 @@ bool PaddlePredictorImpl::Run(const std::vector<PaddleTensor> &inputs,
112112
feed_targets[feed_target_names_[i]] = &feeds[i];
113113
}
114114
// get fetch variable
115-
std::map<std::string, paddle::framework::LoDTensor *> fetch_targets;
116-
std::vector<paddle::framework::LoDTensor> fetchs;
115+
std::map<std::string, framework::LoDTensor *> fetch_targets;
116+
std::vector<framework::LoDTensor> fetchs;
117117
fetchs.resize(fetch_target_names_.size());
118118
for (size_t i = 0; i < fetch_target_names_.size(); ++i) {
119119
fetch_targets[fetch_target_names_[i]] = &fetchs[i];
@@ -149,28 +149,27 @@ bool PaddlePredictorImpl::InitShared() {
149149
VLOG(3) << "Predictor::init_shared";
150150
// 1. Define place, executor, scope
151151
if (this->config_.device >= 0) {
152-
place_ = paddle::platform::CUDAPlace();
152+
place_ = platform::CUDAPlace();
153153
} else {
154-
place_ = paddle::platform::CPUPlace();
154+
place_ = platform::CPUPlace();
155155
}
156-
this->executor_.reset(new paddle::framework::Executor(this->place_));
157-
this->scope_.reset(new paddle::framework::Scope());
156+
this->executor_.reset(new framework::Executor(this->place_));
157+
this->scope_.reset(new framework::Scope());
158158
// Initialize the inference program
159159
if (!this->config_.model_dir.empty()) {
160160
// Parameters are saved in separate files sited in
161161
// the specified `dirname`.
162-
this->inference_program_ = paddle::inference::Load(
162+
this->inference_program_ = inference::Load(
163163
this->executor_.get(), this->scope_.get(), this->config_.model_dir);
164164
} else if (!this->config_.prog_file.empty() &&
165165
!this->config_.param_file.empty()) {
166166
// All parameters are saved in a single file.
167167
// The file names should be consistent with that used
168168
// in Python API `fluid.io.save_inference_model`.
169-
this->inference_program_ =
170-
paddle::inference::Load(this->executor_.get(),
171-
this->scope_.get(),
172-
this->config_.prog_file,
173-
this->config_.param_file);
169+
this->inference_program_ = inference::Load(this->executor_.get(),
170+
this->scope_.get(),
171+
this->config_.prog_file,
172+
this->config_.param_file);
174173
}
175174
this->ctx_ = this->executor_->Prepare(*this->inference_program_, 0);
176175
// 3. create variables
@@ -185,24 +184,21 @@ bool PaddlePredictorImpl::InitShared() {
185184
return true;
186185
}
187186

188-
bool PaddlePredictorImpl::SetFeed(
189-
const std::vector<PaddleTensor> &inputs,
190-
std::vector<paddle::framework::LoDTensor> *feeds) {
187+
bool PaddlePredictorImpl::SetFeed(const std::vector<PaddleTensor> &inputs,
188+
std::vector<framework::LoDTensor> *feeds) {
191189
VLOG(3) << "Predictor::set_feed";
192190
if (inputs.size() != feed_target_names_.size()) {
193191
LOG(ERROR) << "wrong feed input size.";
194192
return false;
195193
}
196194
for (size_t i = 0; i < feed_target_names_.size(); ++i) {
197-
paddle::framework::LoDTensor input;
198-
paddle::framework::DDim ddim =
199-
paddle::framework::make_ddim(inputs[i].shape);
195+
framework::LoDTensor input;
196+
framework::DDim ddim = framework::make_ddim(inputs[i].shape);
200197
void *input_ptr;
201198
if (inputs[i].dtype == PaddleDType::INT64) {
202-
input_ptr =
203-
input.mutable_data<int64_t>(ddim, paddle::platform::CPUPlace());
199+
input_ptr = input.mutable_data<int64_t>(ddim, platform::CPUPlace());
204200
} else if (inputs[i].dtype == PaddleDType::FLOAT32) {
205-
input_ptr = input.mutable_data<float>(ddim, paddle::platform::CPUPlace());
201+
input_ptr = input.mutable_data<float>(ddim, platform::CPUPlace());
206202
} else {
207203
LOG(ERROR) << "unsupported feed type " << inputs[i].dtype;
208204
return false;
@@ -213,13 +209,12 @@ bool PaddlePredictorImpl::SetFeed(
213209
inputs[i].data.data,
214210
inputs[i].data.length);
215211
feeds->push_back(input);
216-
LOG(ERROR) << "Actual feed type " << feeds->back().type().name();
217212
}
218213
return true;
219214
}
220215

221216
bool PaddlePredictorImpl::GetFetch(
222-
const std::vector<paddle::framework::LoDTensor> &fetchs,
217+
const std::vector<framework::LoDTensor> &fetchs,
223218
std::vector<PaddleTensor> *outputs) {
224219
VLOG(3) << "Predictor::get_fetch";
225220
outputs->resize(fetchs.size());
@@ -284,8 +279,9 @@ bool PaddlePredictorImpl::GetFetch(
284279
return true;
285280
}
286281

287-
std::unique_ptr<PaddlePredictorImpl> CreatePaddlePredictorImpl(
288-
const VisConfig &config) {
282+
template <>
283+
std::unique_ptr<PaddlePredictor> CreatePaddlePredictor(
284+
const ConfigImpl &config) {
289285
VLOG(3) << "create PaddlePredictorImpl";
290286
// 1. GPU memeroy
291287
std::vector<std::string> flags;
@@ -299,12 +295,11 @@ std::unique_ptr<PaddlePredictorImpl> CreatePaddlePredictorImpl(
299295
framework::InitGflags(flags);
300296
}
301297

302-
std::unique_ptr<PaddlePredictorImpl> predictor(
303-
new PaddlePredictorImpl(config));
304-
if (!predictor->Init()) {
298+
std::unique_ptr<PaddlePredictor> predictor(new PaddlePredictorImpl(config));
299+
if (!dynamic_cast<PaddlePredictorImpl *>(predictor.get())->Init()) {
305300
return nullptr;
306301
}
307-
return predictor;
302+
return std::move(predictor);
308303
}
309304

310305
} // namespace paddle

paddle/contrib/inference/paddle_inference_api_impl.h

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,17 @@
2929

3030
namespace paddle {
3131

32-
struct VisConfig : public PaddlePredictor::Config {
32+
struct ConfigImpl : public PaddlePredictor::Config {
3333
int device;
3434
float fraction_of_gpu_memory;
3535
std::string prog_file;
3636
std::string param_file;
3737
bool share_variables;
3838
};
3939

40-
/*
41-
* Do not use this, just a demo indicating how to customize a Predictor.
42-
*/
4340
class PaddlePredictorImpl : public PaddlePredictor {
4441
public:
45-
explicit PaddlePredictorImpl(const VisConfig &config) : config_(config) {}
42+
explicit PaddlePredictorImpl(const ConfigImpl &config) : config_(config) {}
4643

4744
bool Init();
4845

@@ -56,21 +53,18 @@ class PaddlePredictorImpl : public PaddlePredictor {
5653
private:
5754
bool InitShared() override;
5855
bool SetFeed(const std::vector<PaddleTensor> &input_datas,
59-
std::vector<paddle::framework::LoDTensor> *feeds);
60-
bool GetFetch(const std::vector<paddle::framework::LoDTensor> &fetchs,
56+
std::vector<framework::LoDTensor> *feeds);
57+
bool GetFetch(const std::vector<framework::LoDTensor> &fetchs,
6158
std::vector<PaddleTensor> *output_data);
6259

63-
VisConfig config_;
64-
paddle::platform::Place place_;
65-
std::unique_ptr<paddle::framework::Executor> executor_;
66-
std::unique_ptr<paddle::framework::Scope> scope_;
67-
std::unique_ptr<paddle::framework::ExecutorPrepareContext> ctx_;
68-
std::unique_ptr<paddle::framework::ProgramDesc> inference_program_;
60+
ConfigImpl config_;
61+
platform::Place place_;
62+
std::unique_ptr<framework::Executor> executor_;
63+
std::unique_ptr<framework::Scope> scope_;
64+
std::unique_ptr<framework::ExecutorPrepareContext> ctx_;
65+
std::unique_ptr<framework::ProgramDesc> inference_program_;
6966
std::vector<std::string> feed_target_names_;
7067
std::vector<std::string> fetch_target_names_;
7168
};
7269

73-
std::unique_ptr<PaddlePredictorImpl> CreatePaddlePredictorImpl(
74-
const VisConfig &config);
75-
7670
} // namespace paddle

paddle/contrib/inference/test_paddle_inference_api_impl.cc

Lines changed: 88 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,19 @@ PaddleTensor LodTensorToPaddleTensor(framework::LoDTensor* t) {
4040
return pt;
4141
}
4242

43-
TEST(paddle_inference_api_impl, word2vec) {
44-
VisConfig config;
43+
ConfigImpl GetConfig() {
44+
ConfigImpl config;
4545
config.model_dir = FLAGS_dirname + "word2vec.inference.model";
4646
LOG(INFO) << "dirname " << config.model_dir;
4747
config.fraction_of_gpu_memory = 0.15;
4848
config.device = 0;
4949
config.share_variables = true;
50+
return config;
51+
}
5052

51-
std::unique_ptr<PaddlePredictorImpl> predictor =
52-
CreatePaddlePredictorImpl(config);
53+
TEST(paddle_inference_api_impl, word2vec) {
54+
ConfigImpl config = GetConfig();
55+
std::unique_ptr<PaddlePredictor> predictor = CreatePaddlePredictor(config);
5356

5457
framework::LoDTensor first_word, second_word, third_word, fourth_word;
5558
framework::LoD lod{{0, 1}};
@@ -60,24 +63,91 @@ TEST(paddle_inference_api_impl, word2vec) {
6063
SetupLoDTensor(&third_word, lod, static_cast<int64_t>(0), dict_size - 1);
6164
SetupLoDTensor(&fourth_word, lod, static_cast<int64_t>(0), dict_size - 1);
6265

63-
std::vector<PaddleTensor> cpu_feeds;
64-
cpu_feeds.push_back(LodTensorToPaddleTensor(&first_word));
65-
cpu_feeds.push_back(LodTensorToPaddleTensor(&second_word));
66-
cpu_feeds.push_back(LodTensorToPaddleTensor(&third_word));
67-
cpu_feeds.push_back(LodTensorToPaddleTensor(&fourth_word));
66+
std::vector<PaddleTensor> paddle_tensor_feeds;
67+
paddle_tensor_feeds.push_back(LodTensorToPaddleTensor(&first_word));
68+
paddle_tensor_feeds.push_back(LodTensorToPaddleTensor(&second_word));
69+
paddle_tensor_feeds.push_back(LodTensorToPaddleTensor(&third_word));
70+
paddle_tensor_feeds.push_back(LodTensorToPaddleTensor(&fourth_word));
71+
72+
std::vector<PaddleTensor> outputs;
73+
ASSERT_TRUE(predictor->Run(paddle_tensor_feeds, &outputs));
74+
ASSERT_EQ(outputs.size(), 1UL);
75+
size_t len = outputs[0].data.length;
76+
float* data = static_cast<float*>(outputs[0].data.data);
77+
for (int j = 0; j < len / sizeof(float); ++j) {
78+
ASSERT_LT(data[j], 1.0);
79+
ASSERT_GT(data[j], -1.0);
80+
}
81+
82+
std::vector<paddle::framework::LoDTensor*> cpu_feeds;
83+
cpu_feeds.push_back(&first_word);
84+
cpu_feeds.push_back(&second_word);
85+
cpu_feeds.push_back(&third_word);
86+
cpu_feeds.push_back(&fourth_word);
87+
88+
framework::LoDTensor output1;
89+
std::vector<paddle::framework::LoDTensor*> cpu_fetchs1;
90+
cpu_fetchs1.push_back(&output1);
91+
92+
TestInference<platform::CPUPlace>(config.model_dir, cpu_feeds, cpu_fetchs1);
93+
94+
float* lod_data = output1.data<float>();
95+
for (size_t i = 0; i < output1.numel(); ++i) {
96+
EXPECT_LT(lod_data[i] - data[i], 1e-3);
97+
EXPECT_GT(lod_data[i] - data[i], -1e-3);
98+
}
99+
100+
free(outputs[0].data.data);
101+
}
102+
103+
TEST(paddle_inference_api_impl, image_classification) {
104+
int batch_size = 2;
105+
bool use_mkldnn = false;
106+
bool repeat = false;
107+
ConfigImpl config = GetConfig();
108+
config.model_dir =
109+
FLAGS_dirname + "image_classification_resnet.inference.model";
110+
111+
const bool is_combined = false;
112+
std::vector<std::vector<int64_t>> feed_target_shapes =
113+
GetFeedTargetShapes(config.model_dir, is_combined);
114+
115+
framework::LoDTensor input;
116+
// Use normilized image pixels as input data,
117+
// which should be in the range [0.0, 1.0].
118+
feed_target_shapes[0][0] = batch_size;
119+
framework::DDim input_dims = framework::make_ddim(feed_target_shapes[0]);
120+
SetupTensor<float>(
121+
&input, input_dims, static_cast<float>(0), static_cast<float>(1));
122+
std::vector<framework::LoDTensor*> cpu_feeds;
123+
cpu_feeds.push_back(&input);
124+
125+
framework::LoDTensor output1;
126+
std::vector<framework::LoDTensor*> cpu_fetchs1;
127+
cpu_fetchs1.push_back(&output1);
128+
129+
TestInference<platform::CPUPlace, false, true>(config.model_dir,
130+
cpu_feeds,
131+
cpu_fetchs1,
132+
repeat,
133+
is_combined,
134+
use_mkldnn);
135+
136+
std::unique_ptr<PaddlePredictor> predictor = CreatePaddlePredictor(config);
137+
std::vector<PaddleTensor> paddle_tensor_feeds;
138+
paddle_tensor_feeds.push_back(LodTensorToPaddleTensor(&input));
68139

69140
std::vector<PaddleTensor> outputs;
70-
ASSERT_TRUE(predictor->Run(cpu_feeds, &outputs));
141+
ASSERT_TRUE(predictor->Run(paddle_tensor_feeds, &outputs));
71142
ASSERT_EQ(outputs.size(), 1UL);
72-
for (size_t i = 0; i < outputs.size(); ++i) {
73-
size_t len = outputs[i].data.length;
74-
float* data = static_cast<float*>(outputs[i].data.data);
75-
for (size_t j = 0; j < len / sizeof(float); ++j) {
76-
ASSERT_LT(data[j], 1.0);
77-
ASSERT_GT(data[j], -1.0);
78-
}
79-
free(outputs[i].data.data);
143+
size_t len = outputs[0].data.length;
144+
float* data = static_cast<float*>(outputs[0].data.data);
145+
float* lod_data = output1.data<float>();
146+
for (size_t j = 0; j < len / sizeof(float); ++j) {
147+
EXPECT_LT(lod_data[j] - data[j], 1e-10);
148+
EXPECT_GT(lod_data[j] - data[j], -1e-10);
80149
}
150+
free(data);
81151
}
82152

83153
} // namespace paddle

0 commit comments

Comments
 (0)