-
-
Notifications
You must be signed in to change notification settings - Fork 312
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #396 from nfejzic/add-thesis-nfejzic
- Loading branch information
Showing
27 changed files
with
2,552 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# peRISCope | ||
|
||
This is a project for exploring the reasoning performance of RISC-V software | ||
models in BTOR2. The name `periscope` is derived from the idea of exploring | ||
PErformance of RISC models, and the idea of a periscope that can be used to | ||
explore the unknown surroundings. | ||
|
||
## Structure | ||
|
||
The project consists of two sub-projects: | ||
|
||
- [`periscope-rs`](./periscope-rs) - A binary written in Rust that can be used | ||
to parse witness format producec by `btormc`, and for benchmarking of model | ||
checking. Check the [README](./periscope-rs/README.md) for more information. | ||
- [`periscope-py`](./periscope-py) - A Python package that can be used to read | ||
output of `periscope-rs` and produce plots. Check the | ||
[README](./periscope-py/README.md) for more information. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
.venv/ | ||
|
||
src/__pycache__/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# PeRISCope - Python script for results visualisation | ||
|
||
This is a simple Python script for generating plots of benchmarking results | ||
produced by [`periscope-rs`](../periscope-rs). | ||
|
||
## Usage | ||
|
||
Make sure you installed all required dependencies: | ||
|
||
```sh | ||
pip install -r requirements.txt | ||
``` | ||
|
||
After that, run the main script file with `--help` flag to get more information: | ||
|
||
```sh | ||
python src/periscope.py --help | ||
``` | ||
|
||
## Example usage: | ||
|
||
```sh | ||
# Generate a plot with bars for each configuration, overall sort-by median time, | ||
# and scale the y-axis logarithmically. Plot results contained in `results_dir` | ||
# and save the plot to test.png file. | ||
python src/periscope.py --sort-by median --scale log --type cmp-bars -o test.png results_dir | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
{ | ||
"include": [ | ||
"src", | ||
], | ||
|
||
"exclude": [ | ||
"**/node_modules", | ||
"**/__pycache__", | ||
".venv", | ||
], | ||
|
||
"venvPath": ".", | ||
"venv": ".venv", | ||
|
||
"ignore": [ | ||
"src/oldstuff" | ||
], | ||
|
||
"reportMissingImports": true, | ||
"reportMissingTypeStubs": false, | ||
|
||
"executionEnvironments": [ | ||
{ | ||
"root": "src" | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
jsonpickle==3.0.4 | ||
matplotlib==3.8.4 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
import argparse | ||
import functools | ||
|
||
from matplotlib import figure | ||
import matplotlib.pyplot as plt | ||
import numpy as np | ||
|
||
from periscope_result import BenchResult | ||
|
||
|
||
def cmp_median(medians: list[float], labels: list[str]): | ||
def compare(i, j): | ||
med_cmp = medians[i] - medians[j] | ||
if med_cmp == 0: | ||
return labels[i] < labels[j] | ||
else: | ||
return med_cmp | ||
|
||
return compare | ||
|
||
|
||
def cmp_median_multi(): | ||
def compare( | ||
i: tuple[str, dict[str, BenchResult]], j: tuple[str, dict[str, BenchResult]] | ||
): | ||
med_i_avg = sum([b.hyperfine_results()[0].median for b in i[1].values()]) / len( | ||
i | ||
) | ||
med_j_avg = sum([b.hyperfine_results()[0].median for b in j[1].values()]) / len( | ||
i | ||
) | ||
|
||
med_cmp = med_i_avg - med_j_avg | ||
return int(med_cmp) | ||
|
||
return compare | ||
|
||
|
||
def cmp_legend(): | ||
def compare(a: str, b: str): | ||
all_numbers_a = list( | ||
filter(lambda x: len(x) > 0 and x[0].isdigit(), a.split("-")) | ||
) | ||
all_numbers_b = list( | ||
filter(lambda x: len(x) > 0 and x[0].isdigit(), b.split("-")) | ||
) | ||
|
||
for num_a, num_b in zip(all_numbers_a, all_numbers_b): | ||
num_a = int(num_a.removesuffix("b")) | ||
num_b = int(num_b.removesuffix("b")) | ||
|
||
if num_a != num_b: | ||
return num_a - num_b | ||
|
||
return 0 | ||
|
||
return compare | ||
|
||
|
||
def plot_cmp_bars( | ||
args: argparse.Namespace, | ||
periscope_results: dict[str, list[BenchResult]], | ||
figure: figure.Figure, | ||
): | ||
legend = sorted( | ||
list(periscope_results.keys()), | ||
key=functools.cmp_to_key(cmp_legend()), | ||
# key=lambda x: int(x.split("-")[0].removesuffix("b")), | ||
) | ||
|
||
bar_w = (1 - 0.4) / len(legend) | ||
group_w = bar_w * len(legend) | ||
offsets = np.arange(start=-(group_w / 2), stop=group_w / 2, step=bar_w) | ||
cmap = plt.get_cmap("rainbow") | ||
colors = [cmap(val / len(legend)) for val in range(len(legend))] | ||
|
||
ax = figure.subplots(1, 1) | ||
_, ax2 = plt.subplots(figsize=(20, 10), constrained_layout=True) | ||
|
||
handles = [] | ||
|
||
per_file: dict[str, dict[str, BenchResult]] = {} | ||
|
||
for bench_config in legend: | ||
for bench_name in periscope_results[bench_config]: | ||
b_name = ( | ||
bench_name.name.removesuffix("-rotorized.btor2") | ||
.removesuffix("-35") | ||
.removesuffix("-10") | ||
.removesuffix("-1") | ||
.removesuffix("-2") | ||
.removesuffix("-3") | ||
) | ||
if b_name not in per_file: | ||
per_file[b_name] = {} | ||
|
||
per_file[b_name][bench_config] = bench_name | ||
|
||
plt.title("Comparison of median times with different model configurations") | ||
|
||
if args.sort_by == "median": | ||
per_file = dict( | ||
sorted(per_file.items(), key=functools.cmp_to_key(cmp_median_multi())) | ||
) | ||
|
||
if args.scale == "log": | ||
ax2.set_yscale("log") | ||
plt.title( | ||
"Comparison of median times with different model configurations (Log scale)", | ||
) | ||
|
||
plt.ylabel("Time [s]") | ||
|
||
labels = list(per_file.keys()) | ||
label_positions = np.arange(len(labels)) - 0.1 | ||
plt.tick_params(axis="x", length=20) | ||
plt.xticks(list(label_positions), labels, rotation=55, ha="right") | ||
|
||
# label_positions = list() | ||
|
||
for idx, file in enumerate(per_file.values()): | ||
for bench_idx, bench_name in enumerate(file.values()): | ||
offs = offsets[bench_idx] | ||
time = bench_name.hyperfine_results()[0].median | ||
color = colors[bench_idx] | ||
ax = plt.bar(x=idx + offs, height=time, width=bar_w, color=color) | ||
handles.append(ax) | ||
# label_positions.append(idx + offs) | ||
|
||
# plt.xticks(label_positions, labels, rotation=0) | ||
|
||
plt.ylim(0.1, 300) | ||
legend = list(map(lambda x: x.removesuffix(".json").replace("-", " "), legend)) | ||
plt.legend(handles=handles, labels=legend) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import argparse | ||
|
||
from matplotlib import figure, pyplot as plt | ||
import numpy as np | ||
|
||
from periscope_result import BenchResult | ||
|
||
|
||
def cmp_wc(labels: list[str], periscope_results: list[BenchResult]): | ||
def compare(i, j): | ||
wc_i = periscope_results[i].wc | ||
wc_j = periscope_results[j].wc | ||
if wc_i == wc_j: | ||
return labels[i] < labels[j] | ||
else: | ||
return wc_i - wc_j | ||
|
||
return compare | ||
|
||
|
||
def plot_histogram( | ||
args: argparse.Namespace, | ||
periscope_results: list[BenchResult], | ||
figure: figure.Figure, | ||
of_dump: bool, | ||
): | ||
labels = [b.name for b in periscope_results] | ||
all_times = [b.times for pr in periscope_results for b in pr.hyperfine_results()] | ||
|
||
t_min = np.min(list(map(np.min, all_times))) | ||
t_max = np.max(list(map(np.max, all_times))) | ||
|
||
if of_dump: | ||
wcs = [pr.results.wc_btormc_dump for pr in periscope_results] | ||
else: | ||
wcs = [pr.results.wc_raw for pr in periscope_results] | ||
|
||
times = list(map(np.min, all_times)) | ||
|
||
_ = figure.subplots(1, 1) | ||
cmap = plt.get_cmap("rainbow") | ||
colors = [cmap(val / len(times)) for val in range(len(times))] | ||
plt.bar(x=times, height=wcs, label=labels, color=colors, width=5) | ||
|
||
plt.title("Solving time and model size") | ||
plt.xlabel("Time [s]") | ||
|
||
if of_dump: | ||
plt.ylabel("Model Size after btormc dump [#chars]") | ||
else: | ||
plt.ylabel("Model Size [#chars]") | ||
|
||
plt.xticks(np.arange(np.floor(t_min), np.floor(t_max), step=10)) | ||
plt.xticks( | ||
list(map(np.min, all_times)), | ||
labels, | ||
rotation=65, | ||
minor=True, | ||
) | ||
|
||
for xtick, color in zip(plt.gca().get_xticklabels(which="minor"), colors): | ||
xtick.set_color(color) |
Oops, something went wrong.