m2m模型翻译
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

122 lines
4.3 KiB

6 months ago
  1. # -------------------------------------------------------------------------
  2. # Copyright (c) Microsoft Corporation. All rights reserved.
  3. # Licensed under the MIT License.
  4. # --------------------------------------------------------------------------
  5. import logging
  6. import os
  7. import sys
  8. from typing import Dict
  9. # In ORT Package the symbolic_shape_infer.py is in ../tools
  10. file_path = os.path.dirname(__file__)
  11. if os.path.exists(os.path.join(file_path, "../tools/symbolic_shape_infer.py")):
  12. sys.path.append(os.path.join(file_path, "../tools"))
  13. else:
  14. sys.path.append(os.path.join(file_path, ".."))
  15. from symbolic_shape_infer import SymbolicShapeInference, get_shape_from_type_proto, sympy
  16. logger = logging.getLogger(__name__)
  17. class SymbolicShapeInferenceHelper(SymbolicShapeInference):
  18. def __init__(self, model, verbose=0, int_max=2**31 - 1, auto_merge=True, guess_output_rank=False):
  19. super().__init__(int_max, auto_merge, guess_output_rank, verbose)
  20. self.model_ = model
  21. self.all_shapes_inferred_: bool = False
  22. self.is_inferred_: bool = False
  23. self.dynamic_axis_mapping_: Dict[str, int] = {}
  24. def infer(self, dynamic_axis_mapping: Dict[str, int], max_runs: int = 128):
  25. """Run shape inference, and try replace dynamic axis from string to integer when mapping is provided.
  26. Args:
  27. dynamic_axis_mapping (_type_): a dictionary with name of dynamic axis as key, like {"batch_size" : 4}
  28. max_runs (int, optional): limit maximum number of runs to avoid infinite loop. Defaults to 32.
  29. Returns:
  30. bool: whether all shapes has been inferred or not.
  31. """
  32. assert dynamic_axis_mapping is not None
  33. if self.is_inferred_ and self.dynamic_axis_mapping_ == dynamic_axis_mapping:
  34. return self.all_shapes_inferred_
  35. self.dynamic_axis_mapping_ = dynamic_axis_mapping
  36. self._preprocess(self.model_)
  37. count = 0
  38. while self.run_:
  39. logger.debug(f"shape infer run {count}")
  40. self.all_shapes_inferred_ = self._infer_impl()
  41. count += 1
  42. if max_runs > 0 and count >= max_runs:
  43. break
  44. self.is_inferred_ = True
  45. return self.all_shapes_inferred_
  46. def _get_sympy_shape(self, node, idx):
  47. """Override it to ensure shape inference by giving the actual value of dynamic axis."""
  48. sympy_shape = []
  49. shape = self._get_shape(node, idx)
  50. if shape:
  51. for dim in shape:
  52. if isinstance(dim, str):
  53. if dim in self.dynamic_axis_mapping_:
  54. sympy_shape.append(self.dynamic_axis_mapping_[dim])
  55. elif dim in self.symbolic_dims_:
  56. sympy_shape.append(self.symbolic_dims_[dim])
  57. else:
  58. sympy_shape.append(sympy.Symbol(dim, integer=True))
  59. else:
  60. assert dim is not None
  61. sympy_shape.append(dim)
  62. return sympy_shape
  63. def get_edge_shape(self, edge):
  64. """Get shape of an edge.
  65. Args:
  66. edge (str): name of edge
  67. Returns:
  68. Optional[List[int]]: the shape, or None if shape is unknown
  69. """
  70. assert self.all_shapes_inferred_
  71. if edge not in self.known_vi_:
  72. print("Cannot retrieve the shape of " + str(edge))
  73. return None
  74. type_proto = self.known_vi_[edge].type
  75. shape = get_shape_from_type_proto(type_proto)
  76. if shape is not None:
  77. for i, dim in enumerate(shape):
  78. if isinstance(dim, str) and dim in self.dynamic_axis_mapping_:
  79. shape[i] = self.dynamic_axis_mapping_[dim]
  80. return shape
  81. def compare_shape(self, edge, edge_other):
  82. """Compare shape of two edges.
  83. Args:
  84. edge (str): name of edge
  85. edge_other (str): name of another edge
  86. Raises:
  87. Exception: At least one shape is missed for edges to compare
  88. Returns:
  89. bool: whether the shape is same or not
  90. """
  91. assert self.all_shapes_inferred_
  92. shape = self.get_edge_shape(edge)
  93. shape_other = self.get_edge_shape(edge_other)
  94. if shape is None or shape_other is None:
  95. raise Exception("At least one shape is missed for edges to compare")
  96. return shape == shape_other