From 7dd551e08b89fe9a67443e6da6ab424621342979 Mon Sep 17 00:00:00 2001 From: wangchaochaohu Date: Thu, 7 Jan 2021 14:40:58 +0800 Subject: [PATCH] refine the paddle place support using str (#28769) --- .../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, 195 insertions(+), 49 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 15971af58c6..44db3f3a335 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 a07378a6f58..a04d58ff25e 100644 --- a/python/paddle/fluid/compiler.py +++ b/python/paddle/fluid/compiler.py @@ -18,8 +18,8 @@ import six import sys from .. import compat as cpt from . import framework +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 +202,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 +213,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 +283,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 7e1db69703c..0f44d7240e2 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 d31dc35d143..2ed06a48c29 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 219025269fe..0017c29cbda 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 b63941206ec..11c836c9166 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 9b17d61c33c..9b0b04a6ea7 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 ebea81ed604..39005d9a982 100644 --- a/python/paddle/fluid/framework.py +++ b/python/paddle/fluid/framework.py @@ -5805,3 +5805,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 98924f80141..7ce2d6a4bf3 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 6b98dea4290..8e52f01a88b 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 84ccba98e60..a9f9c348622 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 4c45908c5c3..f4fa419b91d 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 653127319a1..58ac8aab2db 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 7c731c40029..99e8acd2b0b 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 58641009d9d..25957bd76a3 100644 --- a/python/paddle/tensor/creation.py +++ b/python/paddle/tensor/creation.py @@ -17,7 +17,7 @@ import numpy as np 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 @@ -25,7 +25,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 @@ -69,8 +68,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: @@ -80,7 +80,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: @@ -118,10 +118,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