From e8d24aa144b1f68436e98f4b343aa9d975e67717 Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Thu, 17 May 2018 15:13:17 +0800 Subject: [PATCH 1/3] Inferencer support parallel_executor --- python/paddle/fluid/inferencer.py | 12 ++++++++++-- python/paddle/fluid/trainer.py | 12 ++++++------ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/python/paddle/fluid/inferencer.py b/python/paddle/fluid/inferencer.py index 56c008d1af70f4..8c6dbd3b5ae5d8 100644 --- a/python/paddle/fluid/inferencer.py +++ b/python/paddle/fluid/inferencer.py @@ -17,6 +17,7 @@ import executor import framework import io +import parallel_executor import unique_name from trainer import check_and_get_place @@ -24,7 +25,7 @@ class Inferencer(object): - def __init__(self, infer_func, param_path, place=None): + def __init__(self, infer_func, param_path, place=None, parallel=False): """ :param infer_func: a function that will return predict Variable :param param_path: the path where the inference model is saved by fluid.io.save_params @@ -32,13 +33,20 @@ def __init__(self, infer_func, param_path, place=None): """ self.param_path = param_path self.scope = core.Scope() + self.parallel = parallel + self.place = check_and_get_place(place) self.inference_program = framework.Program() with framework.program_guard(self.inference_program): with unique_name.guard(): self.predict_var = infer_func() - self.exe = executor.Executor(check_and_get_place(place)) + if parallel: + self.exe = parallel_executor.ParallelExecutor( + use_cuda=isinstance(self.place, core.CUDAPlace), + loss_name=self.predict_var.name) + else: + self.exe = executor.Executor(self.place) with executor.scope_guard(self.scope): # load params from param_path into scope io.load_params(self.exe, param_path, self.inference_program) diff --git a/python/paddle/fluid/trainer.py b/python/paddle/fluid/trainer.py index d158d586321833..f4292208c949ea 100644 --- a/python/paddle/fluid/trainer.py +++ b/python/paddle/fluid/trainer.py @@ -12,18 +12,18 @@ # See the License for the specific language governing permissions and # limitations under the License. +import contextlib import os + import core -import framework -import executor + import data_feeder -import contextlib +import executor +import framework import io -import unique_name -import parallel_executor - # optimizer is same as the parameter of Trainer.__init__. Rename it to opt_module import optimizer as opt_module +import parallel_executor from transpiler import distribute_transpiler __all__ = [ From feed94e20f614373986bd749da536caff38fdb5d Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Thu, 17 May 2018 19:50:51 +0800 Subject: [PATCH 2/3] should load parameter before create parallel_executor --- python/paddle/fluid/inferencer.py | 33 +++++++++++-------- .../fit_a_line/test_fit_a_line.py | 2 +- .../test_recognize_digits_conv.py | 2 +- .../test_recognize_digits_mlp.py | 2 +- .../word2vec/no_test_word2vec_new_api.py | 14 ++++---- 5 files changed, 29 insertions(+), 24 deletions(-) diff --git a/python/paddle/fluid/inferencer.py b/python/paddle/fluid/inferencer.py index 8c6dbd3b5ae5d8..0c2620d69268ba 100644 --- a/python/paddle/fluid/inferencer.py +++ b/python/paddle/fluid/inferencer.py @@ -12,6 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +import contextlib + import core import executor @@ -41,31 +43,36 @@ def __init__(self, infer_func, param_path, place=None, parallel=False): with unique_name.guard(): self.predict_var = infer_func() + with self._prog_and_scope_guard(): + # load params from param_path into scope + io.load_params(executor.Executor(self.place), param_path) + if parallel: - self.exe = parallel_executor.ParallelExecutor( - use_cuda=isinstance(self.place, core.CUDAPlace), - loss_name=self.predict_var.name) + with self._prog_and_scope_guard(): + self.exe = parallel_executor.ParallelExecutor( + use_cuda=isinstance(self.place, core.CUDAPlace), + loss_name=self.predict_var.name) else: self.exe = executor.Executor(self.place) - with executor.scope_guard(self.scope): - # load params from param_path into scope - io.load_params(self.exe, param_path, self.inference_program) - def infer(self, inputs, return_numpy=True): + def infer(self, inputs): """ :param inputs: a map of {"input_name": input_var} that will be feed into the inference program to get the predict value - :param return_numpy: if return numpy value for row tensor :return: the predict value of the inference model """ if not isinstance(inputs, dict): raise ValueError( "inputs should be a map of {'input_name': input_var}") - with executor.scope_guard(self.scope): - results = self.exe.run(self.inference_program, - feed=inputs, - fetch_list=[self.predict_var], - return_numpy=return_numpy) + with self._prog_and_scope_guard(): + results = self.exe.run(feed=inputs, + fetch_list=[self.predict_var.name]) return results + + @contextlib.contextmanager + def _prog_and_scope_guard(self): + with framework.program_guard(main_program=self.inference_program): + with executor.scope_guard(self.scope): + yield diff --git a/python/paddle/fluid/tests/book/high-level-api/fit_a_line/test_fit_a_line.py b/python/paddle/fluid/tests/book/high-level-api/fit_a_line/test_fit_a_line.py index fbcf2a282f6421..973142ccdfa3c8 100644 --- a/python/paddle/fluid/tests/book/high-level-api/fit_a_line/test_fit_a_line.py +++ b/python/paddle/fluid/tests/book/high-level-api/fit_a_line/test_fit_a_line.py @@ -94,7 +94,7 @@ def infer(use_cuda, inference_program, save_dirname=None): tensor_x = numpy.random.uniform(0, 10, [batch_size, 13]).astype("float32") results = inferencer.infer({'x': tensor_x}) - print("infer results: ", results[0]) + print("infer results: ", numpy.array(results[0])) def main(use_cuda): diff --git a/python/paddle/fluid/tests/book/high-level-api/recognize_digits/test_recognize_digits_conv.py b/python/paddle/fluid/tests/book/high-level-api/recognize_digits/test_recognize_digits_conv.py index f252a7e2b98b05..c1bae77ec449b3 100644 --- a/python/paddle/fluid/tests/book/high-level-api/recognize_digits/test_recognize_digits_conv.py +++ b/python/paddle/fluid/tests/book/high-level-api/recognize_digits/test_recognize_digits_conv.py @@ -118,7 +118,7 @@ def infer(use_cuda, inference_program, save_dirname=None): results = inferencer.infer({'img': tensor_img}) - print("infer results: ", results[0]) + print("infer results: ", numpy.array(results[0])) def main(use_cuda): diff --git a/python/paddle/fluid/tests/book/high-level-api/recognize_digits/test_recognize_digits_mlp.py b/python/paddle/fluid/tests/book/high-level-api/recognize_digits/test_recognize_digits_mlp.py index 9427a772f54fb5..ae915b8458a728 100644 --- a/python/paddle/fluid/tests/book/high-level-api/recognize_digits/test_recognize_digits_mlp.py +++ b/python/paddle/fluid/tests/book/high-level-api/recognize_digits/test_recognize_digits_mlp.py @@ -99,7 +99,7 @@ def infer(use_cuda, inference_program, save_dirname=None): results = inferencer.infer({'img': tensor_img}) - print("infer results: ", results[0]) + print("infer results: ", numpy.array(results[0])) def main(use_cuda): diff --git a/python/paddle/fluid/tests/book/high-level-api/word2vec/no_test_word2vec_new_api.py b/python/paddle/fluid/tests/book/high-level-api/word2vec/no_test_word2vec_new_api.py index 4f861e5aaeca7c..6d7495e4dd1cd4 100644 --- a/python/paddle/fluid/tests/book/high-level-api/word2vec/no_test_word2vec_new_api.py +++ b/python/paddle/fluid/tests/book/high-level-api/word2vec/no_test_word2vec_new_api.py @@ -127,14 +127,12 @@ def infer(use_cuda, inference_program, save_path): third_word = create_random_lodtensor(lod, place, low=0, high=dict_size - 1) fourth_word = create_random_lodtensor(lod, place, low=0, high=dict_size - 1) - result = inferencer.infer( - { - 'firstw': first_word, - 'secondw': second_word, - 'thirdw': third_word, - 'forthw': fourth_word - }, - return_numpy=False) + result = inferencer.infer({ + 'firstw': first_word, + 'secondw': second_word, + 'thirdw': third_word, + 'forthw': fourth_word + }) print(np.array(result[0])) From d2d671e34107e1193fa4e30314178bb73a6a8c3e Mon Sep 17 00:00:00 2001 From: qiaolongfei Date: Fri, 18 May 2018 09:48:46 +0800 Subject: [PATCH 3/3] add comment --- python/paddle/fluid/inferencer.py | 1 + 1 file changed, 1 insertion(+) diff --git a/python/paddle/fluid/inferencer.py b/python/paddle/fluid/inferencer.py index 0c2620d69268ba..894f6dbfadcaf5 100644 --- a/python/paddle/fluid/inferencer.py +++ b/python/paddle/fluid/inferencer.py @@ -32,6 +32,7 @@ def __init__(self, infer_func, param_path, place=None, parallel=False): :param infer_func: a function that will return predict Variable :param param_path: the path where the inference model is saved by fluid.io.save_params :param place: place to do the inference + :param parallel: use parallel_executor to run the inference, it will use multi CPU/GPU. """ self.param_path = param_path self.scope = core.Scope()