Download code/models/perf/perf_utils.py from DeAIafdeling/qwen38-flash-next: direct link, hf CLI and curl.
- Browser
- Download file 10.2 kB
-
https://huggingface.co/DeAIafdeling/qwen38-flash-next/resolve/main/code/models/perf/perf_utils.py
- Command line
-
hf download hf://DeAIafdeling/qwen38-flash-next/code/models/perf/perf_utils.py
-
curl -L -o perf_utils.py https://huggingface.co/DeAIafdeling/qwen38-flash-next/resolve/main/code/models/perf/perf_utils.py
10.2 kB
| # SPDX-FileCopyrightText: © 2023 Tenstorrent USA, Inc. | |
| # SPDX-License-Identifier: Apache-2.0 | |
| import csv | |
| import re | |
| import time | |
| from os import listdir | |
| from os.path import isfile, join | |
| import git | |
| from loguru import logger | |
| from models.perf.benchmarking_utils import BenchmarkData, BenchmarkProfiler | |
| today = time.strftime("%Y_%m_%d") | |
| def merge_perf_files(fname, perf_fname, expected_cols): | |
| mypath = "./" | |
| csvfiles = [ | |
| f | |
| for f in listdir(mypath) | |
| if isfile(join(mypath, f)) and re.match(f"{perf_fname}_.*_{today}.csv", f) is not None | |
| ] | |
| repo = git.Repo(search_parent_directories=True) | |
| merge_res = open(fname, "w") | |
| if not repo.head.is_detached: | |
| merge_res.write(f"branch: {repo.active_branch} \n") | |
| else: | |
| merge_res.write(f"branch: detached HEAD \n") | |
| merge_res.write(f"hash: {repo.head.object.hexsha} \n") | |
| cols = ", ".join(expected_cols) | |
| merge_res.write(f"{cols} \n") | |
| csvfiles.sort() | |
| for csvfile in csvfiles: | |
| row_name = csvfile.replace("perf_", "") | |
| row_name = row_name.replace(f"{today}", "") | |
| row_name = row_name.replace(".csv", "") | |
| f = open(f"./{csvfile}", "r") | |
| f.readline() | |
| row = f.readline().strip().strip("\n") | |
| merge_res.write(f"{row}\n") | |
| merge_res.close() | |
| def process_perf_results(fname, expected_cols): | |
| with open(fname) as file: | |
| merge_res = csv.reader(file, skipinitialspace=True) | |
| logger.info(next(merge_res)[0].strip()) | |
| logger.info(next(merge_res)[0].strip()) | |
| cols = next(merge_res) | |
| cols = [c.strip() for c in cols] | |
| assert len(expected_cols) == len(cols), "Mismatch between expected and actual columns in perf CSV" | |
| for expected_c, c in zip(expected_cols, cols): | |
| assert expected_c == c, f"Expected column {expected_c} but instead got {c}" | |
| merge_res = list(merge_res) | |
| return cols, merge_res | |
| def check_perf_results( | |
| fname, expected_cols, check_cols, table_width=110, float_precision=4, lower_threshold=0.80, upper_threshold=1.0 | |
| ): | |
| red_color_code = "\033[91m" | |
| green_color_code = "\033[92m" | |
| reset_color_code = "\033[0m" | |
| bold_code = "\033[1m" | |
| underline_code = "\033[4m" | |
| fail_label = "[FAIL]" | |
| pass_label = "[PASS]" | |
| cols, merge_res = process_perf_results(fname, expected_cols) | |
| visited_models = [] | |
| slow_measured = {col: [] for col in check_cols} | |
| logger.info(f"Checking perf results for {fname}...") | |
| print("=" * table_width) | |
| print(f"{bold_code}PERFORMANCE RESULTS{reset_color_code}") | |
| print("=" * table_width) | |
| for models_info in merge_res: | |
| dict_info = {name: value for name, value in zip(cols, models_info)} | |
| model_name = f"{dict_info['Model']}_{dict_info['Setting']}" | |
| visited_models.append(model_name) | |
| print(f"\n{bold_code}{underline_code}Model: {dict_info['Model']}{reset_color_code}") | |
| print(f"{bold_code}Setting: {dict_info['Setting']}{reset_color_code}") | |
| print("-" * 60) | |
| highlight = False | |
| for col in check_cols: | |
| model_expected_col = float(dict_info[f"Expected {col}"]) | |
| model_measured_col = float(dict_info[col]) | |
| low_tolerance = ( | |
| model_expected_col * lower_threshold | |
| ) # fail if model is too fast so we can update the expected values | |
| high_tolerance = model_expected_col * upper_threshold # upper bound for regression | |
| if model_measured_col > high_tolerance: | |
| slow_measured[col].append((model_name, model_measured_col, model_expected_col)) | |
| regression_pct = ((model_measured_col - model_expected_col) / model_expected_col) * 100 | |
| print( | |
| f" FAIL {col}: {red_color_code}{model_measured_col:.{float_precision}f} > {high_tolerance:.{float_precision}f} ({regression_pct:.1f}% worse than expected - performance regression){reset_color_code}" | |
| ) | |
| highlight = True | |
| elif model_measured_col < low_tolerance: | |
| slow_measured[col].append((model_name, model_measured_col, model_expected_col)) | |
| improvement_pct = ((model_expected_col - model_measured_col) / model_expected_col) * 100 | |
| print( | |
| f" FAIL {col}: {red_color_code}{model_measured_col:.{float_precision}f} < {low_tolerance:.{float_precision}f} ({improvement_pct:.1f}% better than expected - update baseline){reset_color_code}" | |
| ) | |
| highlight = True | |
| else: | |
| print( | |
| f" PASS {col}: {model_measured_col:.{float_precision}f} (within tolerance: {low_tolerance:.{float_precision}f} - {high_tolerance:.{float_precision}f})" | |
| ) | |
| if highlight: | |
| print(f" {red_color_code}This model has performance issues{reset_color_code}") | |
| else: | |
| print(f" {green_color_code}All performance targets met{reset_color_code}") | |
| print("\n" + "=" * table_width) | |
| print(f"{bold_code}SUMMARY{reset_color_code}") | |
| print("=" * table_width) | |
| all_passed = True | |
| for col in slow_measured: | |
| if slow_measured[col]: | |
| all_passed = False | |
| print(f"{red_color_code}{fail_label} The following models failed '{col}' checks:{reset_color_code}") | |
| for model_name, measured, expected in slow_measured[col]: | |
| tolerance_range = f"[{expected * lower_threshold:.{float_precision}f}, {expected * upper_threshold:.{float_precision}f}]" | |
| if measured > expected * upper_threshold: | |
| regression_pct = ((measured - expected) / expected) * 100 | |
| status = f"{regression_pct:.1f}% regression" | |
| else: | |
| improvement_pct = ((expected - measured) / expected) * 100 | |
| status = f"{improvement_pct:.1f}% improvement" | |
| print( | |
| f" - {model_name}: measured={measured:.{float_precision}f}, expected={expected:.{float_precision}f}, tolerance={tolerance_range} ({status})" | |
| ) | |
| else: | |
| print(f"{green_color_code}{pass_label} All models meet expected '{col}' performance.{reset_color_code}") | |
| print("=" * table_width) | |
| if all_passed: | |
| print(f"{green_color_code}All performance checks passed!{reset_color_code}") | |
| else: | |
| print(f"{red_color_code}Some performance checks failed!{reset_color_code}") | |
| print("=" * table_width) | |
| if any(len(slow) > 0 for slow in slow_measured.values()): | |
| raise Exception( | |
| "Performance checks failed - see above for models with regressions or significant improvements requiring baseline updates" | |
| ) | |
| def prep_perf_report( | |
| model_name: str, | |
| batch_size: int, | |
| inference_and_compile_time: float, | |
| inference_time: float, | |
| expected_compile_time: float, | |
| expected_inference_time: float, | |
| comments: str, | |
| inference_time_cpu: float = None, | |
| ): | |
| today = time.strftime("%Y_%m_%d") | |
| def write_dict_to_file(csv_path, dict_res): | |
| columns = ", ".join([str(d) for d in dict_res.keys()]) | |
| values = ", ".join([d for d in dict_res.values()]) | |
| with open(csv_path, "w") as csvfile: | |
| csvfile.write(columns) | |
| csvfile.write("\n") | |
| csvfile.write(values) | |
| compile_time = inference_and_compile_time - inference_time | |
| device_throughput = "{:.4f}".format(batch_size * (1 / inference_time)) | |
| cpu_throughput = batch_size * (1 / inference_time_cpu) if inference_time_cpu else "unknown" | |
| cpu_throughput = "{:.4f}".format(cpu_throughput) if not isinstance(cpu_throughput, str) else cpu_throughput | |
| dict_res = { | |
| "Model": model_name, | |
| "Setting": comments, | |
| "Batch": str(batch_size), | |
| "First Run (sec)": "{:.2f}".format(inference_and_compile_time), | |
| "Second Run (sec)": "{:.2f}".format(inference_time), | |
| "Compile Time (sec)": "{:.2f}".format(compile_time), | |
| "Expected Compile Time (sec)": "{:.2f}".format(expected_compile_time), | |
| "Inference Time (sec)": "{:.4f}".format(inference_time), | |
| "Expected Inference Time (sec)": "{:.4f}".format(expected_inference_time), | |
| "Throughput (batch*inf/sec)": device_throughput, | |
| "Inference Time CPU (sec)": "{:.4f}".format(inference_time_cpu) if inference_time_cpu else "unknown", | |
| "Throughput CPU (batch*inf/sec)": cpu_throughput, | |
| } | |
| model_name = model_name.replace("/", "_") | |
| csv_file = f"perf_{model_name}_{comments}_{today}.csv" | |
| write_dict_to_file(csv_file, dict_res) | |
| # Dummy profiler to satisfy BenchmarkData's requirements | |
| profiler = BenchmarkProfiler() | |
| profiler.start("run") | |
| profiler.end("run") | |
| step_name = "end_to_end_perf" | |
| profiler.start(step_name) | |
| profiler.end(step_name) | |
| benchmark_data = BenchmarkData() | |
| # Add measurements for the key performance metrics | |
| # Convert string values back to float for measurements | |
| benchmark_data.add_measurement(profiler, 0, step_name, "inference_time_s", inference_time) | |
| benchmark_data.add_measurement(profiler, 0, step_name, "compile_time_s", compile_time) | |
| benchmark_data.add_measurement(profiler, 0, step_name, "throughput_iter_per_s", float(device_throughput)) | |
| benchmark_data.add_measurement(profiler, 0, step_name, "first_run_s", inference_and_compile_time) | |
| benchmark_data.add_measurement(profiler, 0, step_name, "expected_inference_time_s", expected_inference_time) | |
| benchmark_data.add_measurement(profiler, 0, step_name, "expected_compile_time_s", expected_compile_time) | |
| if inference_time_cpu is not None: | |
| benchmark_data.add_measurement(profiler, 0, step_name, "inference_time_cpu_s", inference_time_cpu) | |
| benchmark_data.add_measurement( | |
| profiler, | |
| 0, | |
| step_name, | |
| "throughput_cpu_iter_per_s", | |
| float(cpu_throughput) if cpu_throughput != "unknown" else 0.0, | |
| ) | |
| benchmark_data.save_partial_run_json( | |
| profiler, | |
| run_type="end_to_end_perf", | |
| ml_model_name=model_name, | |
| batch_size=batch_size, | |
| ) | |