performance_loss_test.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. """
  2. 测试性能损失脚本,通过比较推理过程中CPU、GPU占用、推理时间来进行计算
  3. 需要安装指定python库实现功能
  4. pip install psutil gputil pynvml
  5. """
  6. import argparse
  7. import os
  8. import psutil
  9. import GPUtil
  10. import numpy as np
  11. import time
  12. from threading import Thread
  13. import onnxruntime as ort
  14. from PIL import Image
  15. # 定义监控函数
  16. class UsageMonitor:
  17. def __init__(self, interval=0.5):
  18. self.interval = interval
  19. self.cpu_usage = []
  20. self.gpu_usage = []
  21. self.running = False
  22. def start(self):
  23. self.running = True
  24. self.monitor_thread = Thread(target=self._monitor)
  25. self.monitor_thread.start()
  26. def _monitor(self):
  27. while self.running:
  28. # 记录 CPU 使用率
  29. self.cpu_usage.append(psutil.cpu_percent(interval=None))
  30. # 记录 GPU 使用率
  31. gpus = GPUtil.getGPUs()
  32. if gpus:
  33. self.gpu_usage.append(gpus[0].load * 100) # 获取第一个 GPU 的使用率
  34. else:
  35. self.gpu_usage.append(0) # 若没有 GPU 则记为 0
  36. time.sleep(self.interval)
  37. def stop(self):
  38. self.running = False
  39. self.monitor_thread.join()
  40. def get_average_usage(self):
  41. avg_cpu_usage = np.mean(self.cpu_usage)
  42. avg_gpu_usage = np.mean(self.gpu_usage)
  43. return avg_cpu_usage, avg_gpu_usage
  44. def process_image(image_path):
  45. # 打开图像并转换为RGB
  46. image = Image.open(image_path).convert("RGB")
  47. # 调整图像大小
  48. image = image.resize((224, 224))
  49. # 转换为numpy数组并归一化
  50. image_array = np.array(image) / 255.0 # 将像素值缩放到[0, 1]
  51. # 进行标准化
  52. mean = np.array([0.485, 0.456, 0.406])
  53. std = np.array([0.229, 0.224, 0.225])
  54. image_array = (image_array - mean) / std
  55. image_array = image_array.transpose((2, 0, 1)).copy()
  56. return image_array.astype(np.float32)
  57. def batch_predict_images(session, image_dir, target_class, batch_size=10):
  58. """
  59. 对指定图片文件夹图片进行批量检测
  60. :param session: onnx runtime session
  61. :param image_dir: 待推理的图像文件夹
  62. :param target_class: 目标分类
  63. :param batch_size: 每批图片数量
  64. :return: 检测结果
  65. """
  66. image_files = [f for f in os.listdir(image_dir) if f.lower().endswith(('.png', '.jpg', '.jpeg'))]
  67. results = {}
  68. input_name = session.get_inputs()[0].name
  69. correct_predictions = 0
  70. total_predictions = 0
  71. for i in range(0, len(image_files), batch_size):
  72. batch_files = image_files[i:i + batch_size]
  73. batch_images = []
  74. for image_file in batch_files:
  75. image_path = os.path.join(image_dir, image_file)
  76. image = process_image(image_path)
  77. batch_images.append(image)
  78. # 将批次图片堆叠成 (batch_size, 3, 224, 224) 维度
  79. batch_images = np.stack(batch_images)
  80. # 执行预测
  81. outputs = session.run(None, {input_name: batch_images})
  82. # 提取预测结果
  83. for j, image_file in enumerate(batch_files):
  84. predicted_class = np.argmax(outputs[0][j]) # 假设输出是每类的概率
  85. results[image_file] = predicted_class
  86. total_predictions += 1
  87. # 比较预测结果与目标分类
  88. if predicted_class == target_class:
  89. correct_predictions += 1
  90. # 计算准确率
  91. accuracy = correct_predictions / total_predictions if total_predictions > 0 else 0
  92. return accuracy
  93. # 模型推理函数
  94. def model_inference(model_filename, val_dataset_dir):
  95. """
  96. 模型推理
  97. :param model_filename: 模型文件
  98. :param val_dataset_dir: 验证集图片目录
  99. :return: 验证集推理准确率
  100. """
  101. if ort.get_available_providers():
  102. session = ort.InferenceSession("model.onnx", providers=['CUDAExecutionProvider'])
  103. else:
  104. session = ort.InferenceSession(model_filename)
  105. accuracy = 0
  106. class_num = 0
  107. index = 0
  108. for class_dir in os.listdir(val_dataset_dir):
  109. class_path = os.path.join(val_dataset_dir, class_dir)
  110. # 检查是否为目录
  111. if not os.path.isdir(class_path):
  112. continue
  113. class_num += 1
  114. batch_result = batch_predict_images(session, class_path, index)
  115. accuracy += batch_result
  116. index += 1
  117. print(f"class_num: {class_num}, index: {index}")
  118. return accuracy * 1.0 / class_num
  119. if __name__ == '__main__':
  120. parser = argparse.ArgumentParser(description='模型推理性能验证脚本')
  121. # parser.add_argument('--model_file', default=None, type=str, help='待测试模型的onnx文件')
  122. # parser.add_argument('--val_dataset_dir', default=None, type=str, help='验证集目录')
  123. parser.add_argument('--model_file', default="origin_models/googlenet/model_139.onnx", type=str, help='待测试模型的onnx文件')
  124. parser.add_argument('--val_dataset_dir', default="val", type=str, help='验证集目录')
  125. args, _ = parser.parse_known_args()
  126. if args.model_file is None:
  127. raise Exception("待测试模型的onnx文件不可为空")
  128. if args.val_dataset_dir is None:
  129. raise Exception("验证集目录不可为空")
  130. monitor = UsageMonitor(interval=0.5) # 每隔 0.5 秒采样一次
  131. monitor.start()
  132. # 记录推理开始时间
  133. start_time = time.time()
  134. # 进行模型推理
  135. accuracy = model_inference(args.model_file, args.val_dataset_dir)
  136. # 记录推理结束时间
  137. end_time = time.time()
  138. monitor.stop()
  139. # 输出平均 CPU 和 GPU 使用率
  140. avg_cpu, avg_gpu = monitor.get_average_usage()
  141. print(f"平均 CPU 使用率:{avg_cpu:.2f}%")
  142. print(f"平均 GPU 使用率:{avg_gpu:.2f}%")
  143. print(f"模型推理时间: {end_time - start_time:.2f} 秒")
  144. print(f"准确率: {accuracy * 100:.2f}%")