diff options
| author | Joshua Bakita <jbakita@cs.unc.edu> | 2021-03-13 18:13:18 -0500 |
|---|---|---|
| committer | Joshua Bakita <jbakita@cs.unc.edu> | 2021-03-13 18:16:11 -0500 |
| commit | 4235722244de5b47f78898a7e49bc8324ea323bf (patch) | |
| tree | cf5eadde0b491a9a15d83c7f4d97664e48602bca | |
| parent | 11b7de40aad15d8e3296ef5d9c487139a7073844 (diff) | |
Benchmarks and Analysis Scripts: Fix everything for 2D cache sensitivity exp.
- Adds plot_cache_sensitivity_at_4mb.py to plot the results
- Fixes run_bench.sh to work in mode `dis`
- Fixes postproc.sh to use updated paths
| -rw-r--r-- | dis/inputs/4mb_WSS | 1 | ||||
| -rwxr-xr-x | dis/plot_cache_sensitivity_at_4mb.py | 61 | ||||
| -rwxr-xr-x | dis/postproc.sh | 2 | ||||
| -rwxr-xr-x | run_bench.sh | 10 |
4 files changed, 68 insertions, 6 deletions
diff --git a/dis/inputs/4mb_WSS b/dis/inputs/4mb_WSS new file mode 100644 index 0000000..3f7803d --- /dev/null +++ b/dis/inputs/4mb_WSS | |||
| @@ -0,0 +1 @@ | |||
| 4194304 | |||
diff --git a/dis/plot_cache_sensitivity_at_4mb.py b/dis/plot_cache_sensitivity_at_4mb.py new file mode 100755 index 0000000..56484c8 --- /dev/null +++ b/dis/plot_cache_sensitivity_at_4mb.py | |||
| @@ -0,0 +1,61 @@ | |||
| 1 | #!/usr/bin/env python3 | ||
| 2 | import matplotlib.pyplot as plt | ||
| 3 | import numpy as np | ||
| 4 | import sys | ||
| 5 | |||
| 6 | if len(sys.argv) < 2: | ||
| 7 | print("Usage:", sys.argv[0], "<data file name>") | ||
| 8 | exit() | ||
| 9 | |||
| 10 | # Index to name lookup table | ||
| 11 | id_name_map = ("field", "matrix", "neighborhood", "pointer", "update", "transitive") | ||
| 12 | # Name to index lookup hash table | ||
| 13 | name_id_map = {id_name_map[idx]: idx for idx in range(len(id_name_map))} | ||
| 14 | |||
| 15 | # Extracts one benchmark's result from a file with multiple | ||
| 16 | def multibench_file(filename): | ||
| 17 | data = np.loadtxt(filename, usecols=(1,2,4,0), converters={0: lambda n: name_id_map[n.decode("utf_8")]}) | ||
| 18 | names = np.unique(data[:,3]) | ||
| 19 | for name in names: | ||
| 20 | yield (data[data[:,3] == name][:,:-1], id_name_map[int(name)]) | ||
| 21 | |||
| 22 | # Subsamples one benchmark at a specific WSS | ||
| 23 | def plot_exec_vs_cache_data(data, ax, wss, **kwargs): | ||
| 24 | wsss = np.unique(data[:,0]) | ||
| 25 | # Get exec time for this working set size with all ways allocated | ||
| 26 | divisor = data[np.logical_and(data[:,0] == wss, data[:,1] == 16.0)][0,2] | ||
| 27 | # Normalize relative to that exec time | ||
| 28 | one_wss_data = data[data[:,0] == wss] / [1,1,divisor] | ||
| 29 | # Plot max exec time vs cache allocation | ||
| 30 | return ax.plot(np.flip(one_wss_data[:,1],0), np.flip(one_wss_data[:,2],0), **kwargs) | ||
| 31 | |||
| 32 | # Wrapper function for backwards compatibility | ||
| 33 | def plot_exec_vs_cache(filename, ax, wss, line='-'): | ||
| 34 | data = np.loadtxt(filename, usecols=(1,2,4)) | ||
| 35 | plot_exec_vs_cache_data(data, ax, wss, linestyle=line, label=filename.split("-")[-4]) | ||
| 36 | |||
| 37 | # Styles and colors which match those used in the paper | ||
| 38 | name_to_label = {"matrix":"-", "transitive":"-.", "neighborhood":"--", "pointer":":", "update":"-", "field":"-."} | ||
| 39 | name_to_color = {"matrix":"C0", "transitive":"C1", "neighborhood":"C2", "pointer":"C3", "update":"C4", "field":"C5"} | ||
| 40 | plt.rcParams["font.family"] = "serif" | ||
| 41 | plt.rcParams['figure.figsize'] = [6, 4] | ||
| 42 | legend_labels = [] | ||
| 43 | wss = 4 * 2**20 | ||
| 44 | |||
| 45 | fig, ax = plt.subplots() | ||
| 46 | ax.set_xlabel("Cache Half Ways Allocated") | ||
| 47 | ax.set_ylabel("Worst-Case Execution Time Multiplier") | ||
| 48 | for (data, name) in multibench_file(sys.argv[1]): | ||
| 49 | line, = plot_exec_vs_cache_data(data, ax, wss, linestyle=name_to_label[name], label=name, color=name_to_color[name]) | ||
| 50 | # Save the max plotted value and legend info | ||
| 51 | legend_labels.append((max(line.get_ydata()), line, name)) | ||
| 52 | |||
| 53 | # Sort the legend by the max plotted value | ||
| 54 | legend_labels.sort(key=lambda k: k[0], reverse=True) | ||
| 55 | ax.legend([x[1] for x in legend_labels], [x[2] for x in legend_labels]) | ||
| 56 | |||
| 57 | # Plot from most to least ways allocated | ||
| 58 | ax.set_xlim(ax.get_xlim()[::-1]) | ||
| 59 | |||
| 60 | fig.savefig("exec_vs_cache_4mb_ae.pdf") | ||
| 61 | print("Plot saved as exec_vs_cache_4mb_ae.pdf") | ||
diff --git a/dis/postproc.sh b/dis/postproc.sh index efe6774..0147595 100755 --- a/dis/postproc.sh +++ b/dis/postproc.sh | |||
| @@ -14,5 +14,5 @@ if [[ ! -f $1.txt ]]; then | |||
| 14 | echo "Input does not exist. Exiting..." | 14 | echo "Input does not exist. Exiting..." |
| 15 | exit | 15 | exit |
| 16 | fi | 16 | fi |
| 17 | ./summarize.py $1.txt --inf-precision > $1-pp.txt | 17 | ../summarize.py $1.txt --inf-precision > $1-pp.txt |
| 18 | ./clean.sh $1-pp.txt | 18 | ./clean.sh $1-pp.txt |
diff --git a/run_bench.sh b/run_bench.sh index 6e4abb5..39e9dcb 100755 --- a/run_bench.sh +++ b/run_bench.sh | |||
| @@ -27,8 +27,8 @@ if [ $# -lt 5 ]; then | |||
| 27 | echo " L3-only (i3), or color-based L2+L3 (i)" | 27 | echo " L3-only (i3), or color-based L2+L3 (i)" |
| 28 | echo "Mode base requires no additional options." | 28 | echo "Mode base requires no additional options." |
| 29 | echo "Mode dis does not support the 2nd col. of -b and needs:" | 29 | echo "Mode dis does not support the 2nd col. of -b and needs:" |
| 30 | echo " -W FILE List of working set sizes to pass gen_input.py" | 30 | echo " -W FILE List of kB working set sizes to pass gen_input.py" |
| 31 | echo " -T FILE Input template to pass to gen_input.py" | 31 | echo " -T IN_ID Input template to pass to gen_input.py (eg. in0)" |
| 32 | echo " -C FILE List of cache configurations to test" | 32 | echo " -C FILE List of cache configurations to test" |
| 33 | echo "Mode pair options:" | 33 | echo "Mode pair options:" |
| 34 | echo " -P CPU CPU to run the 2nd benchmark on" | 34 | echo " -P CPU CPU to run the 2nd benchmark on" |
| @@ -87,7 +87,7 @@ if [[ "$mode" == "dis" ]] && [[ ! -f "$wss_settings" ]]; then | |||
| 87 | echo "Invalid argument: $wss_settings does not exist" | 87 | echo "Invalid argument: $wss_settings does not exist" |
| 88 | exit | 88 | exit |
| 89 | fi | 89 | fi |
| 90 | if [[ "$mode" == "dis" ]] && [[ ! -f "$template_input" ]]; then | 90 | if [[ "$mode" == "dis" ]] && [[ ! -f "inputs/Field/$template_input" ]]; then |
| 91 | echo "Invalid argument: $template_input does not exist" | 91 | echo "Invalid argument: $template_input does not exist" |
| 92 | exit | 92 | exit |
| 93 | fi | 93 | fi |
| @@ -350,9 +350,9 @@ for (( i = 0; i < ${#bench[@]} ; i++ )); do | |||
| 350 | echo $j > /sys/fs/resctrl/benchmarks/schemata | 350 | echo $j > /sys/fs/resctrl/benchmarks/schemata |
| 351 | while read ii; do # For WSS setting | 351 | while read ii; do # For WSS setting |
| 352 | if [[ -v $LITMUS ]]; then | 352 | if [[ -v $LITMUS ]]; then |
| 353 | ./gen_input.py ${bench[$i]} inputs/${bench[$i]^}/$template_input $ii | numactl $numa_arg0 $prefix/${bench[$i]} $bench[$i]}-$ii-$j $maxJobs $core $runID 1 | 353 | ./gen_input.py ${bench[$i]} inputs/${bench[$i]^}/$template_input $ii | numactl $numa_arg0 $prefix/${bench[$i]} $bench{[$i]}-$ii-$j $maxJobs $core $runID-$userRunID 1 |
| 354 | else | 354 | else |
| 355 | ./gen_input.py ${bench[$i]} inputs/${bench[$i]^}/$template_input $ii | chrt -r 97 numactl $numa_arg0 taskset -c $core $prefix/${bench[$i]} ${bench[$i]}-$ii-$j $maxJobs $core $runID 1 | 355 | ./gen_input.py ${bench[$i]} inputs/${bench[$i]^}/$template_input $ii | chrt -r 97 numactl $numa_arg0 taskset -c $core $prefix/${bench[$i]} ${bench[$i]}-$ii-$j $maxJobs $core $runID-$userRunID 1 |
| 356 | fi | 356 | fi |
| 357 | done < $wss_settings | 357 | done < $wss_settings |
| 358 | done < $cache_settings | 358 | done < $cache_settings |
