wrapper.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. # Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. import logging
  15. import os
  16. from typing import Set
  17. import numpy as np
  18. import paddle
  19. from paddle.base import core
  20. from paddle.base.core import (
  21. AnalysisConfig,
  22. PaddleDType,
  23. PaddleInferPredictor,
  24. PaddleInferTensor,
  25. PaddlePlace,
  26. convert_to_mixed_precision_bind,
  27. )
  28. from paddle.base.log_helper import get_logger
  29. _logger = get_logger(
  30. __name__, logging.INFO, fmt='%(asctime)s-%(levelname)s: %(message)s'
  31. )
  32. DataType = PaddleDType
  33. PlaceType = PaddlePlace
  34. PrecisionType = AnalysisConfig.Precision
  35. Config = AnalysisConfig
  36. Tensor = PaddleInferTensor
  37. Predictor = PaddleInferPredictor
  38. def tensor_copy_from_cpu(self, data):
  39. '''
  40. Support input type check based on tensor.copy_from_cpu.
  41. '''
  42. if isinstance(data, np.ndarray) or (
  43. isinstance(data, list) and len(data) > 0 and isinstance(data[0], str)
  44. ):
  45. self._copy_from_cpu_bind(data)
  46. else:
  47. raise TypeError(
  48. "In copy_from_cpu, we only support numpy ndarray and list[str] data type."
  49. )
  50. def tensor_share_external_data(self, data):
  51. '''
  52. Support input type check based on tensor.share_external_data.
  53. '''
  54. if isinstance(data, core.LoDTensor):
  55. self._share_external_data_bind(data)
  56. elif isinstance(data, paddle.Tensor):
  57. self._share_external_data_paddle_tensor_bind(data)
  58. elif isinstance(data, paddle.base.framework.Variable):
  59. raise TypeError(
  60. "The interface 'share_external_data' can only be used in dynamic graph mode. "
  61. "Maybe you called 'paddle.enable_static()' and you are in static graph mode now. "
  62. "Please use 'copy_from_cpu' instead."
  63. )
  64. else:
  65. raise TypeError(
  66. "In share_external_data, we only support Tensor and LoDTensor."
  67. )
  68. def convert_to_mixed_precision(
  69. model_file: str,
  70. params_file: str,
  71. mixed_model_file: str,
  72. mixed_params_file: str,
  73. mixed_precision: PrecisionType,
  74. backend: PlaceType,
  75. keep_io_types: bool = True,
  76. black_list: Set[str] = set(),
  77. **kwargs,
  78. ):
  79. '''
  80. Convert a fp32 model to mixed precision model.
  81. Args:
  82. model_file: fp32 model file, e.g. inference.pdmodel.
  83. params_file: fp32 params file, e.g. inference.pdiparams.
  84. mixed_model_file: The storage path of the converted mixed-precision model.
  85. mixed_params_file: The storage path of the converted mixed-precision params.
  86. mixed_precision: The precision, e.g. PrecisionType.Half.
  87. backend: The backend, e.g. PlaceType.GPU.
  88. keep_io_types: Whether the model input and output dtype remains unchanged.
  89. black_list: Operators that do not convert precision.
  90. kwargs: Supported keys including 'white_list'.
  91. - white_list: Operators that do convert precision.
  92. '''
  93. if backend is PlaceType.GPU and not core.is_compiled_with_cuda():
  94. _logger.error(
  95. "You should use PaddlePaddle compiled with GPU when backend set to PlaceType.GPU"
  96. )
  97. mixed_model_dirname = os.path.dirname(mixed_model_file)
  98. # Support mixed_params_file is empty, because some models don't have params, but convert_to_mixed_precision will call
  99. # constant_folding_pass, it will generate a new params file to save persistable vars, which is saved in the same
  100. # level file directory as the model file by default and ends in pdiparams.
  101. mixed_params_dirname = (
  102. os.path.dirname(mixed_params_file)
  103. if len(mixed_params_file) != 0
  104. else mixed_model_dirname
  105. )
  106. if not os.path.exists(mixed_params_dirname):
  107. os.makedirs(mixed_params_dirname)
  108. white_list = kwargs.get('white_list', set())
  109. convert_to_mixed_precision_bind(
  110. model_file,
  111. params_file,
  112. mixed_model_file,
  113. mixed_params_file,
  114. mixed_precision,
  115. backend,
  116. keep_io_types,
  117. black_list,
  118. white_list,
  119. )
  120. Tensor.copy_from_cpu = tensor_copy_from_cpu
  121. Tensor.share_external_data = tensor_share_external_data