diff options
| author | Sebastiano Tronto <sebastiano@tronto.net> | 2026-01-26 22:52:15 +0100 |
|---|---|---|
| committer | Sebastiano Tronto <sebastiano@tronto.net> | 2026-01-26 22:52:15 +0100 |
| commit | 233169d9ab5fb8a796d91a3694f8a522fa54d194 (patch) | |
| tree | 431e21f77f22f123a3caf4ade644c910ae6514d4 /benchmarks/benchmarks.md | |
| parent | 74299c8919cb2e2f6e1678817529e3a730cf6b81 (diff) | |
| download | nissy-core-233169d9ab5fb8a796d91a3694f8a522fa54d194.tar.gz nissy-core-233169d9ab5fb8a796d91a3694f8a522fa54d194.zip | |
Improve multithreading benchmarks (compare speedup factor, not with vcube)
Diffstat (limited to '')
| -rw-r--r-- | benchmarks/benchmarks.md | 155 |
1 files changed, 71 insertions, 84 deletions
diff --git a/benchmarks/benchmarks.md b/benchmarks/benchmarks.md index 768a7ea..3fc2093 100644 --- a/benchmarks/benchmarks.md +++ b/benchmarks/benchmarks.md | |||
| @@ -38,21 +38,6 @@ may be particularly inaccurate, because writing the solution (together | |||
| 38 | with some log messages) to standard output may take a significant portion | 38 | with some log messages) to standard output may take a significant portion |
| 39 | of the time, depending on the terminal emulator used and other factors. | 39 | of the time, depending on the terminal emulator used and other factors. |
| 40 | 40 | ||
| 41 | The main test we performed was finding a single optimal solution, and we | ||
| 42 | compared the results with vcube. This test was run in a single-thread | ||
| 43 | configuration and in two multithread configurations (with 4 and 16 | ||
| 44 | threads). We also ran a test on finding *all* optimal solutions which, | ||
| 45 | as far as I know, is a use case not supported by vcube; this latter test | ||
| 46 | was only run on 16 threads. | ||
| 47 | |||
| 48 | Since the size of the pruning table used by the solver is of utmost | ||
| 49 | importance, we include two statistics: time per cube and time per cube | ||
| 50 | *adjusted by table size*. The adjustment we took simply consists in | ||
| 51 | multiplying the time per cube by the size of the table. Empirically | ||
| 52 | this leads to more even results across the board, as the speed of the | ||
| 53 | solvers of the same family seems to scale linearly with the size of the | ||
| 54 | pruning table. | ||
| 55 | |||
| 56 | All benchmark tests were done on the following configuration: | 41 | All benchmark tests were done on the following configuration: |
| 57 | 42 | ||
| 58 | * CPU: AMD Ryzen 7 7700 (8 cores, 16 virtual threads) | 43 | * CPU: AMD Ryzen 7 7700 (8 cores, 16 virtual threads) |
| @@ -61,9 +46,29 @@ All benchmark tests were done on the following configuration: | |||
| 61 | * Operating system: Debian 13 (Linux kernel 6.12.57) | 46 | * Operating system: Debian 13 (Linux kernel 6.12.57) |
| 62 | * Compiler: GCC 14.2.0 for H48 and Clang 19.1.7 for vcube | 47 | * Compiler: GCC 14.2.0 for H48 and Clang 19.1.7 for vcube |
| 63 | 48 | ||
| 64 | ## Results (click on each item to expand) | 49 | ## Benchmark results |
| 50 | |||
| 51 | ### Single solution, single thread | ||
| 52 | |||
| 53 | The first test we performed was finding a single optimal solution, and | ||
| 54 | we compared the results with vcube. | ||
| 65 | 55 | ||
| 66 | <details><summary>Single solution, single thread</summary> | 56 | This test was run in a single-thread configuration, because the two |
| 57 | solvers use very different strategies for multithreading: vcube can only | ||
| 58 | parallelize by solving one cube per thread, while H48 is able to take | ||
| 59 | advantage of multiple threads even when solving a single cube. Therefore | ||
| 60 | we prefer to compare their single-threaded performance only. | ||
| 61 | |||
| 62 | Since the size of the pruning table used by the solver is of utmost | ||
| 63 | importance, we include two statistics: time per cube and time per cube | ||
| 64 | *adjusted by table size*. The adjustment we took simply consists in | ||
| 65 | multiplying the time per cube by the size of the table. Empirically this | ||
| 66 | leads to more even results across the board, although the speed of the | ||
| 67 | solvers of the same family does not scale exactly linearly with the size | ||
| 68 | of the pruning table. | ||
| 69 | |||
| 70 | <!-- The following details block can be found in benchmarks/single_thread_comparison.md --> | ||
| 71 | <details><summary>Results: Single solution, single thread</summary> | ||
| 67 | 72 | ||
| 68 | Time per cube (in seconds, lower is better). | 73 | Time per cube (in seconds, lower is better). |
| 69 | 74 | ||
| @@ -103,95 +108,92 @@ Time per cube adjusted for table size (in seconds \* GiB, lower is better). | |||
| 103 | <img src="img/20moves1thread.png"> | 108 | <img src="img/20moves1thread.png"> |
| 104 | </details> | 109 | </details> |
| 105 | 110 | ||
| 106 | <details><summary>Single solution, 4 threads</summary> | 111 | As we can see, adjusting for table size, H48 is generally faster than |
| 112 | vcube. The gap between the two solvers is larger for scrambles with | ||
| 113 | longer optimal solutions. | ||
| 114 | |||
| 115 | ### Single solution, multiple threads | ||
| 116 | |||
| 117 | The same benchmark as before is repeated using 4 and 16 threads (recall | ||
| 118 | that the CPU used for these tests has 8 physical cores and 16 virtual | ||
| 119 | threads). | ||
| 120 | |||
| 121 | As mentioned above, we don't compare these results to vcube. Instead, | ||
| 122 | we compare them with the single-threaded results for H48 and we show | ||
| 123 | how far the speedup factor is from a theoretically optimal 4x and 16x. | ||
| 124 | |||
| 125 | <!-- The following details block can be found in benchmarks/tables_4_threads.md --> | ||
| 126 | <details><summary>Results: Single solution, 4 threads</summary> | ||
| 107 | 127 | ||
| 108 | Time per cube (in seconds, lower is better). | 128 | Time per cube (in seconds, lower is better). |
| 109 | 129 | ||
| 110 | | Solver | Size |17 moves|18 moves|19 moves|20 moves|Superflip| | 130 | | Solver | Size |17 moves|18 moves|19 moves|20 moves|Superflip| |
| 111 | |:---------|:-------|-------:|-------:|-------:|-------:|--------:| | 131 | |:---------|:-------|-------:|-------:|-------:|-------:|--------:| |
| 112 | |vcube 212 |58.2 GiB| 0.03| 0.27| 1.04| 7.70| (a) | | ||
| 113 | |H48 h11 |56.5 GiB| 0.04| 0.14| 0.60| 3.97| 4.19| | 132 | |H48 h11 |56.5 GiB| 0.04| 0.14| 0.60| 3.97| 4.19| |
| 114 | |vcube 404 |31.8 GiB| 0.07| 0.30| 1.65| 16.17| (a) | | ||
| 115 | |H48 h10 |28.3 GiB| 0.05| 0.20| 0.91| 6.65| 9.81| | 133 | |H48 h10 |28.3 GiB| 0.05| 0.20| 0.91| 6.65| 9.81| |
| 116 | |vcube 308 |21.2 GiB| 0.05| 0.35| 1.78| 16.61| (a) | | ||
| 117 | |H48 h9 |14.1 GiB| 0.07| 0.39| 1.74| 12.54| 18.96| | 134 | |H48 h9 |14.1 GiB| 0.07| 0.39| 1.74| 12.54| 18.96| |
| 118 | |vcube 208 | 7.3 GiB| 0.16| 1.47| 5.86| | (a) | | ||
| 119 | |H48 h8 | 7.1 GiB| 0.13| 0.90| 3.71| | | | 135 | |H48 h8 | 7.1 GiB| 0.13| 0.90| 3.71| | | |
| 120 | |H48 h7 | 3.5 GiB| 0.17| 1.28| 6.12| | | | 136 | |H48 h7 | 3.5 GiB| 0.17| 1.28| 6.12| | | |
| 121 | |vcube 112 | 2.4 GiB| 0.29| 3.13| 11.95| | (a) | | ||
| 122 | |H48 h6 | 1.8 GiB| 0.33| 2.47| 12.22| | | | 137 | |H48 h6 | 1.8 GiB| 0.33| 2.47| 12.22| | | |
| 123 | 138 | ||
| 124 | Time per cube adjusted for table size (in seconds \* GiB, lower is better). | 139 | Speed-up factor (higher is better). |
| 125 | 140 | ||
| 126 | | Solver | Size |17 moves|18 moves|19 moves|20 moves|Superflip| | 141 | | Solver | Size |17 moves|18 moves|19 moves|20 moves|Superflip| |
| 127 | |:---------|:-------|-------:|-------:|-------:|-------:|--------:| | 142 | |:---------|:-------|-------:|-------:|-------:|-------:|--------:| |
| 128 | |vcube 212 |58.2 GiB| 2.03| 15.69| 60.25| 447.97| (a) | | 143 | |H48 h11 |56.5 GiB| 2.55| 3.46| 3.75| 3.96| 3.71| |
| 129 | |H48 h11 |56.5 GiB| 2.04| 8.17| 33.77| 224.59| 236.92| | 144 | |H48 h10 |28.3 GiB| 3.09| 3.71| 3.67| 3.54| 3.88| |
| 130 | |vcube 404 |31.8 GiB| 2.32| 9.50| 52.46| 514.50| (a) | | 145 | |H48 h9 |14.1 GiB| 3.25| 3.84| 3.85| | | |
| 131 | |H48 h10 |28.3 GiB| 1.37| 5.76| 25.83| 187.88| 277.18| | 146 | |H48 h8 | 7.1 GiB| 3.53| 3.72| 3.81| | | |
| 132 | |vcube 308 |21.2 GiB| 1.02| 7.52| 37.82| 352.36| (a) | | 147 | |H48 h7 | 3.5 GiB| 3.60| 3.78| 3.80| | | |
| 133 | |H48 h9 |14.1 GiB| 1.03| 5.45| 24.58| 177.17| 267.79| | 148 | |H48 h6 | 1.8 GiB| 3.77| 3.82| 3.79| | | |
| 134 | |vcube 208 | 7.3 GiB| 1.18| 10.69| 42.63| | (a) | | 149 | <img src="img/4threads.png"> |
| 135 | |H48 h8 | 7.1 GiB| 0.92| 6.39| 26.20| | | | ||
| 136 | |H48 h7 | 3.5 GiB| 0.62| 4.53| 21.62| | | | ||
| 137 | |vcube 112 | 2.4 GiB| 0.69| 7.59| 28.97| | (a) | | ||
| 138 | |H48 h6 | 1.8 GiB| 0.59| 4.37| 21.61| | | | ||
| 139 | |||
| 140 | (a) vcube cannot parallelize on a single scramble, the results for the | ||
| 141 | superflip are going to be the same as in the single thread case. | ||
| 142 | 150 | ||
| 143 | <img src="img/17moves4threads.png"> | ||
| 144 | <img src="img/18moves4threads.png"> | ||
| 145 | <img src="img/19moves4threads.png"> | ||
| 146 | <img src="img/20moves4threads.png"> | ||
| 147 | </details> | 151 | </details> |
| 148 | 152 | ||
| 149 | <details><summary>Single solution, 16 threads</summary> | 153 | <!-- The following details block can be found in benchmarks/tables_16_threads.md --> |
| 154 | <details><summary>Results: Single solution, 16 threads</summary> | ||
| 150 | 155 | ||
| 151 | Time per cube (in seconds, lower is better). | 156 | Time per cube (in seconds, lower is better). |
| 152 | 157 | ||
| 153 | | Solver | Size |17 moves|18 moves|19 moves|20 moves|Superflip| | 158 | | Solver | Size |17 moves|18 moves|19 moves|20 moves|Superflip| |
| 154 | |:---------|:-------|-------:|-------:|-------:|-------:|--------:| | 159 | |:---------|:-------|-------:|-------:|-------:|-------:|--------:| |
| 155 | |vcube 212 |58.2 GiB| 0.02| 0.13| 0.45| 2.84| (a) | | ||
| 156 | |H48 h11 |56.5 GiB| 0.02| 0.06| 0.22| 1.33| 1.84| | 160 | |H48 h11 |56.5 GiB| 0.02| 0.06| 0.22| 1.33| 1.84| |
| 157 | |vcube 404 |31.8 GiB| 0.04| 0.14| 0.65| 6.08| (a) | | ||
| 158 | |H48 h10 |28.3 GiB| 0.03| 0.08| 0.33| 2.34| 4.18| | 161 | |H48 h10 |28.3 GiB| 0.03| 0.08| 0.33| 2.34| 4.18| |
| 159 | |vcube 308 |21.2 GiB| 0.03| 0.19| 0.78| 6.67| (a) | | ||
| 160 | |H48 h9 |14.1 GiB| 0.04| 0.15| 0.64| 4.45| 8.09| | 162 | |H48 h9 |14.1 GiB| 0.04| 0.15| 0.64| 4.45| 8.09| |
| 161 | |vcube 208 | 7.3 GiB| 0.08| 0.79| 2.43| | (a) | | ||
| 162 | |H48 h8 | 7.1 GiB| 0.06| 0.34| 1.36| | | | 163 | |H48 h8 | 7.1 GiB| 0.06| 0.34| 1.36| | | |
| 163 | |H48 h7 | 3.5 GiB| 0.07| 0.47| 2.20| | | | 164 | |H48 h7 | 3.5 GiB| 0.07| 0.47| 2.20| | | |
| 164 | |vcube 112 | 2.4 GiB| 0.15| 1.63| 5.10| | (a) | | ||
| 165 | |H48 h6 | 1.8 GiB| 0.13| 0.91| 4.39| | | | 165 | |H48 h6 | 1.8 GiB| 0.13| 0.91| 4.39| | | |
| 166 | 166 | ||
| 167 | Time per cube adjusted for table size (in seconds \* GiB, lower is better). | 167 | Speed-up factor (higher is better). |
| 168 | 168 | ||
| 169 | | Solver | Size |17 moves|18 moves|19 moves|20 moves|Superflip| | 169 | | Solver | Size |17 moves|18 moves|19 moves|20 moves|Superflip| |
| 170 | |:---------|:-------|-------:|-------:|-------:|-------:|--------:| | 170 | |:---------|:-------|-------:|-------:|-------:|-------:|--------:| |
| 171 | |vcube 212 |58.2 GiB| 0.95| 7.83| 26.04| 165.03| (a) | | 171 | |H48 h11 |56.5 GiB| 3.90| 8.14| 10.39| 11.86| 8.45| |
| 172 | |H48 h11 |56.5 GiB| 1.34| 3.48| 12.19| 74.93| 103.98| | 172 | |H48 h10 |28.3 GiB| 5.72| 9.00| 10.03| 10.04| 9.09| |
| 173 | |vcube 404 |31.8 GiB| 1.21| 4.60| 20.76| 193.43| (a) | | 173 | |H48 h9 |14.1 GiB| 6.56| 9.75| 10.53| | | |
| 174 | |H48 h10 |28.3 GiB| 0.74| 2.37| 9.46| 66.13| 118.23| | 174 | |H48 h8 | 7.1 GiB| 8.08| 9.91| 10.40| | | |
| 175 | |vcube 308 |21.2 GiB| 0.67| 4.01| 16.48| 141.49| (a) | | 175 | |H48 h7 | 3.5 GiB| 8.59| 10.30| 10.57| | | |
| 176 | |H48 h9 |14.1 GiB| 0.51| 2.15| 8.98| 62.92| 114.31| | 176 | |H48 h6 | 1.8 GiB| 9.60| 10.39| 10.54| | | |
| 177 | |vcube 208 | 7.3 GiB| 0.56| 5.78| 17.68| | (a) | | 177 | <img src="img/16threads.png"> |
| 178 | |H48 h8 | 7.1 GiB| 0.40| 2.40| 9.59| | | | ||
| 179 | |H48 h7 | 3.5 GiB| 0.26| 1.66| 7.77| | | | ||
| 180 | |vcube 112 | 2.4 GiB| 0.35| 3.95| 12.37| | (a) | | ||
| 181 | |H48 h6 | 1.8 GiB| 0.23| 1.61| 7.76| | | | ||
| 182 | 178 | ||
| 183 | (a) vcube cannot parallelize on a single scramble, the results for the | ||
| 184 | superflip are going to be the same as in the single thread case. | ||
| 185 | |||
| 186 | <img src="img/17moves16threads.png"> | ||
| 187 | <img src="img/18moves16threads.png"> | ||
| 188 | <img src="img/19moves16threads.png"> | ||
| 189 | <img src="img/20moves16threads.png"> | ||
| 190 | </details> | 179 | </details> |
| 191 | 180 | ||
| 192 | <details><summary>All solutions, 16 threads</summary> | 181 | We can see that H48 scales pretty well with 4 threads, getting close |
| 182 | to the 4x theoretical maximum speedup in slower cases (small table or | ||
| 183 | long solutions). | ||
| 184 | |||
| 185 | In the 16 threads benchmark shows that, although the virtual threads | ||
| 186 | help push us beyond the 8x theoretical speedup that would be provided | ||
| 187 | by the 8 cores, we are nowhere near a 16x speedup. | ||
| 188 | |||
| 189 | ### All solutions | ||
| 193 | 190 | ||
| 194 | *Note: vcube does not have an option for finding multiple solutions.* | 191 | Finally, we ran a test on finding *all* optimal solutions which, as |
| 192 | far as I know, is a use case not supported by vcube. For convenience, | ||
| 193 | this test is only run on 16 threads. | ||
| 194 | |||
| 195 | <!-- The following details block can be found in benchmarks/all_solutions.md --> | ||
| 196 | <details><summary>Results: All solutions (16 threads)</summary> | ||
| 195 | 197 | ||
| 196 | Time per cube (in seconds, lower is better). | 198 | Time per cube (in seconds, lower is better). |
| 197 | 199 | ||
| @@ -217,16 +219,6 @@ Time per cube adjusted for table size (in seconds \* GiB, lower is better). | |||
| 217 | 219 | ||
| 218 | </details> | 220 | </details> |
| 219 | 221 | ||
| 220 | ## Comments on the results | ||
| 221 | |||
| 222 | * Adjusting for table size, H48 is generally faster than vcube. | ||
| 223 | * The gap between the two solvers is larger for scrambles with | ||
| 224 | longer optimal solutions. | ||
| 225 | * On sets of 25 scrambles, H48 performs better than vcube when using | ||
| 226 | multiple threads, compared to their single-threaded performance. | ||
| 227 | However, this advantage will likely disappear (or | ||
| 228 | even invert) if we increase the size of the set. | ||
| 229 | |||
| 230 | ## Other notes | 222 | ## Other notes |
| 231 | 223 | ||
| 232 | * To repeat the benchmarks, use `./benchmarks/run-h48-benchmarks.sh`. | 224 | * To repeat the benchmarks, use `./benchmarks/run-h48-benchmarks.sh`. |
| @@ -249,8 +241,3 @@ Time per cube adjusted for table size (in seconds \* GiB, lower is better). | |||
| 249 | * For H48, both GCC and Clang have been tried, with the same options; | 241 | * For H48, both GCC and Clang have been tried, with the same options; |
| 250 | the resulting executable was about 10% faster with GCC compared to Clang. | 242 | the resulting executable was about 10% faster with GCC compared to Clang. |
| 251 | vcube only supports compiling with Clang. | 243 | vcube only supports compiling with Clang. |
| 252 | * The performance of the H48 solver depends slightly, but measurably, on the | ||
| 253 | alignment of the pruning table in memory. This is not handled by the core | ||
| 254 | library, but by the program that uses it. For these tests, we have used as | ||
| 255 | reference implementation the program in `tools/301_solve_file`, which | ||
| 256 | ensures 64-byte alignment. | ||
