metrics.py 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. # -------------------------------------------------------------------------
  2. # Copyright (c) Microsoft Corporation. All rights reserved.
  3. # Licensed under the MIT License. See License.txt in the project root for
  4. # license information.
  5. # --------------------------------------------------------------------------
  6. import datetime
  7. import json
  8. import pandas as pd
  9. class BaseObject:
  10. def __init__(self):
  11. self.customized = {}
  12. def to_dict(self):
  13. default_values = self.__dict__.copy()
  14. default_values.pop("customized", None)
  15. default_values.update(self.customized)
  16. for k, v in default_values.items():
  17. if isinstance(v, BaseObject):
  18. default_values[k] = v.to_dict()
  19. return {k: v for k, v in default_values.items() if v}
  20. class ModelInfo(BaseObject):
  21. def __init__(
  22. self,
  23. full_name: str | None = None,
  24. is_huggingface: bool | None = False,
  25. is_text_generation: bool | None = False,
  26. short_name: str | None = None,
  27. ):
  28. super().__init__()
  29. self.full_name = full_name
  30. self.is_huggingface = is_huggingface
  31. self.is_text_generation = is_text_generation
  32. self.short_name = short_name
  33. self.input_shape = []
  34. class BackendOptions(BaseObject):
  35. def __init__(
  36. self,
  37. enable_profiling: bool | None = False,
  38. execution_provider: str | None = None,
  39. use_io_binding: bool | None = False,
  40. ):
  41. super().__init__()
  42. self.enable_profiling = enable_profiling
  43. self.execution_provider = execution_provider
  44. self.use_io_binding = use_io_binding
  45. class Config(BaseObject):
  46. def __init__(
  47. self,
  48. backend: str | None = "onnxruntime",
  49. batch_size: int | None = 1,
  50. seq_length: int | None = 0,
  51. precision: str | None = "fp32",
  52. warmup_runs: int | None = 1,
  53. measured_runs: int | None = 10,
  54. ):
  55. super().__init__()
  56. self.backend = backend
  57. self.batch_size = batch_size
  58. self.seq_length = seq_length
  59. self.precision = precision
  60. self.warmup_runs = warmup_runs
  61. self.measured_runs = measured_runs
  62. self.model_info = ModelInfo()
  63. self.backend_options = BackendOptions()
  64. class Metadata(BaseObject):
  65. def __init__(
  66. self,
  67. device: str | None = None,
  68. package_name: str | None = None,
  69. package_version: str | None = None,
  70. platform: str | None = None,
  71. python_version: str | None = None,
  72. ):
  73. super().__init__()
  74. self.device = device
  75. self.package_name = package_name
  76. self.package_version = package_version
  77. self.platform = platform
  78. self.python_version = python_version
  79. class Metrics(BaseObject):
  80. def __init__(
  81. self,
  82. latency_ms_mean: float | None = 0.0,
  83. throughput_qps: float | None = 0.0,
  84. max_memory_usage_GB: float | None = 0.0,
  85. ):
  86. super().__init__()
  87. self.latency_ms_mean = latency_ms_mean
  88. self.throughput_qps = throughput_qps
  89. self.max_memory_usage_GB = max_memory_usage_GB
  90. class BenchmarkRecord:
  91. def __init__(
  92. self,
  93. model_name: str,
  94. precision: str,
  95. backend: str,
  96. device: str,
  97. package_name: str,
  98. package_version: str,
  99. batch_size: int | None = 1,
  100. warmup_runs: int | None = 1,
  101. measured_runs: int | None = 10,
  102. trigger_date: str | None = None,
  103. ):
  104. self.config = Config()
  105. self.metrics = Metrics()
  106. self.metadata = Metadata()
  107. self.trigger_date = trigger_date or datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
  108. self.config.model_info.full_name = model_name
  109. self.config.precision = precision
  110. self.config.backend = backend
  111. self.config.batch_size = batch_size
  112. self.config.warmup_runs = warmup_runs
  113. self.config.measured_runs = measured_runs
  114. self.metadata.device = device
  115. self.metadata.package_name = package_name
  116. self.metadata.package_version = package_version
  117. def to_dict(self) -> dict:
  118. return {
  119. "config": self.config.to_dict(),
  120. "metadata": self.metadata.to_dict(),
  121. "metrics": self.metrics.to_dict(),
  122. "trigger_date": self.trigger_date,
  123. }
  124. def to_json(self) -> str:
  125. return json.dumps(self.to_dict(), default=str)
  126. @classmethod
  127. def save_as_csv(cls, file_name: str, records: list) -> None:
  128. if records is None or len(records) == 0:
  129. return
  130. rds = [record.to_dict() for record in records]
  131. df = pd.json_normalize(rds)
  132. df.to_csv(file_name, index=False)
  133. @classmethod
  134. def save_as_json(cls, file_name: str, records: list) -> None:
  135. if records is None or len(records) == 0:
  136. return
  137. rds = [record.to_dict() for record in records]
  138. with open(file_name, "w") as f:
  139. json.dump(rds, f, indent=4, default=str)