diff options
Diffstat (limited to 'benchmarks/plot-benchmarks.py')
| -rw-r--r-- | benchmarks/plot-benchmarks.py | 216 |
1 files changed, 118 insertions, 98 deletions
diff --git a/benchmarks/plot-benchmarks.py b/benchmarks/plot-benchmarks.py index 46031c6..027e0fe 100644 --- a/benchmarks/plot-benchmarks.py +++ b/benchmarks/plot-benchmarks.py | |||
| @@ -1,6 +1,14 @@ | |||
| 1 | import matplotlib.pyplot as plt | 1 | import matplotlib.pyplot as plt |
| 2 | import results_h48 | 2 | import results_h48 |
| 3 | import results_vcube | 3 | import results_vcube |
| 4 | from pathlib import Path | ||
| 5 | |||
| 6 | benchmarks_dir = Path("benchmarks") | ||
| 7 | benchmarks_img_dir = benchmarks_dir / "img" | ||
| 8 | benchmarks_single_thread = benchmarks_dir / "tables_1_thread.md" | ||
| 9 | benchmarks_4_threads = benchmarks_dir / "tables_4_threads.md" | ||
| 10 | benchmarks_16_threads = benchmarks_dir / "tables_16_threads.md" | ||
| 11 | benchmarks_all_solutions = benchmarks_dir / "tables_all_solutions.md" | ||
| 4 | 12 | ||
| 5 | # Table sizes in bytes | 13 | # Table sizes in bytes |
| 6 | 14 | ||
| @@ -23,7 +31,7 @@ sizes_vcube = { | |||
| 23 | 31 | ||
| 24 | # Printing tables in markdown format | 32 | # Printing tables in markdown format |
| 25 | 33 | ||
| 26 | def print_row(solver_name, solver_size, dict, mul_by_size, superflip_star): | 34 | def print_row(f, solver_name, solver_size, dict, mul_by_size, superflip_star): |
| 27 | if dict is None: | 35 | if dict is None: |
| 28 | return | 36 | return |
| 29 | solver_gib = solver_size / (2**30) | 37 | solver_gib = solver_size / (2**30) |
| @@ -36,104 +44,106 @@ def print_row(solver_name, solver_size, dict, mul_by_size, superflip_star): | |||
| 36 | f"{dict["superflip"]*m:>9.2f}" if "superflip" in dict else s | 44 | f"{dict["superflip"]*m:>9.2f}" if "superflip" in dict else s |
| 37 | ] | 45 | ] |
| 38 | sep = "|" | 46 | sep = "|" |
| 39 | print(sep + sep.join(cols) + sep) | 47 | f.write(sep + sep.join(cols) + sep + "\n") |
| 40 | 48 | ||
| 41 | def print_table(h48, vcube, ms, st): | 49 | def print_table(f, h48, vcube, ms, st): |
| 42 | vcube = vcube or {} | 50 | vcube = vcube or {} |
| 43 | print("| Solver | Size |17 moves|18 moves|19 moves|20 moves|Superflip|") | 51 | f.write("| Solver | Size |17 moves|18 moves|19 moves|20 moves|Superflip|\n") |
| 44 | print("|:---------|:-------|-------:|-------:|-------:|-------:|--------:|") | 52 | f.write("|:---------|:-------|-------:|-------:|-------:|-------:|--------:|\n") |
| 45 | print_row("vcube 212", sizes_vcube[212], vcube.get(212), ms, not st) | 53 | print_row(f, "vcube 212", sizes_vcube[212], vcube.get(212), ms, not st) |
| 46 | print_row("H48 h11", sizes_h48[11], h48[11], ms, False) | 54 | print_row(f, "H48 h11", sizes_h48[11], h48[11], ms, False) |
| 47 | print_row("vcube 404", sizes_vcube[404], vcube.get(404), ms, not st) | 55 | print_row(f, "vcube 404", sizes_vcube[404], vcube.get(404), ms, not st) |
| 48 | print_row("H48 h10", sizes_h48[10], h48[10], ms, False) | 56 | print_row(f, "H48 h10", sizes_h48[10], h48[10], ms, False) |
| 49 | print_row("vcube 308", sizes_vcube[308], vcube.get(308), ms, not st) | 57 | print_row(f, "vcube 308", sizes_vcube[308], vcube.get(308), ms, not st) |
| 50 | print_row("H48 h9", sizes_h48[9], h48[9], ms, False) | 58 | print_row(f, "H48 h9", sizes_h48[9], h48[9], ms, False) |
| 51 | print_row("vcube 208", sizes_vcube[208], vcube.get(208), ms, not st) | 59 | print_row(f, "vcube 208", sizes_vcube[208], vcube.get(208), ms, not st) |
| 52 | print_row("H48 h8", sizes_h48[8], h48[8], ms, False) | 60 | print_row(f, "H48 h8", sizes_h48[8], h48[8], ms, False) |
| 53 | print_row("H48 h7", sizes_h48[7], h48[7], ms, False) | 61 | print_row(f, "H48 h7", sizes_h48[7], h48[7], ms, False) |
| 54 | print_row("vcube 112", sizes_vcube[112], vcube.get(112), ms, not st) | 62 | print_row(f, "vcube 112", sizes_vcube[112], vcube.get(112), ms, not st) |
| 55 | print_row("H48 h6", sizes_h48[6], h48[6], ms, False) | 63 | print_row(f, "H48 h6", sizes_h48[6], h48[6], ms, False) |
| 64 | |||
| 65 | def print_factor_table(f, slow, fast): | ||
| 66 | ratio = {} | ||
| 67 | for m in [6, 7, 8, 9, 10, 11]: | ||
| 68 | ratio[m] = {} | ||
| 69 | for k in slow[m]: | ||
| 70 | ratio[m][k] = (slow[m][k] / fast[m][k]) * (25 if k != "superflip" else 1) | ||
| 71 | f.write("| Solver | Size |17 moves|18 moves|19 moves|20 moves|Superflip|\n") | ||
| 72 | f.write("|:---------|:-------|-------:|-------:|-------:|-------:|--------:|\n") | ||
| 73 | print_row(f, "H48 h11", sizes_h48[11], ratio[11], False, False) | ||
| 74 | print_row(f, "H48 h10", sizes_h48[10], ratio[10], False, False) | ||
| 75 | print_row(f, "H48 h9", sizes_h48[9], ratio[9], False, False) | ||
| 76 | print_row(f, "H48 h8", sizes_h48[8], ratio[8], False, False) | ||
| 77 | print_row(f, "H48 h7", sizes_h48[7], ratio[7], False, False) | ||
| 78 | print_row(f, "H48 h6", sizes_h48[6], ratio[6], False, False) | ||
| 56 | 79 | ||
| 57 | print("<details><summary>Single solution, single thread</summary>") | 80 | with open(benchmarks_single_thread, "w") as f: |
| 58 | print() | 81 | f.write(f"<!-- The following details block can be found in {benchmarks_single_thread} -->\n") |
| 59 | print("Time per cube (in seconds, lower is better).") | 82 | f.write("<details><summary>Results: Single solution, single thread</summary>\n") |
| 60 | print() | 83 | f.write("\n") |
| 61 | print_table(results_h48.h48_single_thread, results_vcube.vcube_single_thread, False, True) | 84 | f.write("Time per cube (in seconds, lower is better).\n") |
| 62 | print() | 85 | f.write("\n") |
| 63 | print("Time per cube adjusted for table size (in seconds \\* GiB, lower is better).") | 86 | print_table(f, results_h48.h48_single_thread, results_vcube.vcube_single_thread, False, True) |
| 64 | print() | 87 | f.write("\n") |
| 65 | print_table(results_h48.h48_single_thread, results_vcube.vcube_single_thread, True, True) | 88 | f.write("Time per cube adjusted for table size (in seconds \\* GiB, lower is better).\n") |
| 66 | print() | 89 | f.write("\n") |
| 67 | print( | 90 | print_table(f, results_h48.h48_single_thread, results_vcube.vcube_single_thread, True, True) |
| 68 | '<img src="img/17moves1thread.png">\n' | 91 | f.write("\n") |
| 69 | '<img src="img/18moves1thread.png">\n' | 92 | f.write( |
| 70 | '<img src="img/19moves1thread.png">\n' | 93 | '<img src="img/17moves1thread.png">\n' |
| 71 | '<img src="img/20moves1thread.png">' | 94 | '<img src="img/18moves1thread.png">\n' |
| 72 | ) | 95 | '<img src="img/19moves1thread.png">\n' |
| 73 | print("</details>") | 96 | '<img src="img/20moves1thread.png">\n' |
| 97 | ) | ||
| 98 | f.write("</details>\n") | ||
| 74 | 99 | ||
| 75 | print() | 100 | with open(benchmarks_4_threads, "w") as f: |
| 76 | print("<details><summary>Single solution, 4 threads</summary>") | 101 | f.write(f"<!-- The following details block can be found in {benchmarks_4_threads} -->\n") |
| 77 | print() | 102 | f.write("<details><summary>Results: Single solution, 4 threads</summary>\n") |
| 78 | print("Time per cube (in seconds, lower is better).") | 103 | f.write("\n") |
| 79 | print() | 104 | f.write("Time per cube (in seconds, lower is better).\n") |
| 80 | print_table(results_h48.h48_4_threads, results_vcube.vcube_4_threads, False, False) | 105 | f.write("\n") |
| 81 | print() | 106 | print_table(f, results_h48.h48_4_threads, None, False, False) |
| 82 | print("Time per cube adjusted for table size (in seconds \\* GiB, lower is better).") | 107 | f.write("\n") |
| 83 | print() | 108 | f.write("Speed-up factor (higher is better).\n") |
| 84 | print_table(results_h48.h48_4_threads, results_vcube.vcube_4_threads, True, False) | 109 | f.write("\n") |
| 85 | print() | 110 | print_factor_table(f, results_h48.h48_single_thread, results_h48.h48_4_threads) |
| 86 | print("(a) vcube cannot parallelize on a single scramble, the results for the") | 111 | f.write('<img src="img/4threadsspeedupfactor.png">\n') |
| 87 | print("superflip are going to be the same as in the single thread case.") | 112 | f.write("\n") |
| 88 | print() | 113 | f.write("</details>\n") |
| 89 | print( | ||
| 90 | '<img src="img/17moves4threads.png">\n' | ||
| 91 | '<img src="img/18moves4threads.png">\n' | ||
| 92 | '<img src="img/19moves4threads.png">\n' | ||
| 93 | '<img src="img/20moves4threads.png">' | ||
| 94 | ) | ||
| 95 | print("</details>") | ||
| 96 | 114 | ||
| 97 | print() | 115 | with open(benchmarks_16_threads, "w") as f: |
| 98 | print("<details><summary>Single solution, 16 threads</summary>") | 116 | f.write(f"<!-- The following details block can be found in {benchmarks_16_threads} -->\n") |
| 99 | print() | 117 | f.write("<details><summary>Results: Single solution, 16 threads</summary>\n") |
| 100 | print("Time per cube (in seconds, lower is better).") | 118 | f.write("\n") |
| 101 | print() | 119 | f.write("Time per cube (in seconds, lower is better).\n") |
| 102 | print_table(results_h48.h48_16_threads, results_vcube.vcube_16_threads, False, False) | 120 | f.write("\n") |
| 103 | print() | 121 | print_table(f, results_h48.h48_16_threads, None, False, False) |
| 104 | print("Time per cube adjusted for table size (in seconds \\* GiB, lower is better).") | 122 | f.write("\n") |
| 105 | print() | 123 | f.write("Speed-up factor (higher is better).\n") |
| 106 | print_table(results_h48.h48_16_threads, results_vcube.vcube_16_threads, True, False) | 124 | f.write("\n") |
| 107 | print() | 125 | print_factor_table(f, results_h48.h48_single_thread, results_h48.h48_16_threads) |
| 108 | print("(a) vcube cannot parallelize on a single scramble, the results for the") | 126 | f.write('<img src="img/16threadsspeedupfactor.png">\n') |
| 109 | print("superflip are going to be the same as in the single thread case.") | 127 | f.write("\n") |
| 110 | print() | 128 | f.write("</details>\n") |
| 111 | print( | ||
| 112 | '<img src="img/17moves16threads.png">\n' | ||
| 113 | '<img src="img/18moves16threads.png">\n' | ||
| 114 | '<img src="img/19moves16threads.png">\n' | ||
| 115 | '<img src="img/20moves16threads.png">' | ||
| 116 | ) | ||
| 117 | print("</details>") | ||
| 118 | 129 | ||
| 119 | print() | 130 | with open(benchmarks_all_solutions, "w") as f: |
| 120 | print("<details><summary>All solutions, 16 threads</summary>") | 131 | f.write(f"<!-- The following details block can be found in {benchmarks_all_solutions} -->\n") |
| 121 | print() | 132 | f.write("<details><summary>Results: All solutions, 16 threads</summary>\n") |
| 122 | print("*Note: vcube does not have an option for finding multiple solutions.*") | 133 | f.write("\n") |
| 123 | print() | 134 | f.write("Time per cube (in seconds, lower is better).\n") |
| 124 | print("Time per cube (in seconds, lower is better).") | 135 | f.write("\n") |
| 125 | print() | 136 | print_table(f, results_h48.h48_all_solutions, None, False, False) |
| 126 | print_table(results_h48.h48_all_solutions, None, False, False) | 137 | f.write("\n") |
| 127 | print() | 138 | f.write("Time per cube adjusted for table size (in seconds \\* GiB, lower is better).\n") |
| 128 | print("Time per cube adjusted for table size (in seconds \\* GiB, lower is better).") | 139 | f.write("\n") |
| 129 | print() | 140 | print_table(f, results_h48.h48_all_solutions, None, True, False) |
| 130 | print_table(results_h48.h48_all_solutions, None, True, False) | 141 | f.write("\n") |
| 131 | print() | 142 | f.write("</details>\n") |
| 132 | print("</details>") | ||
| 133 | 143 | ||
| 134 | # Plotting | 144 | # Plotting |
| 135 | 145 | ||
| 136 | def plot(title, hd, vd, key): | 146 | def plot_comparison(title, hd, vd, key): |
| 137 | d = 1 if key == "superflip" else 25 | 147 | d = 1 if key == "superflip" else 25 |
| 138 | h48x = [sizes_h48[m]/(2**30) for m in hd.keys() if key in hd[m]] | 148 | h48x = [sizes_h48[m]/(2**30) for m in hd.keys() if key in hd[m]] |
| 139 | vcubex = [sizes_vcube[m]/(2**30) for m in vd.keys() if key in vd[m]] | 149 | vcubex = [sizes_vcube[m]/(2**30) for m in vd.keys() if key in vd[m]] |
| @@ -148,17 +158,27 @@ def plot(title, hd, vd, key): | |||
| 148 | plt.plot(vcubex, vcubey, "o--", label = "vcube") | 158 | plt.plot(vcubex, vcubey, "o--", label = "vcube") |
| 149 | plt.legend(loc = "right") | 159 | plt.legend(loc = "right") |
| 150 | filename = title.replace(" ", "").replace(",", "") + ".png" | 160 | filename = title.replace(" ", "").replace(",", "") + ".png" |
| 151 | plt.savefig("benchmarks/img/" + filename, dpi=300) | 161 | plt.savefig(benchmarks_img_dir / filename, dpi=300) |
| 152 | #plt.show() | 162 | #plt.show() |
| 153 | 163 | ||
| 154 | rh, rv = results_h48.h48_single_thread, results_vcube.vcube_single_thread | 164 | rh, rv = results_h48.h48_single_thread, results_vcube.vcube_single_thread |
| 155 | for m in [17, 18, 19, 20]: | 165 | for m in [17, 18, 19, 20]: |
| 156 | plot(f"{m} moves 1 thread", rh, rv, m) | 166 | plot_comparison(f"{m} moves 1 thread", rh, rv, m) |
| 157 | 167 | ||
| 158 | rh, rv = results_h48.h48_4_threads, results_vcube.vcube_4_threads | 168 | def plot_multithread_scatter(title, slow, fast): |
| 159 | for m in [17, 18, 19, 20]: | 169 | plt.clf() |
| 160 | plot(f"{m} moves 4 threads", rh, rv, m) | 170 | plt.title(title) |
| 171 | plt.xlabel("Moves") | ||
| 172 | plt.ylabel("Speed-up factor") | ||
| 173 | x = [17, 18, 19] | ||
| 174 | plt.xticks(x) | ||
| 175 | for h in [11, 10, 9, 8, 7, 6]: | ||
| 176 | y = [slow[h][i] / fast[h][i] for i in x] | ||
| 177 | plt.scatter(x, y, label=f"H48 h{h}") | ||
| 178 | plt.legend(loc = "right") | ||
| 179 | filename = title.replace(" ", "").replace(",", "") + ".png" | ||
| 180 | plt.savefig(benchmarks_img_dir / filename, dpi=300) | ||
| 181 | plt.show() | ||
| 161 | 182 | ||
| 162 | rh, rv = results_h48.h48_16_threads, results_vcube.vcube_16_threads | 183 | plot_multithread_scatter("4 threads speedup factor", results_h48.h48_single_thread, results_h48.h48_4_threads) |
| 163 | for m in [17, 18, 19, 20]: | 184 | plot_multithread_scatter("16 threads speedup factor", results_h48.h48_single_thread, results_h48.h48_16_threads) |
| 164 | plot(f"{m} moves 16 threads", rh, rv, m) | ||
