-
Notifications
You must be signed in to change notification settings - Fork 38
Add Skip Existing Option For run_framework.py #45
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,12 +2,16 @@ | |
| import os | ||
| import pathlib | ||
| import sys | ||
| import json | ||
| import sqlite3 | ||
|
|
||
| from multiprocessing import Process | ||
| from typing import Dict, List | ||
| from npbench.infrastructure import (Benchmark, generate_framework, LineCount, | ||
| Test, utilities as util) | ||
|
|
||
|
|
||
|
|
||
| def run_benchmark(benchname, fname, preset, validate, repeat, timeout, | ||
| ignore_errors, save_strict, load_strict): | ||
| frmwrk = generate_framework(fname, save_strict, load_strict) | ||
|
|
@@ -19,6 +23,63 @@ def run_benchmark(benchname, fname, preset, validate, repeat, timeout, | |
| test.run(preset, validate, repeat, timeout, ignore_errors) | ||
|
|
||
|
|
||
|
|
||
| def filter_out_completed_benchmarks( | ||
| framework_name: str, | ||
| preset: str, | ||
| all_benchmarks: List[str], | ||
| benchname_to_shortname_mapping: Dict[str, str], | ||
| ) -> List[str]: | ||
|
|
||
|
|
||
| db_path = pathlib.Path("npbench.db") | ||
|
|
||
| # No DB → nothing measured yet | ||
| if not db_path.exists(): | ||
| print("Database does not exist, running all benchmarks") | ||
| return all_benchmarks | ||
|
|
||
| try: | ||
| with sqlite3.connect(db_path) as conn: | ||
| cur = conn.cursor() | ||
|
|
||
| # Check if results table exists | ||
| cur.execute(""" | ||
| SELECT name FROM sqlite_master | ||
| WHERE type='table' AND name='results' | ||
| """) | ||
| if cur.fetchone() is None: | ||
| print("Results table does not exist, running all benchmarks") | ||
| return all_benchmarks | ||
|
|
||
| # Query measured benchmarks | ||
| cur.execute(""" | ||
| SELECT DISTINCT benchmark | ||
| FROM results | ||
| WHERE framework = ? AND preset = ? | ||
| """, (framework_name, preset)) | ||
|
|
||
| measured_benchmarks = [row[0] for row in cur.fetchall()] | ||
|
|
||
| except sqlite3.Error as e: | ||
| # Any SQLite issue → be conservative | ||
| print(f"SQLite error ({e}), running all benchmarks") | ||
| return all_benchmarks | ||
|
|
||
| remaining_benchmarks = [ | ||
| bn | ||
| for bn in all_benchmarks | ||
| if benchname_to_shortname_mapping[bn] not in measured_benchmarks | ||
| ] | ||
|
|
||
| print( | ||
| f"Skipping {measured_benchmarks} for framework {framework_name} " | ||
| f"as they are already measured and in the database" | ||
| ) | ||
|
|
||
| return remaining_benchmarks | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| parser = argparse.ArgumentParser() | ||
| parser.add_argument("-f", | ||
|
|
@@ -57,13 +118,33 @@ def run_benchmark(benchname, fname, preset, validate, repeat, timeout, | |
| type=util.str2bool, | ||
| nargs="?", | ||
| default=False) | ||
| parser.add_argument("-e", | ||
| "--skip-existing-benchmarks", | ||
| type=util.str2bool, | ||
| nargs="?", | ||
| default=False) | ||
| args = vars(parser.parse_args()) | ||
|
|
||
| parent_folder = pathlib.Path(__file__).parent.absolute() | ||
| bench_dir = parent_folder.joinpath("bench_info") | ||
| pathlist = pathlib.Path(bench_dir).rglob('*.json') | ||
| benchnames = [os.path.basename(path)[:-5] for path in pathlist] | ||
| benchnames.sort() | ||
|
|
||
|
|
||
| if args["skip_existing_benchmarks"]: | ||
| benchname_to_shortname_mapping = dict() | ||
| json_dir = bench_dir | ||
| for json_file in json_dir.glob("*.json"): | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why don't you just get the benchmark names from line 132 here?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I need to load the JSON to get the short benchmark name, since the database already has it. JSON files' names do not necessarily have long names, so I have to build the mapping. This dictionary needs to load all the JSONs and read the "short_name" field anyway. |
||
| with open(json_file, "r") as f: | ||
| data = json.load(f) | ||
|
|
||
| short_name = data["benchmark"]["short_name"] | ||
| benchname = os.path.basename(json_file).replace(".json", "") | ||
| benchname_to_shortname_mapping[benchname] = short_name | ||
|
|
||
| benchnames = filter_out_completed_benchmarks(args["framework"], args["preset"], benchnames, benchname_to_shortname_mapping) | ||
|
|
||
| failed = [] | ||
| for benchname in benchnames: | ||
| p = Process(target=run_benchmark, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it make sense to also check whether sufficient executions have been recorded? To be clear, all executions for a specific benchmark (in a specific run) are recorded together. Therefore, a partial benchmark, e.g., with 5 out of 10 desired repetitions, is not possible. So, such a feature would only make sense if, in subsequent jobs, the number of repetitions was increased.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This makes sense. I was just not sure how to detect whether all desired repetitions had been completed. We can assume that if a timeout occurs and the desired repetitions are R, then there should be 2 possible values in the database at any given time. (R and another integer that is less than R in value, but not 3 unique values).
I can check for this. What do you think?