From fb66355ef5486f2e1c7a1c476daf2da55138b60d Mon Sep 17 00:00:00 2001 From: wangchaochaohu Date: Mon, 11 Jan 2021 16:12:24 +0800 Subject: [PATCH] [cherry-pick]add support for place string representation #30264 cherry-pick #28769, add support for place string representation --- .../reader/create_double_buffer_reader_op.cc | 9 +-- python/paddle/fluid/compiler.py | 12 +++- .../quantization/quant2_int8_mkldnn_pass.py | 3 +- .../quantization/quant_int8_mkldnn_pass.py | 6 +- .../slim/quantization/quantization_pass.py | 33 ++++++---- python/paddle/fluid/dygraph/base.py | 17 ++++-- python/paddle/fluid/executor.py | 6 +- python/paddle/fluid/framework.py | 61 +++++++++++++++++++ python/paddle/fluid/generator.py | 8 ++- python/paddle/fluid/layers/io.py | 7 ++- python/paddle/fluid/reader.py | 45 ++++++++++++-- .../unittests/test_py_reader_error_msg.py | 15 +++++ .../fluid/tests/unittests/test_var_base.py | 3 + python/paddle/hapi/model.py | 3 +- python/paddle/tensor/creation.py | 16 ++--- 15 files changed, 196 insertions(+), 48 deletions(-) diff --git a/paddle/fluid/operators/reader/create_double_buffer_reader_op.cc b/paddle/fluid/operators/reader/create_double_buffer_reader_op.cc index 15971af58c..44db3f3a33 100644 --- a/paddle/fluid/operators/reader/create_double_buffer_reader_op.cc +++ b/paddle/fluid/operators/reader/create_double_buffer_reader_op.cc @@ -47,11 +47,12 @@ class CreateDoubleBufferReaderOp : public framework::OperatorBase { platform::Place place; if (place_str == "AUTO") { place = dev_place; - } else if (place_str == "CPU") { + } else if (place_str == "CPUPLACE") { place = platform::CPUPlace(); } else { + place_str = place_str.substr(0, place_str.length() - 1); std::istringstream sin(place_str); - sin.seekg(std::string("CUDA:").size(), std::ios::beg); + sin.seekg(std::string("CUDAPLACE(").size(), std::ios::beg); size_t num; sin >> num; place = platform::CUDAPlace(static_cast(num)); @@ -78,9 +79,9 @@ class CreateDoubleBufferReaderOpMaker : public DecoratedReaderMakerBase { std::unordered_set enum_range; constexpr size_t kMaxCUDADevs = 128; for (size_t i = 0; i < kMaxCUDADevs; ++i) { - enum_range.insert(string::Sprintf("CUDA:%d", i)); + enum_range.insert(string::Sprintf("CUDAPLACE(%d)", i)); } - enum_range.insert("CPU"); + enum_range.insert("CPUPLACE"); enum_range.insert("AUTO"); AddAttr("place", "The double buffer place") .SetDefault("AUTO") diff --git a/python/paddle/fluid/compiler.py b/python/paddle/fluid/compiler.py index a07378a6f5..cf4a0ee56e 100644 --- a/python/paddle/fluid/compiler.py +++ b/python/paddle/fluid/compiler.py @@ -20,6 +20,8 @@ from .. import compat as cpt from . import framework from .framework import cuda_places, cpu_places, xpu_places +from .framework import _get_paddle_place, _get_paddle_place_list +from .framework import cuda_places, cpu_places, xpu_places from . import core __all__ = ['CompiledProgram', 'ExecutionStrategy', 'BuildStrategy'] @@ -202,7 +204,7 @@ class CompiledProgram(object): Tensors to other devices when it is first executed, the CompiledProgram specified by share_vars_from must be run before the current CompiledProgram. The default is None. - places(list(CUDAPlace)|list(CPUPlace)|None): This parameter specifies the device + places(list(CUDAPlace)|list(CPUPlace)|list(str)|None): This parameter specifies the device on which the model is running. If you want to run on GPU0 and GPU1, places are [fluid.CUDAPlace(0), fluid.CUDAPlace(1)]; if you want to run with 2 CPUs, places are [fluid.CPUPlace()] * 2. If the parameter is not set, i.e. the parameter is None, @@ -213,7 +215,8 @@ class CompiledProgram(object): CPU number is obtained from the environment variable CPU_NUM. For example, export CPU_NUM=4, if the environment variable is not set, the executor will add the variable to the environment variable and set its value to 1. - The default is None. + The default is None. If ``places`` is the list of string, the string in the list + can be ``cpu``, ``gpu:x``, where ``x`` is the index of the GPUs. Returns: CompiledProgram @@ -282,7 +285,10 @@ class CompiledProgram(object): self._exec_strategy = exec_strategy self._loss_name = loss_name self._share_vars_from = share_vars_from - self._places = places + if isinstance(places, (list, tuple)): + self._places = _get_paddle_place_list(places) + else: + self._places = _get_paddle_place(places) if _has_backward_op(self._graph): assert self._loss_name is not None, "The loss name of CompiledProgram is None. The loss name should be set if CompiledProgram contains backward part." diff --git a/python/paddle/fluid/contrib/slim/quantization/quant2_int8_mkldnn_pass.py b/python/paddle/fluid/contrib/slim/quantization/quant2_int8_mkldnn_pass.py index 7e1db69703..0f44d7240e 100644 --- a/python/paddle/fluid/contrib/slim/quantization/quant2_int8_mkldnn_pass.py +++ b/python/paddle/fluid/contrib/slim/quantization/quant2_int8_mkldnn_pass.py @@ -15,6 +15,7 @@ import numpy as np from .... import core from ....framework import IrGraph +from ....framework import _get_paddle_place __all__ = ['Quant2Int8MkldnnPass'] @@ -43,7 +44,7 @@ class Quant2Int8MkldnnPass(object): _core=None, _debug=False): self._scope = _scope - self._place = _place + self._place = _get_paddle_place(_place) self._core = _core self._debug = _debug self._fake_quantize_types = [ diff --git a/python/paddle/fluid/contrib/slim/quantization/quant_int8_mkldnn_pass.py b/python/paddle/fluid/contrib/slim/quantization/quant_int8_mkldnn_pass.py index d31dc35d14..2ed06a48c2 100644 --- a/python/paddle/fluid/contrib/slim/quantization/quant_int8_mkldnn_pass.py +++ b/python/paddle/fluid/contrib/slim/quantization/quant_int8_mkldnn_pass.py @@ -16,6 +16,7 @@ import numpy as np from .... import core from ....framework import IrGraph from ....framework import IrNode +from ....framework import _get_paddle_place __all__ = ['QuantInt8MkldnnPass'] @@ -40,7 +41,8 @@ class QuantInt8MkldnnPass(object): r""" Args: scope(fluid.Scope): scope is used to initialize the new parameters. - place(fluid.CPUPlace): place is used to initialize the new parameters. + place(fluid.CPUPlace|str): place is used to initialize the new parameters. + When it is string, it can be only 'cpu'. Examples: @@ -60,7 +62,7 @@ class QuantInt8MkldnnPass(object): """ self._scope = _scope - self._place = _place + self._place = _get_paddle_place(_place) self._quantize_type = [ 'fake_quantize_moving_average_abs_max', diff --git a/python/paddle/fluid/contrib/slim/quantization/quantization_pass.py b/python/paddle/fluid/contrib/slim/quantization/quantization_pass.py index 219025269f..0017c29cbd 100644 --- a/python/paddle/fluid/contrib/slim/quantization/quantization_pass.py +++ b/python/paddle/fluid/contrib/slim/quantization/quantization_pass.py @@ -25,6 +25,7 @@ from ....framework import Program, program_guard, default_startup_program from ....data import data from ....layers import mean from ....executor import scope_guard +from ....framework import _get_paddle_place __all__ = [ 'QuantizationTransformPass', 'QuantizationFreezePass', 'ConvertToInt8Pass', @@ -246,8 +247,9 @@ class QuantizationTransformPass(object): scope(fluid.Scope): When activation use 'range_abs_max' as the quantize type, this pass will create some new parameters. The scope is used to initialize these new parameters. - place(fluid.CPUPlace|fluid.CUDAPlace): place is used to initialize new - parameters described above. + place(fluid.CPUPlace|fluid.CUDAPlace|str): place is used to initialize new + parameters described above. If it's string, It can be ``cpu``, and ``gpu:x``, + where ``x`` is the index of the GPUs. weight_bits(int): quantization bit number for weights, the bias is not quantized. activation_bits(int): quantization bit number for activation. @@ -315,7 +317,7 @@ class QuantizationTransformPass(object): transform_pass.apply(graph) """ self._scope = scope - self._place = place + self._place = _get_paddle_place(place) self._weight_bits = weight_bits self._activation_bits = activation_bits self._skip_pattern = skip_pattern @@ -1057,7 +1059,8 @@ class QuantizationFreezePass(object): Args: scope(fluid.Scope): scope is used to get the weight tensor values. - place(fluid.CPUPlace|fluid.CUDAPlace): place is used to restore the weight tensors. + place(fluid.CPUPlace|fluid.CUDAPlace|str): place is used to restore the weight tensors. + If it's string, It can be ``cpu``, and ``gpu:x``, where ``x`` is the index of the GPUs. weight_bits(int): quantization bit number for weights. activation_bits(int): quantization bit number for activation. weight_quantize_type(str): quantization type for weights, support 'abs_max' and @@ -1071,7 +1074,7 @@ class QuantizationFreezePass(object): assert place is not None, \ 'The place cannot be set None.' self._scope = scope - self._place = place + self._place = _get_paddle_place(place) self._weight_bits = weight_bits self._activation_bits = activation_bits self._weight_quantize_type = weight_quantize_type @@ -1365,8 +1368,9 @@ class ConvertToInt8Pass(object): Args: scope(fluid.Scope): scope is used to get the weight tensor values. - place(fluid.CPUPlace|fluid.CUDAPlace): place is used to restore the - 8bits weight tensors. + place(fluid.CPUPlace|fluid.CUDAPlace|str): place is used to restore the + 8bits weight tensors. If it's string, It can be ``cpu``, and ``gpu:x``, + where ``x`` is the index of the GPUs. quantizable_op_type(list[str]): This input param will be removed latter. The pass will process all quantized op, so it is not necessary to set the input param. """ @@ -1375,7 +1379,7 @@ class ConvertToInt8Pass(object): assert place is not None, \ 'The place cannot be set None.' self._scope = scope - self._place = place + self._place = _get_paddle_place(place) def apply(self, graph): """ @@ -1495,11 +1499,13 @@ class OutScaleForTrainingPass(object): Args: scope(fluid.Scope): The scope is used to initialize these new parameters. - place(fluid.CPUPlace|fluid.CUDAPlace): The place is used to initialize new parameters. + place(fluid.CPUPlace|fluid.CUDAPlace|str): The place is used to initialize new parameters. + If it's string, It can be ``cpu``, and ``gpu:x``, where ``x`` is the + index of the GPUs. moving_rate(float): The decay coefficient of moving average. The default value is 0.9. """ self._scope = scope - self._place = place + self._place = _get_paddle_place(place) self._moving_rate = moving_rate self._is_test = None self._teller_set = _out_scale_op_list @@ -1688,8 +1694,9 @@ class AddQuantDequantPass(object): Args: scope(fluid.Scope): The scope is used to initialize these new parameters. - place(fluid.CPUPlace|fluid.CUDAPlace): place is used to initialize new - parameters described above. + place(fluid.CPUPlace|fluid.CUDAPlace|str): place is used to initialize new + parameters described above. If ``place`` is string, it can be It can be ``cpu`` + or ``gpu:x``, where ``x`` is the index of the GPUs. moving_rate(float, optional): the param for 'quant_dequant_moving_average_abs_max' quantization. Default is 0.9. quant_bits(int, optional): quantization bit number for activation. Default is 8. @@ -1705,7 +1712,7 @@ class AddQuantDequantPass(object): quantizable_op_type. """ self._scope = scope - self._place = place + self._place = _get_paddle_place(place) self._moving_rate = moving_rate self._quant_bits = quant_bits self._is_test = None diff --git a/python/paddle/fluid/dygraph/base.py b/python/paddle/fluid/dygraph/base.py index b63941206e..11c836c916 100644 --- a/python/paddle/fluid/dygraph/base.py +++ b/python/paddle/fluid/dygraph/base.py @@ -25,6 +25,7 @@ from .tracer import Tracer import logging from ..data_feeder import convert_dtype import warnings +from ..framework import _get_paddle_place __all__ = [ 'no_grad', 'no_grad_', 'grad', 'guard', 'enable_dygraph', 'disable_dygraph', @@ -128,8 +129,9 @@ def enable_dygraph(place=None): This API turn OFF static graph mode. You can turn ON static graph mode by `enable_static <./disable_dygraph_en.html>`_ . Parameters: - place(paddle.CPUPlace|paddle.CUDAPlace, optional): Place to run dynamic graph. Default: None. Which means that the running place will be - determined according to the way of paddle compilation. + place(paddle.CPUPlace|paddle.CUDAPlace|str, optional): Place to run dynamic graph. Default: None. Which means that the running place will be + determined according to the way of paddle compilation. If ``place`` is string, It can be ``cpu``, and ``gpu:x``, where ``x`` is the + index of the GPUs. return: None @@ -149,7 +151,8 @@ def enable_dygraph(place=None): """ global _functional_dygraph_context_manager if _functional_dygraph_context_manager is None: - _functional_dygraph_context_manager = guard(place=place) + _functional_dygraph_context_manager = guard( + place=_get_paddle_place(place)) _functional_dygraph_context_manager.__enter__() # call disable_dygraph when Python exit @@ -343,8 +346,10 @@ def guard(place=None): This context will create a dygraph context for dygraph to run, using python ``with`` statement. Parameters: - place(fluid.CPUPlace or fluid.CUDAPlace, optional): Place to execute dygraph. - If None, the running place will be determined according to the way of paddle compilation. Default: None + place(fluid.CPUPlace| fluid.CUDAPlace|str, optional): Place to execute dygraph. + If None, the running place will be determined according to the way of paddle compilation. + If ``place`` is string, It can be ``cpu``, ``gpu:x`` and ``xpu:x``, where ``x`` is the + index of the GPUs or XPUs. Default: None return: None @@ -371,7 +376,7 @@ def guard(place=None): VarBase = core.VarBase if place is not None: - expected_place = place + expected_place = _get_paddle_place(place) else: expected_place = framework._current_expected_place() tracer._expected_place = expected_place diff --git a/python/paddle/fluid/executor.py b/python/paddle/fluid/executor.py index 9b17d61c33..9b0b04a6ea 100644 --- a/python/paddle/fluid/executor.py +++ b/python/paddle/fluid/executor.py @@ -480,11 +480,13 @@ class Executor(object): and single/multiple-CPU running. Args: - place(paddle.CPUPlace()|paddle.CUDAPlace(n)|None): This parameter represents + place(paddle.CPUPlace()|paddle.CUDAPlace(n)|str|None): This parameter represents which device the executor runs on. When this parameter is None, PaddlePaddle will set the default device according to its installation version. If Paddle is CPU version, the default device would be set to `CPUPlace()` . If Paddle is GPU version, the default device would be set to `CUDAPlace(0)` . Default is None. + If ``place`` is string, it can be ``cpu``, and ``gpu:x``, where ``x`` + is the index of the GPUs. Returns: Executor @@ -550,7 +552,7 @@ class Executor(object): expected_place = framework._current_expected_place() self.place = expected_place else: - self.place = place + self.place = framework._get_paddle_place(place) self.program_caches = dict() self.ctx_caches = dict() self.scope_caches = dict() diff --git a/python/paddle/fluid/framework.py b/python/paddle/fluid/framework.py index ac2fa5c0bd..c1e048b769 100644 --- a/python/paddle/fluid/framework.py +++ b/python/paddle/fluid/framework.py @@ -5801,3 +5801,64 @@ def get_flags(flags): else: raise TypeError('Flags in get_flags should be a list, tuple or string.') return flags_value + + +def _get_paddle_place(place): + "convert the string to paddle Place" + if place is None: + return place + if isinstance(place, (core.Place, core.XPUPlace, core.CPUPlace, + core.CUDAPinnedPlace, core.CUDAPlace)): + return place + + if not isinstance(place, str): + raise ValueError( + "place only support string which is 'Place' and so on.") + + place = place.lower() + if (place == "cpu"): + return core.CPUPlace() + if (place == "device"): + return core.Place() + + avaliable_gpu_place = re.match(r'gpu:\d+', place) + if place == "gpu_pinned" or place == "gpu" or avaliable_gpu_place: + if not core.is_compiled_with_cuda(): + raise ValueError( + "The device should not be {}, since PaddlePaddle is " \ + "not compiled with CUDA".format(avaliable_gpu_place)) + if place == "gpu_pinned": + return core.CUDAPinnedPlace() + elif place == "gpu": + return core.CUDAPlace(0) + else: + place_info_list = place.split(':', 1) + device_id = place_info_list[1] + device_id = int(device_id) + return core.CUDAPlace(device_id) + avaliable_xpu_place = re.match(r'xpu:\d+', place) + if avaliable_xpu_place: + if not core.is_compiled_with_xpu(): + raise ValueError( + "The device should not be {}, since PaddlePaddle is " \ + "not compiled with XPU".format(avaliable_xpu_place)) + place_info_list = place.split(':', 1) + device_id = place_info_list[1] + device_id = int(device_id) + return core.XPUPlace(device_id) + raise ValueError( + "paddle support CPUPlace, CUDAPlace,CUDAPinnedPlace and XPUPlace, Please check your Place Input" + ) + + +def _get_paddle_place_list(places): + + if not isinstance(places, (list, tuple)): + raise TypeError("places must to be List or Tuple") + + ret = [] + for p in places: + p = _get_paddle_place(p) + ret.append(p) + + return ret diff --git a/python/paddle/fluid/generator.py b/python/paddle/fluid/generator.py index 98924f8014..7ce2d6a4bf 100644 --- a/python/paddle/fluid/generator.py +++ b/python/paddle/fluid/generator.py @@ -14,6 +14,7 @@ """This is definition of generator class, which is for managing the state of the algorithm that produces pseudo random numbers.""" from . import core +from .framework import _get_paddle_place __all__ = ['Generator'] @@ -26,14 +27,15 @@ class Generator(core.Generator): Create a generator object which manages the random number generation. ( Experimental Feature ) Parameters: - place(CPUPlace|CUDAPinnedPlace|CUDAPlace, optional): The place to allocate Tensor. Can be - CPUPlace, CUDAPinnedPlace, CUDAPlace. Default: None, means global place. + place(CPUPlace|CUDAPinnedPlace|CUDAPlace|str,optional): The place to allocate Tensor. Can be + CPUPlace, CUDAPinnedPlace, CUDAPlace. Default: None, means global place. If ``place`` is + string, it can be ``cpu`` and ``gpu:x``, where ``x`` is the index of the GPUs. Returns: Generator: A generator object. """ - self.place = place + self.place = _get_paddle_place(place) if not place: place = core.CPUPlace() if isinstance(place, core.CPUPlace): diff --git a/python/paddle/fluid/layers/io.py b/python/paddle/fluid/layers/io.py index 6b98dea429..8e52f01a88 100644 --- a/python/paddle/fluid/layers/io.py +++ b/python/paddle/fluid/layers/io.py @@ -32,6 +32,7 @@ from ..unique_name import generate as unique_name import logging from ..data_feeder import check_dtype, check_type from paddle.fluid.framework import static_only +from ..framework import _get_paddle_place __all__ = [ 'data', 'read_file', 'double_buffer', 'py_reader', @@ -842,7 +843,8 @@ def double_buffer(reader, place=None, name=None): Args: reader (Variable): The Reader Variable need to be wrapped. - place (Place, optional): The place of target data, such as CPU, GPU, and if use GPU, it's necessary to point out which card is involved. Default is the sample place of executor perform. + place (Place|str, optional): The place of target data, such as CPU, GPU, and if use GPU, it's necessary to point out which card is involved. Default is the sample place of executor perform. + if ``place`` is string, It can be ``cpu``, ``gpu:x``, where ``x`` is the ndex of the GPUs. name (str, optional): Variable name. Normally there is no need for user to set this property. For more information, please refer to :ref:`api_guide_Name`. Default is None. Returns: @@ -861,7 +863,8 @@ def double_buffer(reader, place=None, name=None): """ attrs = dict() if place is not None: - attrs['place'] = str(place).upper() + attrs['place'] = str(_get_paddle_place(place)).upper() + return __create_unshared_decorated_reader__( 'create_double_buffer_reader', reader, attrs, name=name) diff --git a/python/paddle/fluid/reader.py b/python/paddle/fluid/reader.py index 84ccba98e6..a9f9c34862 100644 --- a/python/paddle/fluid/reader.py +++ b/python/paddle/fluid/reader.py @@ -27,6 +27,7 @@ from .dataloader.dataloader_iter import _DataLoaderIterSingleProcess, _DataLoade from .dataloader.batch_sampler import _InfiniteIterableSampler from .layers.io import monkey_patch_reader_methods, _copy_reader_var_, double_buffer from .unique_name import UniqueNameGenerator +from .framework import _get_paddle_place, _get_paddle_place_list import logging import warnings @@ -186,10 +187,12 @@ class DataLoader(object): The Tensors should be created by :code:`paddle.static.data()`. :attr:`feed_list` must be set if :attr:`return_list` is False. Default None. - places(list(Place)|tuple(Place)|optional): a list of Place, + places(list(Place)|tuple(Place)|list(str)|optional): a list of Place, to put data onto, :attr:`places` can be None, if :attr:`places` is None, default place(CPUPlace or CUDAPlace(0)) - will be used. Default None. + will be used. Default None. If ``places`` is list of string, + the string in the list can be ``cpu``, ``gpu:x`` and ``gpu_pinned``, + where ``x`` is the index of the GPUs. return_list (bool): whether the return value on each device is presented as a list. If :attr:`return_list=False`, the return value on each device would be a dict of str -> Tensor, where @@ -335,6 +338,10 @@ class DataLoader(object): if places is None: places = _current_expected_place() + if isinstance(places, (list, tuple)): + places = _get_paddle_place_list(places) + else: + places = _get_paddle_place(places) self.places = _convert_places(places) assert num_workers >= 0, "num_workers should be a non-negative value" @@ -752,8 +759,9 @@ class DataLoader(object): Args: dataset (InMemoryDataset|QueueDataset): the dataset object. - places (list(CUDAPlace)|list(CPUPlace)): places where the result - data should be converted. + places (list(CUDAPlace)|list(CPUPlace)|list(str)): places where the result + data should be converted. If places is list of string, the string in the list + can be ``cpu``, ``gpu:x`` and ``gpu_pinned``, where x is the index of the GPUs. drop_last (bool): whether to drop the last batch whose sample number is less than batch size. If drop_last = True, they would be dropped. If drop_last = False, they would be kept. @@ -1030,6 +1038,10 @@ class DygraphGeneratorLoader(DataLoaderBase): drop_last=True, places=None): assert batch_size > 0, "batch_size must be larger than 0" + if isinstance(places, (list, tuple)): + places = _get_paddle_place_list(places) + else: + places = _get_paddle_place(places) self.set_sample_list_generator( paddle.batch( reader, batch_size=batch_size, drop_last=drop_last), @@ -1037,6 +1049,11 @@ class DygraphGeneratorLoader(DataLoaderBase): return self def set_sample_list_generator(self, reader, places=None): + if isinstance(places, (list, tuple)): + places = _get_paddle_place_list(places) + else: + places = _get_paddle_place(places) + def __batch_reader_impl__(): for batch in reader(): slots = [] @@ -1052,6 +1069,10 @@ class DygraphGeneratorLoader(DataLoaderBase): return self def set_batch_generator(self, reader, places=None): + if isinstance(places, (list, tuple)): + places = _get_paddle_place_list(places) + else: + places = _get_paddle_place(places) self._batch_reader = reader if places is None: places = _current_expected_place() @@ -1275,6 +1296,10 @@ class GeneratorLoader(DataLoaderBase): drop_last=True, places=None): assert batch_size > 0, "batch_size must be larger than 0" + if isinstance(places, (list, tuple)): + places = _get_paddle_place_list(places) + else: + places = _get_paddle_place(places) has_lod = False for f in self._feed_list: if f.lod_level != 0: @@ -1297,6 +1322,10 @@ class GeneratorLoader(DataLoaderBase): return self def set_sample_list_generator(self, reader, places=None): + if isinstance(places, (list, tuple)): + places = _get_paddle_place_list(places) + else: + places = _get_paddle_place(places) with program_guard(Program(), Program()): feeder = DataFeeder( feed_list=self._feed_list, place=core.CPUPlace()) @@ -1310,6 +1339,10 @@ class GeneratorLoader(DataLoaderBase): return self def set_batch_generator(self, reader, places=None): + if isinstance(places, (list, tuple)): + places = _get_paddle_place_list(places) + else: + places = _get_paddle_place(places) self._tensor_reader = reader if self._iterable: assert places is not None, "Places cannot be None when DataLoader is iterable" @@ -1784,6 +1817,10 @@ class DatasetLoader(DataLoaderBase): DatasetBase), "dataset must be type of DatasetBase" assert not in_dygraph_mode( ), "DatasetLoader is not supported in dygraph mode yet" + if isinstance(places, (list, tuple)): + places = _get_paddle_place_list(places) + else: + places = _get_paddle_place(places) thread_num = len(places) diff --git a/python/paddle/fluid/tests/unittests/test_py_reader_error_msg.py b/python/paddle/fluid/tests/unittests/test_py_reader_error_msg.py index 4c45908c5c..f4fa419b91 100644 --- a/python/paddle/fluid/tests/unittests/test_py_reader_error_msg.py +++ b/python/paddle/fluid/tests/unittests/test_py_reader_error_msg.py @@ -15,6 +15,7 @@ import paddle.fluid as fluid import unittest import numpy as np +import paddle class TestPyReaderErrorMsg(unittest.TestCase): @@ -35,5 +36,19 @@ class TestPyReaderErrorMsg(unittest.TestCase): ]) +class TestDoubleBufferAPI(unittest.TestCase): + def test_double_buffer(self): + paddle.enable_static() + if fluid.core.is_compiled_with_cuda(): + reader = fluid.layers.py_reader( + capacity=64, + shapes=[(-1, 1, 28, 28), (-1, 1)], + dtypes=['float32', 'int64'], + use_double_buffer=False) + reader = fluid.layers.double_buffer( + reader, place=fluid.core.CUDAPlace(0)) + image, label = fluid.layers.read_file(reader) + + if __name__ == '__main__': unittest.main() diff --git a/python/paddle/fluid/tests/unittests/test_var_base.py b/python/paddle/fluid/tests/unittests/test_var_base.py index 653127319a..58ac8aab2d 100644 --- a/python/paddle/fluid/tests/unittests/test_var_base.py +++ b/python/paddle/fluid/tests/unittests/test_var_base.py @@ -149,9 +149,12 @@ class TestVarBase(unittest.TestCase): paddle.to_tensor([[1], [2, 3]], place=1) _test_place(core.CPUPlace()) + _test_place("cpu") if core.is_compiled_with_cuda(): _test_place(core.CUDAPinnedPlace()) + _test_place("gpu_pinned") _test_place(core.CUDAPlace(0)) + _test_place("gpu:0") def test_to_variable(self): with fluid.dygraph.guard(): diff --git a/python/paddle/hapi/model.py b/python/paddle/hapi/model.py index 7c731c4002..99e8acd2b0 100644 --- a/python/paddle/hapi/model.py +++ b/python/paddle/hapi/model.py @@ -31,7 +31,7 @@ import paddle from paddle import fluid from paddle.fluid import core from paddle.fluid.framework import in_dygraph_mode, Variable, ParamBase, _current_expected_place -from paddle.fluid.framework import in_dygraph_mode, Variable +from paddle.fluid.framework import in_dygraph_mode, Variable, _get_paddle_place from paddle.fluid.framework import _current_expected_place as _get_device from paddle.fluid.executor import global_scope from paddle.fluid.io import is_belong_to_optimizer @@ -167,6 +167,7 @@ def prepare_distributed_context(place=None): place = fluid.CUDAPlace(ParallelEnv().dev_id) if ParallelEnv().nranks > 1 \ else fluid.CUDAPlace(0) + place = _get_paddle_place(place) strategy = fluid.dygraph.parallel.ParallelStrategy() strategy.nranks = ParallelEnv().nranks strategy.local_rank = ParallelEnv().local_rank diff --git a/python/paddle/tensor/creation.py b/python/paddle/tensor/creation.py index d1c203d84c..fd5ca15840 100644 --- a/python/paddle/tensor/creation.py +++ b/python/paddle/tensor/creation.py @@ -18,7 +18,7 @@ import numpy as np from ..fluid.layers import tensor from ..fluid.framework import Variable from ..fluid.framework import unique_name -from ..fluid.framework import _current_expected_place +from ..fluid.framework import _current_expected_place, _get_paddle_place from ..fluid.framework import dygraph_only from ..fluid.initializer import Constant from ..fluid.layers import core @@ -26,7 +26,6 @@ from ..fluid.layer_helper import LayerHelper from ..fluid.data_feeder import check_variable_and_dtype, check_type, check_dtype, convert_dtype from ..fluid.framework import convert_np_dtype_to_dtype_, in_dygraph_mode, _varbase_creator, device_guard, OpProtoHolder from paddle.common_ops_import import * - # TODO: define functions to get create a tensor from ..fluid.layers import linspace #DEFINE_ALIAS import paddle @@ -70,8 +69,9 @@ def to_tensor(data, dtype=None, place=None, stop_gradient=True): 'float32' , 'float64' , 'int8' , 'int16' , 'int32' , 'int64' , 'uint8', 'complex64' , 'complex128'. Default: None, infers dtype from ``data`` except for python float number which gets dtype from ``get_default_type`` . - place(CPUPlace|CUDAPinnedPlace|CUDAPlace, optional): The place to allocate Tensor. Can be - CPUPlace, CUDAPinnedPlace, CUDAPlace. Default: None, means global place. + place(CPUPlace|CUDAPinnedPlace|CUDAPlace|str, optional): The place to allocate Tensor. Can be + CPUPlace, CUDAPinnedPlace, CUDAPlace. Default: None, means global place. If ``place`` is + string, It can be ``cpu``, ``gpu:x`` and ``gpu_pinned``, where ``x`` is the index of the GPUs. stop_gradient(bool, optional): Whether to block the gradient propagation of Autograd. Default: True. Returns: @@ -81,7 +81,7 @@ def to_tensor(data, dtype=None, place=None, stop_gradient=True): TypeError: If the data type of ``data`` is not scalar, list, tuple, numpy.ndarray, paddle.Tensor ValueError: If ``data`` is tuple|list, it can't contain nested tuple|list with different lengths , such as: [[1, 2], [3, 4, 5]] TypeError: If ``dtype`` is not bool, float16, float32, float64, int8, int16, int32, int64, uint8, complex64, complex128 - ValueError: If ``place`` is not paddle.CPUPlace, paddle.CUDAPinnedPlace, paddle.CUDAPlace + ValueError: If ``place`` is not paddle.CPUPlace, paddle.CUDAPinnedPlace, paddle.CUDAPlace or specified pattern string. Examples: @@ -119,10 +119,12 @@ def to_tensor(data, dtype=None, place=None, stop_gradient=True): # [(3+2j), (4+0j)]]) """ + place = _get_paddle_place(place) if place is None: place = _current_expected_place() - elif not isinstance(place, (core.Place, core.CPUPlace, core.CUDAPinnedPlace, - core.CUDAPlace)): + elif not isinstance( + place, + (core.Place, core.CPUPlace, core.CUDAPinnedPlace, core.CUDAPlace)): raise ValueError( "'place' must be any of paddle.Place, paddle.CPUPlace, paddle.CUDAPinnedPlace, paddle.CUDAPlace" ) -- GitLab