├── .gitmodules
├── CMakeLists.txt
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── benchmarks
├── challenging
│ ├── A.1048576.csv
│ ├── B.1048576.csv
│ ├── C.1048576.csv
│ ├── D.1048576.csv
│ ├── E.1048576.csv
│ ├── F.1048576.csv
│ ├── G.1048576.csv
│ ├── H.1048576.csv
│ ├── I.1048576.csv
│ ├── J.1048576.csv
│ └── K.1048576.csv
└── examples
│ └── input.12.csv
├── img
├── acm_badges.png
├── lattice.gif
├── minimalloc-with-badges.png
└── minimalloc.png
├── scripts
└── run-challenging.sh
├── src
├── converter.cc
├── converter.h
├── main.cc
├── minimalloc.cc
├── minimalloc.h
├── solver.cc
├── solver.h
├── sweeper.cc
├── sweeper.h
├── validator.cc
└── validator.h
└── tests
├── converter_test.cc
├── minimalloc_test.cc
├── solver_test.cc
├── sweeper_test.cc
└── validator_test.cc
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "external/abseil-cpp"]
2 | path = external/abseil-cpp
3 | url = https://github.com/abseil/abseil-cpp.git
4 | [submodule "external/googletest"]
5 | path = external/googletest
6 | url = https://github.com/google/googletest.git
7 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.25.1)
2 | project(MiniMalloc)
3 | set(CMAKE_CXX_STANDARD 20)
4 | set(CMAKE_CXX_STANDARD_REQUIRED ON)
5 | add_subdirectory(external/abseil-cpp)
6 | add_subdirectory(external/googletest)
7 | add_executable(minimalloc
8 | src/converter.cc
9 | src/main.cc
10 | src/minimalloc.cc
11 | src/solver.cc
12 | src/sweeper.cc
13 | src/validator.cc
14 | )
15 | target_link_libraries(minimalloc
16 | absl::flags_parse
17 | absl::statusor
18 | )
19 |
20 | enable_testing()
21 |
22 | add_executable(converter_test
23 | tests/converter_test.cc
24 | src/converter.cc
25 | src/minimalloc.cc
26 | )
27 | target_link_libraries(converter_test
28 | GTest::gmock_main
29 | GTest::gtest_main
30 | absl::flags
31 | absl::statusor
32 | )
33 | add_test(NAME converter_test COMMAND converter_test)
34 |
35 | add_executable(minimalloc_test
36 | tests/minimalloc_test.cc
37 | src/minimalloc.cc
38 | )
39 | target_link_libraries(minimalloc_test
40 | GTest::gmock_main
41 | GTest::gtest_main
42 | absl::statusor
43 | )
44 | add_test(NAME minimalloc_test COMMAND minimalloc_test)
45 |
46 | add_executable(solver_test
47 | tests/solver_test.cc
48 | src/minimalloc.cc
49 | src/solver.cc
50 | src/sweeper.cc
51 | )
52 | target_link_libraries(solver_test
53 | GTest::gmock_main
54 | GTest::gtest_main
55 | absl::flags
56 | absl::statusor
57 | )
58 | add_test(NAME solver_test COMMAND solver_test)
59 |
60 | add_executable(sweeper_test
61 | tests/sweeper_test.cc
62 | src/minimalloc.cc
63 | src/sweeper.cc
64 | )
65 | target_link_libraries(sweeper_test
66 | GTest::gtest_main
67 | absl::flags
68 | absl::statusor
69 | )
70 | add_test(NAME sweeper_test COMMAND sweeper_test)
71 |
72 | add_executable(validator_test
73 | tests/validator_test.cc
74 | src/minimalloc.cc
75 | src/validator.cc
76 | )
77 | target_link_libraries(validator_test
78 | GTest::gtest_main
79 | absl::statusor
80 | )
81 | add_test(NAME validator_test COMMAND validator_test)
82 |
83 | include(GoogleTest)
84 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # How to Contribute
2 |
3 | We'd love to accept your patches and contributions to this project.
4 |
5 | ## Before you begin
6 |
7 | ### Sign our Contributor License Agreement
8 |
9 | Contributions to this project must be accompanied by a
10 | [Contributor License Agreement](https://cla.developers.google.com/about) (CLA).
11 | You (or your employer) retain the copyright to your contribution; this simply
12 | gives us permission to use and redistribute your contributions as part of the
13 | project.
14 |
15 | If you or your current employer have already signed the Google CLA (even if it
16 | was for a different project), you probably don't need to do it again.
17 |
18 | Visit to see your current agreements or to
19 | sign a new one.
20 |
21 | ### Review our Community Guidelines
22 |
23 | This project follows
24 | [Google's Open Source Community Guidelines](https://opensource.google/conduct/).
25 |
26 | ## Contribution process
27 |
28 | ### Code Reviews
29 |
30 | All submissions, including submissions by project members, require review. We
31 | use GitHub pull requests for this purpose. Consult
32 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
33 | information on using pull requests.
34 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Source code for our [ASPLOS 2023](https://www.asplos-conference.org/asplos2023/) paper, "***[MiniMalloc: A Lightweight Memory Allocator for Hardware-Accelerated Machine Learning](https://doi.org/10.1145/3623278.3624752)***."
6 |
7 | ## News
8 |
9 | * MiniMalloc to be featured in the [MIT PL Review 2025](https://plr.csail.mit.edu/) on April 25th, 2025.
10 |
11 | ## Overview
12 |
13 | An increasing number of deep learning workloads are being supported by *hardware acceleration*. In order to unlock the maximum performance of a hardware accelerator, a machine learning model must first be carefully mapped onto its various internal components by way of a *compiler*. One especially important problem faced by a production-class compiler is that of *memory allocation*, whereby a set of buffers with predefined lifespans are mapped onto offsets in global memory. Since this allocation is performed statically, the compiler has the freedom to place buffers strategically, but must nevertheless wrestle with a combinatorial explosion in the number of assignment possibilities.
14 |
15 | **MiniMalloc** is a state-of-the-art algorithm designed specifically for static memory allocation that uses several novel search techiques in order to solve such problems efficiently and effectively.
16 |
17 | ## How it works
18 |
19 | A key insight motivating our methodology is the discovery of a specific category of solutions -- which we call *canonical solutions* -- that correspond to the members of an algebraic lattice:
20 |
21 |
22 |
23 |
24 |
25 | By limiting our exploration to the subset of canonical solutions, we can dramatically reduce the size of the search space while simultaneously ensuring that our algorithm remains sound and complete. We also employ a new spatial inference technique that takes advantage of this special structure, allowing our solver to backtrack much earlier than otherwise possible. Finally, we implement a new mechanism for detecting and eliminating dominated solutions from consideration.
26 |
27 | ## Setup
28 |
29 | ```
30 | $ git clone --recursive git@github.com:google/minimalloc.git && \
31 | cd minimalloc && cmake -DCMAKE_BUILD_TYPE=Release && make
32 | ```
33 |
34 | ## Example input file
35 |
36 | ```
37 | id,lower,upper,size
38 | b1,0,3,4
39 | b2,3,9,4
40 | b3,0,9,4
41 | b4,9,21,4
42 | b5,0,21,4
43 | ```
44 |
45 | ## Example usage
46 |
47 | ```
48 | $ ./minimalloc --capacity=12 --input=benchmarks/examples/input.12.csv --output=output.12.csv
49 | ```
50 |
51 | ## Example output file
52 |
53 | ```
54 | id,lower,upper,size,offset
55 | b1,0,3,4,8
56 | b2,3,9,4,8
57 | b3,0,9,4,4
58 | b4,9,21,4,4
59 | b5,0,21,4,0
60 | ```
61 |
62 | ## How to cite?
63 |
64 | ```bibtex
65 | @inproceedings{Moffitt2023,
66 | title = {{MiniMalloc}: A Lightweight Memory Allocator for Hardware-Accelerated Machine Learning},
67 | booktitle = {Proceedings of the 28th International Conference on Architectural Support for Programming Languages and Operating Systems},
68 | volume = {4},
69 | pages = {238--252},
70 | author = {Moffitt, Michael D.},
71 | year = {2023},
72 | series = {ASPLOS 2023},
73 | url = {https://doi.org/10.1145/3623278.3624752},
74 | doi = {10.1145/3623278.3624752}
75 | }
76 | ```
77 |
78 | ## Disclaimer
79 |
80 | This is not an officially supported Google product.
81 |
--------------------------------------------------------------------------------
/benchmarks/challenging/A.1048576.csv:
--------------------------------------------------------------------------------
1 | id,lower,upper,size
2 | 0,995328,1000448,656384
3 | 1,779264,828416,183296
4 | 2,0,1048576,5120
5 | 3,0,307200,43008
6 | 4,541696,749568,44032
7 | 5,677888,763904,64512
8 | 6,650240,966656,10240
9 | 7,0,966656,11264
10 | 8,388096,650240,13312
11 | 9,0,174080,28672
12 | 10,194560,221184,291840
13 | 11,169984,272384,34816
14 | 12,595968,840704,52224
15 | 13,0,1048576,2048
16 | 14,650240,966656,19456
17 | 15,0,60416,131072
18 | 16,362496,595968,62464
19 | 17,0,202752,25600
20 | 18,272384,636928,34816
21 | 19,354304,374784,162816
22 | 20,0,288768,34816
23 | 21,685056,779264,27648
24 | 22,153600,362496,1024
25 | 23,169984,272384,9216
26 | 24,760832,966656,7168
27 | 25,610304,626688,81920
28 | 26,903168,1048576,75776
29 | 27,650240,760832,86016
30 | 28,595968,840704,59392
31 | 29,144384,167936,75776
32 | 30,760832,966656,7168
33 | 31,0,60416,113664
34 | 32,680960,840704,4096
35 | 33,388096,406528,57344
36 | 34,272384,336896,165888
37 | 35,680960,840704,91136
38 | 36,989184,995328,656384
39 | 37,272384,636928,6144
40 | 38,650240,745472,54272
41 | 39,272384,336896,117760
42 | 40,362496,595968,10240
43 | 41,408576,610304,18432
44 | 42,143360,236544,44032
45 | 43,851968,1048576,62464
46 | 44,100352,153600,126976
47 | 45,354304,433152,96256
48 | 46,0,966656,10240
49 | 47,685056,779264,1024
50 | 48,169984,272384,128000
51 | 49,851968,1048576,15360
52 | 50,202752,1048576,5120
53 | 51,763904,966656,64512
54 | 52,60416,97280,321536
55 | 53,651264,890880,20480
56 | 54,167936,362496,75776
57 | 55,31744,966656,2048
58 | 56,851968,1048576,52224
59 | 57,272384,636928,16384
60 | 58,60416,97280,142336
61 | 59,680960,840704,18432
62 | 60,374784,388096,162816
63 | 61,108544,126976,433152
64 | 62,977920,989184,656384
65 | 63,305152,506880,24576
66 | 64,650240,677888,64512
67 | 65,104448,144384,83968
68 | 66,126976,161792,324608
69 | 67,31744,966656,11264
70 | 68,108544,169984,30720
71 | 69,636928,650240,94208
72 | 70,595968,840704,33792
73 | 71,31744,966656,8192
74 | 72,760832,943104,71680
75 | 73,0,966656,4096
76 | 74,0,1048576,10240
77 | 75,898048,1048576,28672
78 | 76,0,966656,3072
79 | 77,680960,840704,21504
80 | 78,272384,636928,27648
81 | 79,236544,541696,44032
82 | 80,0,966656,1024
83 | 81,408576,610304,63488
84 | 82,336896,354304,352256
85 | 83,388096,447488,92160
86 | 84,840704,851968,205824
87 | 85,31744,966656,2048
88 | 86,100352,104448,83968
89 | 87,1000448,1029120,375808
90 | 88,31744,966656,8192
91 | 89,595968,840704,5120
92 | 90,272384,636928,9216
93 | 91,851968,903168,75776
94 | 92,1000448,1029120,280576
95 | 93,650240,966656,22528
96 | 94,202752,1048576,6144
97 | 95,943104,966656,71680
98 | 96,31744,966656,1024
99 | 97,433152,482304,96256
100 | 98,202752,1048576,14336
101 | 99,0,13312,126976
102 | 100,224256,272384,291840
103 | 101,307200,650240,43008
104 | 102,272384,650240,17408
105 | 103,650240,966656,34816
106 | 104,0,651264,20480
107 | 105,595968,680960,135168
108 | 106,221184,224256,291840
109 | 107,97280,108544,463872
110 | 108,0,966656,6144
111 | 109,447488,564224,92160
112 | 110,828416,921600,64512
113 | 111,749568,750592,44032
114 | 112,921600,966656,215040
115 | 113,0,100352,83968
116 | 114,408576,650240,11264
117 | 115,828416,921600,150528
118 | 116,0,143360,44032
119 | 117,423936,595968,41984
120 | 118,650240,685056,215040
121 | 119,0,31744,32768
122 | 120,685056,828416,31744
123 | 121,0,362496,23552
124 | 122,0,60416,219136
125 | 123,685056,779264,154624
126 | 124,288768,305152,24576
127 | 125,1029120,1048576,656384
128 | 126,626688,650240,81920
129 | 127,362496,595968,25600
130 | 128,564224,650240,92160
131 | 129,482304,650240,80896
132 | 130,406528,650240,57344
133 | 131,750592,966656,44032
134 | 132,161792,169984,433152
135 | 133,169984,194560,291840
136 | 134,506880,1048576,24576
137 | 135,144384,362496,8192
138 | 136,153600,362496,56320
139 | 137,362496,595968,1024
140 | 138,13312,100352,126976
141 | 139,153600,362496,69632
142 | 140,272384,336896,68608
143 | 141,745472,966656,54272
144 | 142,288768,1048576,10240
145 | 143,354304,408576,93184
146 | 144,423936,595968,70656
147 | 145,464896,595968,73728
148 | 146,840704,922624,79872
149 | 147,0,101376,51200
150 | 148,0,966656,10240
151 | 149,126976,161792,108544
152 | 150,922624,1048576,79872
153 | 151,890880,966656,20480
154 | 152,482304,650240,15360
155 | 153,966656,977920,656384
156 |
--------------------------------------------------------------------------------
/benchmarks/challenging/B.1048576.csv:
--------------------------------------------------------------------------------
1 | id,lower,upper,size
2 | 0,44032,282624,34816
3 | 1,0,522240,6144
4 | 2,101376,118784,263168
5 | 3,364544,449536,115712
6 | 4,1015808,1048576,124928
7 | 5,778240,971776,15360
8 | 6,145408,175104,316416
9 | 7,329728,778240,24576
10 | 8,112640,405504,20480
11 | 9,181248,778240,7168
12 | 10,508928,1048576,19456
13 | 11,0,17408,187392
14 | 12,67584,108544,58368
15 | 13,856064,877568,34816
16 | 14,189440,366592,47104
17 | 15,782336,872448,72704
18 | 16,181248,778240,17408
19 | 17,782336,1048576,44032
20 | 18,957440,1000448,33792
21 | 19,189440,366592,31744
22 | 20,404480,411648,335872
23 | 21,782336,915456,92160
24 | 22,17408,778240,7168
25 | 23,76800,181248,34816
26 | 24,646144,782336,62464
27 | 25,646144,782336,23552
28 | 26,522240,978944,25600
29 | 27,560128,576512,253952
30 | 28,527360,529408,211968
31 | 29,17408,64512,79872
32 | 30,189440,364544,54272
33 | 31,118784,189440,165888
34 | 32,67584,108544,258048
35 | 33,508928,1048576,7168
36 | 34,660480,1048576,24576
37 | 35,957440,1041408,139264
38 | 36,1033216,1048576,164864
39 | 37,0,17408,285696
40 | 38,578560,1048576,3072
41 | 39,411648,449536,317440
42 | 40,181248,778240,10240
43 | 41,869376,872448,197632
44 | 42,978944,1048576,25600
45 | 43,0,1000448,5120
46 | 44,17408,299008,21504
47 | 45,134144,612352,12288
48 | 46,0,189440,30720
49 | 47,449536,468992,632832
50 | 48,646144,782336,91136
51 | 49,340992,396288,188416
52 | 50,0,63488,14336
53 | 51,653312,1048576,2048
54 | 52,299008,642048,21504
55 | 53,17408,642048,3072
56 | 54,957440,1048576,23552
57 | 55,340992,396288,53248
58 | 56,778240,971776,28672
59 | 57,958464,1033216,164864
60 | 58,505856,508928,34816
61 | 59,915456,1048576,28672
62 | 60,782336,856064,164864
63 | 61,82944,384000,25600
64 | 62,17408,778240,13312
65 | 63,118784,189440,97280
66 | 64,863232,869376,197632
67 | 65,235520,268288,335872
68 | 66,872448,932864,45056
69 | 67,782336,863232,49152
70 | 68,189440,449536,11264
71 | 69,0,82944,61440
72 | 70,0,1048576,2048
73 | 71,0,522240,19456
74 | 72,474112,778240,38912
75 | 73,340992,396288,92160
76 | 74,17408,778240,2048
77 | 75,527360,586752,83968
78 | 76,0,134144,33792
79 | 77,642048,743424,25600
80 | 78,778240,971776,4096
81 | 79,957440,1048576,107520
82 | 80,0,508928,3072
83 | 81,654336,665600,186368
84 | 82,189440,235520,80896
85 | 83,646144,782336,76800
86 | 84,646144,782336,81920
87 | 85,17408,778240,4096
88 | 86,0,112640,34816
89 | 87,366592,449536,78848
90 | 88,396288,404480,333824
91 | 89,63488,67584,205824
92 | 90,0,6144,34816
93 | 91,17408,329728,24576
94 | 92,189440,449536,47104
95 | 93,446464,505856,34816
96 | 94,646144,654336,186368
97 | 95,307200,340992,333824
98 | 96,17408,642048,1024
99 | 97,778240,971776,46080
100 | 98,497664,516096,632832
101 | 99,877568,1000448,34816
102 | 100,0,1000448,10240
103 | 101,508928,1048576,7168
104 | 102,189440,364544,61440
105 | 103,586752,617472,378880
106 | 104,282624,446464,34816
107 | 105,189440,235520,254976
108 | 106,995328,1015808,124928
109 | 107,782336,915456,61440
110 | 108,189440,449536,44032
111 | 109,17408,291840,38912
112 | 110,621568,957440,33792
113 | 111,17408,778240,11264
114 | 112,508928,524288,46080
115 | 113,928768,958464,164864
116 | 114,778240,878592,51200
117 | 115,726016,782336,186368
118 | 116,872448,932864,57344
119 | 117,508928,1048576,6144
120 | 118,0,63488,191488
121 | 119,631808,646144,632832
122 | 120,468992,497664,179200
123 | 121,508928,1048576,13312
124 | 122,134144,612352,21504
125 | 123,17408,748544,15360
126 | 124,405504,856064,20480
127 | 125,516096,560128,253952
128 | 126,646144,782336,1024
129 | 127,856064,928768,164864
130 | 128,778240,971776,12288
131 | 129,0,1000448,5120
132 | 130,578560,653312,43008
133 | 131,6144,44032,34816
134 | 132,291840,474112,38912
135 | 133,743424,778240,25600
136 | 134,646144,782336,56320
137 | 135,576512,617472,253952
138 | 136,468992,497664,121856
139 | 137,660480,1048576,16384
140 | 138,268288,299008,335872
141 | 139,108544,145408,316416
142 | 140,411648,449536,18432
143 | 141,646144,782336,53248
144 | 142,17408,76800,34816
145 | 143,872448,932864,167936
146 | 144,778240,971776,14336
147 | 145,299008,307200,335872
148 | 146,64512,189440,22528
149 | 147,175104,189440,316416
150 | 148,665600,726016,186368
151 | 149,915456,995328,124928
152 | 150,384000,508928,61440
153 | 151,82944,384000,35840
154 | 152,878592,1048576,51200
155 | 153,612352,621568,33792
156 | 154,17408,64512,205824
157 | 155,524288,578560,46080
158 | 156,17408,778240,5120
159 | 157,112640,856064,14336
160 | 158,0,1000448,12288
161 | 159,0,67584,110592
162 | 160,782336,863232,148480
163 | 161,653312,660480,40960
164 | 162,527360,586752,82944
165 | 163,468992,497664,331776
166 | 164,932864,957440,270336
167 | 165,516096,527360,378880
168 | 166,529408,586752,211968
169 | 167,17408,778240,5120
170 | 168,1000448,1048576,101376
171 | 169,617472,631808,632832
172 |
--------------------------------------------------------------------------------
/benchmarks/challenging/C.1048576.csv:
--------------------------------------------------------------------------------
1 | id,lower,upper,size
2 | 0,871424,906240,143360
3 | 1,0,23552,29696
4 | 2,23552,568320,18432
5 | 3,0,1048576,5120
6 | 4,235520,259072,70656
7 | 5,530432,735232,40960
8 | 6,66560,346112,32768
9 | 7,212992,273408,160768
10 | 8,265216,368640,12288
11 | 9,916480,930816,712704
12 | 10,569344,634880,117760
13 | 11,871424,916480,1024
14 | 12,355328,796672,17408
15 | 13,404480,450560,123904
16 | 14,0,212992,37888
17 | 15,23552,533504,5120
18 | 16,0,1046528,8192
19 | 17,529408,530432,398336
20 | 18,1046528,1048576,25600
21 | 19,378880,407552,207872
22 | 20,667648,735232,102400
23 | 21,772096,881664,51200
24 | 22,1029120,1048576,88064
25 | 23,846848,1048576,17408
26 | 24,237568,491520,18432
27 | 25,533504,827392,11264
28 | 26,934912,1048576,11264
29 | 27,1015808,1047552,249856
30 | 28,857088,871424,411648
31 | 29,0,1048576,8192
32 | 30,881664,916480,236544
33 | 31,772096,881664,84992
34 | 32,1015808,1047552,140288
35 | 33,586752,602112,193536
36 | 34,6144,212992,44032
37 | 35,450560,488448,123904
38 | 36,815104,839680,411648
39 | 37,941056,1048576,57344
40 | 38,309248,345088,253952
41 | 39,212992,265216,131072
42 | 40,212992,273408,49152
43 | 41,0,23552,64512
44 | 42,772096,916480,52224
45 | 43,0,212992,18432
46 | 44,1015808,1047552,87040
47 | 45,772096,775168,411648
48 | 46,169984,212992,192512
49 | 47,602112,694272,16384
50 | 48,27648,53248,192512
51 | 49,346112,451584,66560
52 | 50,0,1048576,3072
53 | 51,694272,735232,59392
54 | 52,993280,1048576,52224
55 | 53,6144,139264,71680
56 | 54,537600,566272,313344
57 | 55,462848,477184,342016
58 | 56,306176,368640,111616
59 | 57,568320,902144,12288
60 | 58,265216,306176,111616
61 | 59,634880,662528,313344
62 | 60,273408,309248,209920
63 | 61,1020928,1048576,13312
64 | 62,812032,815104,328704
65 | 63,566272,586752,193536
66 | 64,259072,393216,70656
67 | 65,212992,297984,48128
68 | 66,101376,138240,192512
69 | 67,906240,916480,305152
70 | 68,530432,569344,256000
71 | 69,32768,153600,61440
72 | 70,6144,139264,57344
73 | 71,0,60416,11264
74 | 72,530432,735232,19456
75 | 73,569344,634880,86016
76 | 74,529408,533504,66560
77 | 75,778240,812032,34816
78 | 76,566272,673792,53248
79 | 77,60416,934912,11264
80 | 78,662528,667648,313344
81 | 79,569344,634880,135168
82 | 80,495616,530432,20480
83 | 81,681984,827392,39936
84 | 82,772096,822272,100352
85 | 83,775168,778240,328704
86 | 84,902144,1048576,41984
87 | 85,491520,529408,95232
88 | 86,0,1048576,7168
89 | 87,796672,846848,17408
90 | 88,530432,569344,82944
91 | 89,602112,659456,177152
92 | 90,491520,524288,282624
93 | 91,6144,212992,8192
94 | 92,6144,212992,45056
95 | 93,139264,212992,77824
96 | 94,730112,735232,157696
97 | 95,0,66560,32768
98 | 96,212992,316416,69632
99 | 97,6144,32768,84992
100 | 98,568320,642048,22528
101 | 99,23552,233472,24576
102 | 100,0,332800,13312
103 | 101,345088,407552,40960
104 | 102,980992,1015808,207872
105 | 103,393216,409600,70656
106 | 104,0,1046528,1024
107 | 105,582656,681984,84992
108 | 106,152576,254976,46080
109 | 107,871424,916480,63488
110 | 108,332800,1020928,13312
111 | 109,0,346112,3072
112 | 110,1046528,1048576,14336
113 | 111,451584,529408,66560
114 | 112,694272,735232,21504
115 | 113,960512,1015808,74752
116 | 114,117760,1048576,10240
117 | 115,659456,694272,177152
118 | 116,681984,827392,1024
119 | 117,495616,530432,293888
120 | 118,297984,491520,48128
121 | 119,681984,827392,44032
122 | 120,254976,367616,46080
123 | 121,941056,1048576,90112
124 | 122,0,355328,17408
125 | 123,345088,407552,5120
126 | 124,379904,444416,88064
127 | 125,566272,673792,66560
128 | 126,212992,309248,27648
129 | 127,6144,212992,20480
130 | 128,0,1046528,8192
131 | 129,735232,772096,262144
132 | 130,6144,212992,7168
133 | 131,0,1046528,1024
134 | 132,1047552,1048576,477184
135 | 133,153600,212992,84992
136 | 134,827392,1048576,4096
137 | 135,871424,906240,161792
138 | 136,930816,941056,147456
139 | 137,960512,980992,207872
140 | 138,960512,1015808,62464
141 | 139,822272,881664,100352
142 | 140,0,27648,192512
143 | 141,6144,212992,37888
144 | 142,212992,309248,104448
145 | 143,827392,1048576,27648
146 | 144,32768,153600,23552
147 | 145,673792,694272,119808
148 | 146,139264,212992,91136
149 | 147,363520,491520,69632
150 | 148,827392,993280,52224
151 | 149,138240,169984,192512
152 | 150,735232,738304,438272
153 | 151,265216,491520,7168
154 | 152,930816,951296,477184
155 | 153,0,1046528,9216
156 | 154,233472,533504,24576
157 | 155,0,1048576,8192
158 | 156,827392,1048576,12288
159 | 157,634880,667648,25600
160 | 158,667648,730112,157696
161 | 159,0,346112,27648
162 | 160,960512,1015808,82944
163 | 161,53248,101376,192512
164 | 162,0,1048576,5120
165 | 163,368640,404480,123904
166 | 164,345088,378880,207872
167 | 165,960512,1015808,49152
168 | 166,491520,495616,314368
169 | 167,930816,1029120,88064
170 | 168,778240,812032,293888
171 | 169,316416,363520,69632
172 | 170,0,1048576,6144
173 | 171,871424,916480,41984
174 | 172,409600,491520,70656
175 | 173,212992,491520,5120
176 | 174,533504,582656,84992
177 | 175,491520,529408,20480
178 | 176,0,1048576,9216
179 | 177,0,1046528,5120
180 | 178,642048,1048576,22528
181 | 179,0,346112,3072
182 | 180,568320,902144,29696
183 | 181,0,1046528,7168
184 | 182,212992,237568,46080
185 | 183,738304,772096,197632
186 | 184,530432,537600,313344
187 | 185,0,427008,13312
188 | 186,444416,462848,342016
189 | 187,735232,916480,12288
190 | 188,694272,735232,232448
191 | 189,237568,491520,27648
192 | 190,212992,235520,70656
193 | 191,407552,444416,253952
194 | 192,6144,139264,39936
195 | 193,775168,815104,82944
196 | 194,23552,152576,46080
197 | 195,367616,568320,46080
198 | 196,839680,857088,411648
199 | 197,6144,212992,47104
200 | 198,477184,491520,342016
201 | 199,427008,1048576,13312
202 | 200,309248,379904,88064
203 | 201,0,1048576,8192
204 | 202,524288,529408,282624
205 |
--------------------------------------------------------------------------------
/benchmarks/challenging/D.1048576.csv:
--------------------------------------------------------------------------------
1 | id,lower,upper,size
2 | 0,1024,172032,14336
3 | 1,200704,212992,70656
4 | 2,705536,761856,37888
5 | 3,37888,528384,11264
6 | 4,45056,637952,11264
7 | 5,0,290816,9216
8 | 6,376832,973824,13312
9 | 7,45056,1048576,5120
10 | 8,351232,502784,56320
11 | 9,637952,759808,44032
12 | 10,708608,1048576,14336
13 | 11,995328,1048576,68608
14 | 12,101376,115712,121856
15 | 13,203776,538624,18432
16 | 14,0,502784,2048
17 | 15,553984,695296,49152
18 | 16,618496,831488,13312
19 | 17,8192,230400,3072
20 | 18,908288,973824,16384
21 | 19,631808,776192,43008
22 | 20,695296,1048576,11264
23 | 21,301056,556032,25600
24 | 22,608256,776192,21504
25 | 23,0,1048576,5120
26 | 24,1011712,1048576,34816
27 | 25,0,1048576,2048
28 | 26,0,176128,16384
29 | 27,172032,404480,14336
30 | 28,299008,340992,114688
31 | 29,339968,789504,13312
32 | 30,710656,973824,34816
33 | 31,203776,538624,23552
34 | 32,695296,1048576,17408
35 | 33,0,1048576,2048
36 | 34,761856,973824,37888
37 | 35,0,844800,4096
38 | 36,376832,710656,12288
39 | 37,36864,79872,80896
40 | 38,0,865280,2048
41 | 39,436224,608256,43008
42 | 40,271360,351232,70656
43 | 41,808960,1048576,35840
44 | 42,45056,1048576,1024
45 | 43,0,101376,57344
46 | 44,973824,1048576,103424
47 | 45,239616,299008,114688
48 | 46,196608,210944,121856
49 | 47,839680,983040,46080
50 | 48,37888,528384,13312
51 | 49,0,39936,68608
52 | 50,0,1048576,4096
53 | 51,37888,528384,7168
54 | 52,376832,515072,57344
55 | 53,261120,737280,4096
56 | 54,37888,528384,12288
57 | 55,553984,1048576,14336
58 | 56,502784,973824,18432
59 | 57,34816,708608,9216
60 | 58,553984,695296,25600
61 | 59,618496,831488,36864
62 | 60,488448,844800,15360
63 | 61,0,1011712,4096
64 | 62,0,844800,2048
65 | 63,296960,328704,121856
66 | 64,0,1048576,6144
67 | 65,878592,1048576,46080
68 | 66,502784,973824,10240
69 | 67,246784,789504,5120
70 | 68,0,1048576,3072
71 | 69,0,239616,8192
72 | 70,210944,286720,53248
73 | 71,88064,246784,18432
74 | 72,0,539648,11264
75 | 73,0,865280,1024
76 | 74,323584,436224,57344
77 | 75,0,844800,9216
78 | 76,0,1024,14336
79 | 77,631808,681984,68608
80 | 78,620544,973824,23552
81 | 79,0,1048576,1024
82 | 80,776192,880640,59392
83 | 81,210944,286720,68608
84 | 82,608256,631808,76800
85 | 83,0,37888,74752
86 | 84,737280,952320,29696
87 | 85,340992,1048576,10240
88 | 86,0,518144,14336
89 | 87,45056,637952,7168
90 | 88,39936,203776,40960
91 | 89,0,1048576,5120
92 | 90,257024,261120,29696
93 | 91,0,239616,14336
94 | 92,261120,737280,11264
95 | 93,502784,973824,5120
96 | 94,290816,502784,33792
97 | 95,376832,908288,16384
98 | 96,0,844800,1024
99 | 97,0,165888,40960
100 | 98,789504,844800,46080
101 | 99,539648,844800,11264
102 | 100,0,275456,24576
103 | 101,556032,722944,25600
104 | 102,0,1048576,3072
105 | 103,0,8192,83968
106 | 104,0,239616,36864
107 | 105,8192,36864,80896
108 | 106,0,1048576,5120
109 | 107,0,488448,15360
110 | 108,212992,230400,80896
111 | 109,515072,973824,7168
112 | 110,0,290816,10240
113 | 111,340992,1048576,7168
114 | 112,0,285696,15360
115 | 113,722944,1048576,25600
116 | 114,286720,296960,121856
117 | 115,759808,1048576,18432
118 | 116,66560,493568,20480
119 | 117,0,200704,43008
120 | 118,323584,436224,29696
121 | 119,776192,880640,35840
122 | 120,519168,844800,24576
123 | 121,340992,1048576,10240
124 | 122,88064,339968,13312
125 | 123,994304,1003520,211968
126 | 124,0,1048576,3072
127 | 125,328704,376832,121856
128 | 126,436224,608256,44032
129 | 127,502784,973824,18432
130 | 128,376832,710656,22528
131 | 129,518144,553984,27648
132 | 130,573440,618496,50176
133 | 131,992256,994304,211968
134 | 132,37888,528384,3072
135 | 133,515072,573440,50176
136 | 134,212992,271360,70656
137 | 135,0,844800,8192
138 | 136,0,1048576,2048
139 | 137,631808,776192,25600
140 | 138,340992,1048576,9216
141 | 139,0,1048576,3072
142 | 140,0,1048576,5120
143 | 141,275456,519168,24576
144 | 142,502784,973824,7168
145 | 143,37888,528384,12288
146 | 144,553984,1048576,13312
147 | 145,870400,973824,50176
148 | 146,285696,323584,99328
149 | 147,301056,1048576,12288
150 | 148,120832,212992,80896
151 | 149,831488,870400,50176
152 | 150,880640,973824,63488
153 | 151,88064,789504,9216
154 | 152,115712,196608,61440
155 | 153,759808,1048576,25600
156 | 154,404480,865280,14336
157 | 155,39936,203776,8192
158 | 156,261120,737280,9216
159 | 157,351232,502784,14336
160 | 158,844800,958464,77824
161 | 159,1003520,1048576,69632
162 | 160,0,1011712,5120
163 | 161,435200,1011712,15360
164 | 162,493568,637952,20480
165 | 163,958464,1029120,77824
166 | 164,865280,973824,17408
167 | 165,1029120,1048576,77824
168 | 166,993280,1048576,9216
169 | 167,37888,528384,1024
170 | 168,165888,257024,40960
171 | 169,0,1048576,1024
172 | 170,257024,1048576,11264
173 | 171,203776,538624,26624
174 | 172,0,1048576,6144
175 | 173,983040,995328,68608
176 | 174,45056,637952,5120
177 | 175,538624,631808,68608
178 | 176,176128,435200,16384
179 | 177,323584,608256,12288
180 | 178,39936,203776,19456
181 | 179,340992,808960,9216
182 | 180,45056,66560,20480
183 | 181,93184,301056,37888
184 | 182,505856,727040,26624
185 | 183,290816,502784,14336
186 | 184,79872,120832,80896
187 | 185,340992,1048576,9216
188 | 186,952320,1048576,29696
189 | 187,115712,196608,60416
190 | 188,274432,285696,83968
191 | 189,340992,1048576,10240
192 | 190,7168,88064,46080
193 | 191,435200,1011712,1024
194 | 192,869376,1048576,41984
195 | 193,502784,620544,23552
196 | 194,681984,811008,68608
197 | 195,230400,274432,83968
198 | 196,0,101376,64512
199 | 197,0,1048576,6144
200 | 198,608256,776192,1024
201 | 199,869376,1048576,13312
202 | 200,1003520,1048576,142336
203 | 201,973824,992256,211968
204 | 202,340992,1048576,6144
205 | 203,0,651264,9216
206 | 204,205824,239616,55296
207 | 205,528384,553984,74752
208 | 206,0,290816,28672
209 | 207,0,73728,55296
210 | 208,34816,708608,5120
211 | 209,844800,869376,55296
212 | 210,0,844800,1024
213 | 211,811008,839680,68608
214 | 212,0,993280,9216
215 |
--------------------------------------------------------------------------------
/benchmarks/challenging/E.1048576.csv:
--------------------------------------------------------------------------------
1 | id,lower,upper,size
2 | 0,791552,879616,11264
3 | 1,982016,1035264,18432
4 | 2,408576,441344,145408
5 | 3,964608,1022976,34816
6 | 4,777216,834560,135168
7 | 5,781312,911360,64512
8 | 6,472064,555008,60416
9 | 7,0,703488,4096
10 | 8,370688,377856,327680
11 | 9,0,33792,113664
12 | 10,284672,311296,30720
13 | 11,920576,964608,193536
14 | 12,583680,674816,90112
15 | 13,36864,61440,202752
16 | 14,488448,512000,46080
17 | 15,268288,299008,36864
18 | 16,0,146432,39936
19 | 17,96256,214016,71680
20 | 18,472064,515072,122880
21 | 19,304128,318464,194560
22 | 20,190464,304128,56320
23 | 21,911360,968704,145408
24 | 22,233472,304128,50176
25 | 23,648192,703488,112640
26 | 24,515072,540672,276480
27 | 25,545792,573440,272384
28 | 26,911360,934912,71680
29 | 27,0,65536,106496
30 | 28,982016,1035264,126976
31 | 29,124928,304128,16384
32 | 30,741376,911360,43008
33 | 31,761856,860160,57344
34 | 32,441344,476160,184320
35 | 33,108544,169984,70656
36 | 34,840704,964608,12288
37 | 35,476160,538624,54272
38 | 36,1031168,1032192,203776
39 | 37,964608,1031168,1024
40 | 38,555008,648192,60416
41 | 39,403456,452608,35840
42 | 40,648192,683008,193536
43 | 41,971776,1035264,135168
44 | 42,272384,284672,507904
45 | 43,205824,267264,142336
46 | 44,65536,233472,50176
47 | 45,813056,879616,120832
48 | 46,968704,976896,138240
49 | 47,741376,911360,7168
50 | 48,781312,911360,6144
51 | 49,559104,632832,52224
52 | 50,559104,584704,324608
53 | 51,703488,964608,15360
54 | 52,741376,911360,11264
55 | 53,0,96256,39936
56 | 54,940032,968704,179200
57 | 55,96256,120832,112640
58 | 56,191488,214016,112640
59 | 57,0,703488,10240
60 | 58,0,108544,70656
61 | 59,350208,370688,194560
62 | 60,96256,214016,40960
63 | 61,540672,674816,35840
64 | 62,476160,538624,86016
65 | 63,267264,272384,507904
66 | 64,850944,964608,35840
67 | 65,146432,267264,39936
68 | 66,96256,214016,20480
69 | 67,703488,879616,45056
70 | 68,911360,968704,24576
71 | 69,33792,96256,113664
72 | 70,67584,107520,104448
73 | 71,401408,403456,327680
74 | 72,330752,441344,32768
75 | 73,703488,860160,2048
76 | 74,214016,267264,115712
77 | 75,968704,1035264,26624
78 | 76,441344,447488,263168
79 | 77,61440,65536,337920
80 | 78,330752,441344,11264
81 | 79,731136,735232,444416
82 | 80,538624,559104,48128
83 | 81,583680,622592,161792
84 | 82,330752,441344,30720
85 | 83,311296,330752,302080
86 | 84,80896,100352,256000
87 | 85,703488,879616,43008
88 | 86,124928,259072,33792
89 | 87,703488,850944,35840
90 | 88,877568,879616,84992
91 | 89,1022976,1031168,160768
92 | 90,1032192,1035264,203776
93 | 91,559104,632832,70656
94 | 92,304128,370688,117760
95 | 93,452608,540672,51200
96 | 94,96256,214016,9216
97 | 95,430080,452608,291840
98 | 96,0,205824,37888
99 | 97,741376,911360,46080
100 | 98,800768,899072,78848
101 | 99,911360,968704,23552
102 | 100,613376,674816,93184
103 | 101,0,67584,104448
104 | 102,844800,920576,58368
105 | 103,964608,982016,248832
106 | 104,124928,259072,61440
107 | 105,735232,741376,444416
108 | 106,0,352256,14336
109 | 107,436224,540672,81920
110 | 108,934912,1046528,71680
111 | 109,472064,515072,153600
112 | 110,914432,940032,315392
113 | 111,299008,472064,36864
114 | 112,584704,632832,142336
115 | 113,542720,545792,272384
116 | 114,540672,542720,272384
117 | 115,879616,914432,95232
118 | 116,879616,914432,35840
119 | 117,100352,124928,256000
120 | 118,65536,304128,36864
121 | 119,284672,304128,239616
122 | 120,648192,683008,201728
123 | 121,741376,800768,78848
124 | 122,982016,1035264,103424
125 | 123,65536,80896,256000
126 | 124,289792,311296,334848
127 | 125,540672,566272,93184
128 | 126,573440,583680,272384
129 | 127,318464,350208,194560
130 | 128,214016,267264,139264
131 | 129,169984,267264,70656
132 | 130,879616,914432,184320
133 | 131,964608,1035264,58368
134 | 132,769024,781312,87040
135 | 133,311296,332800,145408
136 | 134,0,96256,33792
137 | 135,743424,777216,135168
138 | 136,330752,382976,126976
139 | 137,452608,472064,276480
140 | 138,0,703488,1024
141 | 139,352256,703488,14336
142 | 140,503808,538624,240640
143 | 141,899072,911360,78848
144 | 142,356352,436224,81920
145 | 143,1035264,1048576,604160
146 | 144,0,703488,1024
147 | 145,0,17408,337920
148 | 146,968704,1035264,9216
149 | 147,120832,191488,112640
150 | 148,476160,538624,66560
151 | 149,371712,408576,145408
152 | 150,741376,911360,22528
153 | 151,703488,791552,89088
154 | 152,741376,911360,22528
155 | 153,968704,1035264,63488
156 | 154,840704,844800,193536
157 | 155,476160,503808,240640
158 | 156,964608,1035264,69632
159 | 157,311296,472064,24576
160 | 158,17408,36864,202752
161 | 159,911360,940032,179200
162 | 160,844800,920576,5120
163 | 161,781312,911360,8192
164 | 162,382976,441344,126976
165 | 163,377856,401408,327680
166 | 164,968704,971776,135168
167 | 165,703488,712704,444416
168 | 166,0,268288,28672
169 | 167,743424,834560,70656
170 | 168,566272,613376,93184
171 | 169,964608,1035264,23552
172 | 170,193536,205824,104448
173 | 171,512000,703488,26624
174 | 172,311296,472064,35840
175 | 173,781312,911360,8192
176 | 174,403456,430080,291840
177 | 175,512000,703488,19456
178 | 176,304128,540672,34816
179 | 177,741376,911360,12288
180 | 178,259072,284672,239616
181 | 179,964608,1022976,125952
182 | 180,741376,852992,40960
183 | 181,964608,1031168,22528
184 | 182,703488,860160,25600
185 | 183,703488,743424,205824
186 | 184,964608,1031168,19456
187 | 185,304128,370688,15360
188 | 186,65536,304128,9216
189 | 187,0,268288,8192
190 | 188,844800,920576,32768
191 | 189,0,96256,67584
192 | 190,472064,488448,46080
193 | 191,681984,703488,304128
194 | 192,622592,674816,161792
195 | 193,65536,304128,20480
196 | 194,674816,681984,444416
197 | 195,0,152576,15360
198 | 196,538624,559104,399360
199 | 197,703488,791552,53248
200 | 198,404480,441344,100352
201 | 199,769024,911360,15360
202 | 200,304128,356352,81920
203 | 201,152576,703488,15360
204 | 202,584704,632832,53248
205 | 203,976896,1035264,138240
206 | 204,65536,190464,56320
207 | 205,791552,879616,10240
208 | 206,741376,852992,57344
209 | 207,447488,476160,263168
210 | 208,124928,131072,86016
211 | 209,852992,911360,98304
212 | 210,834560,840704,205824
213 | 211,107520,180224,104448
214 | 212,860160,877568,84992
215 | 213,844800,920576,97280
216 | 214,1035264,1046528,372736
217 |
--------------------------------------------------------------------------------
/benchmarks/challenging/F.1048576.csv:
--------------------------------------------------------------------------------
1 | id,lower,upper,size
2 | 0,323584,362496,61440
3 | 1,790528,824320,63488
4 | 2,782336,806912,88064
5 | 3,568320,614400,61440
6 | 4,607232,629760,89088
7 | 5,278528,319488,48128
8 | 6,350208,385024,90112
9 | 7,663552,695296,74752
10 | 8,653312,681984,75776
11 | 9,1024000,1048576,102400
12 | 10,440320,473088,93184
13 | 11,940032,969728,68608
14 | 12,674816,707584,62464
15 | 13,824320,852992,75776
16 | 14,967680,997376,58368
17 | 15,718848,768000,65536
18 | 16,893952,919552,72704
19 | 17,888832,928768,37888
20 | 18,815104,839680,69632
21 | 19,765952,795648,72704
22 | 20,488448,529408,38912
23 | 21,812032,839680,103424
24 | 22,662528,691200,74752
25 | 23,940032,968704,74752
26 | 24,695296,718848,74752
27 | 25,921600,959488,69632
28 | 26,799744,824320,77824
29 | 27,367616,414720,67584
30 | 28,602112,629760,72704
31 | 29,488448,523264,48128
32 | 30,533504,570368,68608
33 | 31,78848,122880,64512
34 | 32,928768,959488,88064
35 | 33,629760,674816,56320
36 | 34,217088,242688,104448
37 | 35,959488,987136,74752
38 | 36,1005568,1048576,44032
39 | 37,533504,570368,82944
40 | 38,586752,614400,87040
41 | 39,888832,921600,64512
42 | 40,857088,897024,60416
43 | 41,750592,776192,73728
44 | 42,523264,546816,71680
45 | 43,570368,614400,75776
46 | 44,533504,568320,48128
47 | 45,529408,570368,65536
48 | 46,783360,815104,69632
49 | 47,407552,429056,79872
50 | 48,707584,744448,77824
51 | 49,887808,928768,50176
52 | 50,737280,765952,67584
53 | 51,768000,790528,63488
54 | 52,214016,242688,102400
55 | 53,488448,529408,45056
56 | 54,987136,1016832,74752
57 | 55,478208,503808,89088
58 | 56,468992,494592,104448
59 | 57,674816,707584,56320
60 | 58,959488,997376,39936
61 | 59,580608,629760,63488
62 | 60,162816,191488,63488
63 | 61,408576,455680,53248
64 | 62,568320,614400,44032
65 | 63,529408,570368,39936
66 | 64,888832,928768,50176
67 | 65,917504,959488,59392
68 | 66,702464,724992,78848
69 | 67,1005568,1048576,60416
70 | 68,805888,839680,84992
71 | 69,959488,1005568,48128
72 | 70,707584,744448,64512
73 | 71,744448,783360,70656
74 | 72,408576,430080,79872
75 | 73,724992,750592,73728
76 | 74,429056,455680,79872
77 | 75,852992,897024,63488
78 | 76,315392,361472,53248
79 | 77,435200,455680,76800
80 | 78,839680,870400,70656
81 | 79,122880,157696,46080
82 | 80,430080,455680,79872
83 | 81,414720,455680,43008
84 | 82,882688,915456,59392
85 | 83,600064,629760,62464
86 | 84,602112,629760,93184
87 | 85,724992,751616,65536
88 | 86,870400,911360,38912
89 | 87,852992,875520,76800
90 | 88,570368,600064,62464
91 | 89,702464,724992,91136
92 | 90,959488,1005568,46080
93 | 91,850944,887808,62464
94 | 92,870400,911360,49152
95 | 93,707584,737280,67584
96 | 94,1016832,1048576,94208
97 | 95,911360,936960,79872
98 | 96,959488,989184,64512
99 | 97,748544,775168,79872
100 | 98,319488,361472,41984
101 | 99,638976,665600,91136
102 | 100,959488,1005568,56320
103 | 101,959488,1002496,72704
104 | 102,191488,232448,67584
105 | 103,928768,959488,107520
106 | 104,494592,533504,57344
107 | 105,718848,742400,84992
108 | 106,440320,478208,76800
109 | 107,776192,805888,84992
110 | 108,748544,775168,99328
111 | 109,989184,1016832,64512
112 | 110,665600,688128,82944
113 | 111,839680,888832,55296
114 | 112,724992,751616,102400
115 | 113,122880,165888,53248
116 | 114,997376,1048576,60416
117 | 115,409600,455680,46080
118 | 116,1006592,1048576,57344
119 | 117,514048,559104,51200
120 | 118,135168,165888,79872
121 | 119,888832,921600,45056
122 | 120,523264,548864,93184
123 | 121,839680,882688,60416
124 | 122,689152,724992,45056
125 | 123,765952,795648,60416
126 | 124,795648,839680,49152
127 | 125,242688,286720,57344
128 | 126,629760,664576,88064
129 | 127,718848,739328,75776
130 | 128,455680,496640,59392
131 | 129,897024,928768,51200
132 | 130,242688,285696,55296
133 | 131,629760,653312,75776
134 | 132,897024,928768,56320
135 | 133,536576,559104,86016
136 | 134,969728,997376,64512
137 | 135,514048,559104,48128
138 | 136,570368,594944,66560
139 | 137,744448,783360,71680
140 | 138,724992,748544,99328
141 | 139,501760,533504,63488
142 | 140,455680,491520,83968
143 | 141,959488,998400,47104
144 | 142,959488,1005568,61440
145 | 143,688128,724992,82944
146 | 144,732160,765952,65536
147 | 145,237568,278528,33792
148 | 146,388096,407552,74752
149 | 147,775168,824320,64512
150 | 148,893952,940032,57344
151 | 149,882688,916480,76800
152 | 150,323584,362496,78848
153 | 151,552960,580608,77824
154 | 152,681984,724992,70656
155 | 153,331776,367616,59392
156 | 154,629760,647168,77824
157 | 155,278528,319488,76800
158 | 156,455680,488448,83968
159 | 157,783360,808960,72704
160 | 158,386048,409600,92160
161 | 159,478208,501760,63488
162 | 160,122880,147456,110592
163 | 161,353280,385024,102400
164 | 162,629760,674816,62464
165 | 163,968704,994304,74752
166 | 164,739328,768000,75776
167 | 165,824320,858112,92160
168 | 166,147456,184320,58368
169 | 167,768000,799744,77824
170 | 168,928768,959488,97280
171 | 169,278528,315392,86016
172 | 170,795648,817152,83968
173 | 171,839680,870400,71680
174 | 172,915456,940032,59392
175 | 173,751616,782336,89088
176 | 174,775168,804864,94208
177 | 175,897024,924672,54272
178 | 176,808960,839680,72704
179 | 177,1016832,1048576,80896
180 | 178,362496,402432,46080
181 | 179,664576,707584,39936
182 | 180,570368,602112,93184
183 | 181,724992,751616,89088
184 | 182,409600,455680,49152
185 | 183,614400,638976,91136
186 | 184,911360,959488,62464
187 | 185,858112,887808,92160
188 | 186,494592,533504,47104
189 | 187,1002496,1027072,76800
190 | 188,318464,340992,69632
191 | 189,685056,718848,63488
192 | 190,394240,414720,80896
193 | 191,629760,672768,68608
194 | 192,959488,998400,47104
195 | 193,681984,702464,78848
196 | 194,691200,718848,74752
197 | 195,523264,552960,77824
198 | 196,514048,536576,86016
199 | 197,491520,523264,83968
200 | 198,776192,806912,54272
201 | 199,919552,940032,72704
202 | 200,940032,967680,58368
203 | 201,806912,839680,54272
204 | 202,638976,665600,88064
205 | 203,718848,775168,36864
206 | 204,924672,959488,54272
207 | 205,157696,191488,97280
208 | 206,655360,681984,73728
209 | 207,782336,812032,103424
210 | 208,284672,322560,32768
211 | 209,857088,897024,38912
212 | 210,604160,629760,66560
213 | 211,1005568,1048576,57344
214 | 212,629760,655360,73728
215 | 213,529408,570368,45056
216 | 214,533504,568320,57344
217 | 215,839680,882688,75776
218 | 216,232448,278528,58368
219 | 217,875520,897024,76800
220 | 218,775168,824320,57344
221 | 219,614400,638976,88064
222 | 220,672768,702464,91136
223 | 221,806912,839680,88064
224 | 222,385024,440320,54272
225 | 223,824320,852992,64512
226 | 224,614400,638976,69632
227 | 225,633856,662528,78848
228 | 226,529408,570368,67584
229 | 227,959488,980992,91136
230 | 228,887808,917504,105472
231 | 229,861184,888832,91136
232 | 230,1016832,1048576,45056
233 | 231,817152,839680,83968
234 | 232,672768,707584,68608
235 | 233,322560,350208,90112
236 | 234,1005568,1048576,50176
237 | 235,191488,232448,77824
238 | 236,122880,165888,55296
239 | 237,980992,1006592,91136
240 | 238,997376,1024000,102400
241 | 239,246784,278528,99328
242 | 240,664576,707584,48128
243 | 241,571392,595968,92160
244 | 242,385024,440320,59392
245 | 243,414720,455680,44032
246 | 244,592896,614400,75776
247 | 245,707584,732160,65536
248 | 246,571392,602112,72704
249 | 247,850944,887808,48128
250 | 248,662528,718848,50176
251 | 249,614400,662528,46080
252 | 250,998400,1021952,94208
253 | 251,315392,361472,51200
254 | 252,689152,724992,51200
255 | 253,385024,412672,86016
256 | 254,280576,322560,61440
257 | 255,237568,278528,74752
258 | 256,361472,388096,74752
259 | 257,742400,775168,84992
260 | 258,595968,629760,92160
261 | 259,700416,724992,90112
262 | 260,455680,495616,68608
263 | 261,315392,361472,55296
264 | 262,751616,782336,102400
265 | 263,278528,318464,82944
266 | 264,927744,959488,77824
267 | 265,614400,636928,68608
268 | 266,1027072,1048576,76800
269 | 267,839680,870400,68608
270 | 268,959488,997376,62464
271 | 269,455680,488448,62464
272 | 270,362496,402432,56320
273 | 271,278528,303104,75776
274 | 272,614400,633856,78848
275 | 273,488448,529408,72704
276 | 274,319488,361472,56320
277 | 275,804864,824320,94208
278 | 276,940032,969728,64512
279 | 277,665600,689152,96256
280 | 278,839680,888832,51200
281 | 279,897024,927744,77824
282 | 280,917504,959488,46080
283 | 281,799744,824320,84992
284 | 282,751616,776192,65536
285 | 283,824320,857088,99328
286 | 284,824320,850944,110592
287 | 285,559104,590848,98304
288 | 286,590848,614400,98304
289 | 287,870400,893952,68608
290 | 288,286720,323584,50176
291 | 289,208896,237568,108544
292 | 290,663552,685056,63488
293 | 291,433152,455680,72704
294 | 292,839680,861184,91136
295 | 293,88064,122880,55296
296 | 294,570368,592896,75776
297 | 295,775168,799744,84992
298 |
--------------------------------------------------------------------------------
/benchmarks/challenging/G.1048576.csv:
--------------------------------------------------------------------------------
1 | id,lower,upper,size
2 | 0,887808,921600,62464
3 | 1,694272,732160,58368
4 | 2,805888,857088,56320
5 | 3,851968,884736,60416
6 | 4,907264,937984,86016
7 | 5,269312,307200,47104
8 | 6,521216,563200,40960
9 | 7,735232,771072,74752
10 | 8,234496,270336,80896
11 | 9,563200,594944,96256
12 | 10,724992,756736,68608
13 | 11,830464,860160,83968
14 | 12,1010688,1048576,71680
15 | 13,191488,227328,39936
16 | 14,490496,545792,57344
17 | 15,490496,519168,79872
18 | 16,927744,954368,101376
19 | 17,616448,655360,55296
20 | 18,548864,580608,59392
21 | 19,811008,833536,78848
22 | 20,726016,765952,35840
23 | 21,1000448,1048576,62464
24 | 22,54272,73728,78848
25 | 23,354304,389120,56320
26 | 24,423936,464896,51200
27 | 25,270336,315392,55296
28 | 26,771072,814080,44032
29 | 27,850944,885760,54272
30 | 28,694272,714752,83968
31 | 29,637952,672768,56320
32 | 30,985088,1015808,58368
33 | 31,957440,984064,79872
34 | 32,884736,927744,65536
35 | 33,672768,701440,77824
36 | 34,737280,771072,66560
37 | 35,1015808,1048576,74752
38 | 36,124928,167936,45056
39 | 37,827392,860160,86016
40 | 38,814080,857088,50176
41 | 39,796672,828416,44032
42 | 40,438272,465920,64512
43 | 41,453632,490496,36864
44 | 42,336896,367616,87040
45 | 43,693248,732160,32768
46 | 44,584704,616448,69632
47 | 45,815104,850944,55296
48 | 46,885760,927744,64512
49 | 47,732160,771072,47104
50 | 48,553984,592896,54272
51 | 49,249856,270336,78848
52 | 50,652288,694272,57344
53 | 51,592896,628736,60416
54 | 52,561152,594944,74752
55 | 53,884736,907264,108544
56 | 54,655360,694272,47104
57 | 55,796672,820224,69632
58 | 56,984064,1015808,74752
59 | 57,872448,907264,45056
60 | 58,419840,456704,52224
61 | 59,857088,888832,81920
62 | 60,726016,763904,72704
63 | 61,657408,693248,45056
64 | 62,592896,628736,76800
65 | 63,521216,552960,51200
66 | 64,649216,672768,83968
67 | 65,951296,993280,49152
68 | 66,704512,726016,74752
69 | 67,771072,815104,56320
70 | 68,820224,846848,69632
71 | 69,521216,560128,73728
72 | 70,316416,344064,80896
73 | 71,270336,315392,64512
74 | 72,517120,542720,72704
75 | 73,231424,269312,80896
76 | 74,950272,985088,61440
77 | 75,698368,724992,75776
78 | 76,1015808,1048576,44032
79 | 77,860160,880640,68608
80 | 78,792576,816128,74752
81 | 79,888832,927744,81920
82 | 80,627712,672768,49152
83 | 81,491520,521216,77824
84 | 82,771072,816128,61440
85 | 83,850944,885760,67584
86 | 84,694272,732160,57344
87 | 85,694272,737280,65536
88 | 86,633856,672768,65536
89 | 87,359424,389120,56320
90 | 88,829440,857088,77824
91 | 89,238592,269312,66560
92 | 90,236544,269312,59392
93 | 91,518144,548864,78848
94 | 92,927744,957440,79872
95 | 93,389120,423936,86016
96 | 94,937984,962560,86016
97 | 95,411648,449536,81920
98 | 96,652288,677888,81920
99 | 97,382976,404480,76800
100 | 98,884736,927744,51200
101 | 99,434176,453632,79872
102 | 100,710656,740352,56320
103 | 101,307200,336896,76800
104 | 102,726016,765952,47104
105 | 103,657408,693248,48128
106 | 104,521216,552960,84992
107 | 105,459776,490496,63488
108 | 106,907264,962560,52224
109 | 107,769024,796672,90112
110 | 108,672768,691200,80896
111 | 109,321536,354304,65536
112 | 110,947200,980992,67584
113 | 111,459776,490496,41984
114 | 112,701440,724992,77824
115 | 113,954368,980992,101376
116 | 114,633856,672768,56320
117 | 115,927744,953344,58368
118 | 116,816128,850944,71680
119 | 117,1000448,1048576,61440
120 | 118,459776,490496,94208
121 | 119,389120,423936,64512
122 | 120,953344,984064,58368
123 | 121,796672,846848,51200
124 | 122,816128,850944,64512
125 | 123,846848,872448,94208
126 | 124,434176,460800,63488
127 | 125,197632,238592,46080
128 | 126,907264,946176,43008
129 | 127,962560,1000448,60416
130 | 128,321536,354304,67584
131 | 129,545792,580608,77824
132 | 130,78848,116736,48128
133 | 131,424960,459776,48128
134 | 132,116736,146432,88064
135 | 133,521216,563200,55296
136 | 134,759808,796672,56320
137 | 135,628736,649216,83968
138 | 136,521216,561152,67584
139 | 137,985088,1015808,67584
140 | 138,405504,434176,66560
141 | 139,592896,637952,67584
142 | 140,941056,962560,63488
143 | 141,846848,884736,65536
144 | 142,301056,321536,63488
145 | 143,955392,985088,76800
146 | 144,167936,203776,83968
147 | 145,197632,238592,55296
148 | 146,637952,672768,60416
149 | 147,771072,814080,50176
150 | 148,453632,490496,79872
151 | 149,759808,796672,30720
152 | 150,467968,490496,64512
153 | 151,269312,310272,55296
154 | 152,815104,850944,63488
155 | 153,560128,587776,64512
156 | 154,740352,769024,90112
157 | 155,980992,1014784,81920
158 | 156,353280,382976,70656
159 | 157,828416,851968,108544
160 | 158,465920,490496,64512
161 | 159,310272,335872,121856
162 | 160,680960,724992,63488
163 | 161,552960,592896,73728
164 | 162,985088,1010688,71680
165 | 163,880640,907264,68608
166 | 164,814080,857088,44032
167 | 165,326656,353280,70656
168 | 166,732160,771072,52224
169 | 167,851968,884736,48128
170 | 168,763904,796672,72704
171 | 169,432128,459776,105472
172 | 170,765952,796672,82944
173 | 171,116736,152576,64512
174 | 172,420864,449536,77824
175 | 173,921600,954368,67584
176 | 174,1015808,1048576,72704
177 | 175,116736,148480,63488
178 | 176,464896,491520,78848
179 | 177,771072,811008,78848
180 | 178,907264,946176,69632
181 | 179,135168,155648,70656
182 | 180,732160,771072,69632
183 | 181,833536,857088,78848
184 | 182,885760,921600,63488
185 | 183,490496,521216,61440
186 | 184,796672,830464,83968
187 | 185,1014784,1048576,81920
188 | 186,149504,184320,92160
189 | 187,292864,316416,86016
190 | 188,490496,516096,65536
191 | 189,184320,227328,72704
192 | 190,389120,411648,81920
193 | 191,269312,295936,74752
194 | 192,850944,887808,61440
195 | 193,724992,771072,68608
196 | 194,218112,243712,101376
197 | 195,630784,680960,58368
198 | 196,359424,389120,44032
199 | 197,580608,616448,77824
200 | 198,732160,771072,46080
201 | 199,771072,805888,71680
202 | 200,449536,486400,36864
203 | 201,54272,92160,66560
204 | 202,1019904,1048576,110592
205 | 203,907264,950272,52224
206 | 204,456704,501760,40960
207 | 205,630784,650240,64512
208 | 206,907264,950272,63488
209 | 207,650240,680960,64512
210 | 208,490496,521216,56320
211 | 209,424960,459776,46080
212 | 210,602112,630784,67584
213 | 211,693248,732160,66560
214 | 212,701440,740352,66560
215 | 213,872448,907264,49152
216 | 214,672768,710656,55296
217 | 215,691200,726016,80896
218 | 216,242688,269312,101376
219 | 217,962560,1000448,80896
220 | 218,453632,490496,53248
221 | 219,616448,652288,60416
222 | 220,724992,771072,54272
223 | 221,1000448,1025024,74752
224 | 222,887808,921600,70656
225 | 223,771072,792576,74752
226 | 224,560128,616448,53248
227 | 225,438272,467968,64512
228 | 226,561152,594944,61440
229 | 227,79872,116736,82944
230 | 228,737280,771072,82944
231 | 229,927744,947200,67584
232 | 230,553984,592896,63488
233 | 231,486400,521216,88064
234 | 232,587776,616448,64512
235 | 233,984064,1012736,63488
236 | 234,627712,672768,61440
237 | 235,521216,553984,69632
238 | 236,672768,698368,75776
239 | 237,857088,884736,44032
240 | 238,954368,985088,67584
241 | 239,26624,54272,81920
242 | 240,846848,884736,48128
243 | 241,680960,724992,59392
244 | 242,367616,401408,63488
245 | 243,606208,630784,70656
246 | 244,63488,96256,89088
247 | 245,616448,652288,78848
248 | 246,389120,424960,80896
249 | 247,359424,389120,70656
250 | 248,756736,796672,68608
251 | 249,796672,827392,86016
252 | 250,822272,846848,87040
253 | 251,796672,822272,87040
254 | 252,1015808,1048576,68608
255 | 253,616448,655360,70656
256 | 254,724992,755712,84992
257 | 255,796672,828416,64512
258 | 256,1012736,1048576,63488
259 | 257,423936,464896,40960
260 | 258,594944,633856,59392
261 | 259,594944,627712,67584
262 | 260,850944,887808,71680
263 | 261,361472,389120,54272
264 | 262,755712,796672,46080
265 | 263,382976,424960,48128
266 | 264,755712,796672,38912
267 | 265,513024,545792,90112
268 | 266,552960,592896,62464
269 | 267,714752,737280,83968
270 | 268,885760,921600,58368
271 | 269,630784,657408,93184
272 | 270,857088,885760,108544
273 | 271,203776,242688,39936
274 | 272,432128,453632,90112
275 | 273,167936,191488,88064
276 | 274,740352,759808,87040
277 | 275,419840,456704,43008
278 | 276,885760,927744,44032
279 | 277,884736,907264,113664
280 | 278,950272,985088,54272
281 | 279,604160,630784,88064
282 | 280,548864,580608,99328
283 | 281,270336,327680,54272
284 | 282,592896,637952,49152
285 | 283,710656,740352,54272
286 | 284,575488,602112,67584
287 | 285,655360,694272,78848
288 | 286,860160,907264,34816
289 | 287,860160,907264,66560
290 | 288,487424,521216,71680
291 | 289,1011712,1048576,50176
292 | 290,946176,985088,60416
293 | 291,491520,521216,78848
294 | 292,771072,815104,62464
295 | 293,857088,884736,72704
296 | 294,1015808,1048576,58368
297 | 295,490496,517120,72704
298 | 296,771072,805888,62464
299 | 297,456704,501760,57344
300 | 298,594944,627712,43008
301 | 299,805888,829440,77824
302 | 300,294912,321536,69632
303 | 301,672768,704512,74752
304 | 302,921600,951296,70656
305 | 303,907264,941056,63488
306 | 304,980992,1011712,87040
307 | 305,269312,326656,55296
308 | 306,580608,606208,70656
309 | 307,1000448,1048576,59392
310 |
--------------------------------------------------------------------------------
/benchmarks/challenging/H.1048576.csv:
--------------------------------------------------------------------------------
1 | id,lower,upper,size
2 | 0,531456,569344,61440
3 | 1,758784,782336,84992
4 | 2,322560,357376,78848
5 | 3,638976,666624,73728
6 | 4,558080,579584,68608
7 | 5,768000,814080,56320
8 | 6,430080,462848,56320
9 | 7,634880,665600,65536
10 | 8,742400,768000,75776
11 | 9,966656,1017856,52224
12 | 10,1015808,1048576,88064
13 | 11,805888,838656,47104
14 | 12,425984,447488,75776
15 | 13,288768,322560,74752
16 | 14,686080,732160,56320
17 | 15,317440,350208,46080
18 | 16,369664,395264,64512
19 | 17,973824,1011712,56320
20 | 18,814080,848896,51200
21 | 19,666624,706560,60416
22 | 20,250880,286720,58368
23 | 21,150528,180224,60416
24 | 22,999424,1022976,81920
25 | 23,254976,285696,53248
26 | 24,73728,110592,63488
27 | 25,453632,475136,81920
28 | 26,768000,807936,60416
29 | 27,821248,858112,38912
30 | 28,462848,499712,66560
31 | 29,345088,365568,77824
32 | 30,782336,802816,76800
33 | 31,150528,174080,64512
34 | 32,914432,936960,88064
35 | 33,769024,821248,51200
36 | 34,856064,889856,68608
37 | 35,399360,425984,73728
38 | 36,791552,829440,40960
39 | 37,317440,351232,39936
40 | 38,254976,288768,64512
41 | 39,716800,768000,54272
42 | 40,1005568,1048576,62464
43 | 41,729088,768000,34816
44 | 42,937984,973824,48128
45 | 43,658432,686080,86016
46 | 44,905216,925696,81920
47 | 45,669696,699392,68608
48 | 46,732160,762880,67584
49 | 47,499712,528384,88064
50 | 48,442368,474112,63488
51 | 49,606208,634880,65536
52 | 50,861184,883712,73728
53 | 51,1010688,1048576,71680
54 | 52,565248,593920,66560
55 | 53,569344,606208,58368
56 | 54,907264,937984,93184
57 | 55,592896,634880,53248
58 | 56,499712,525312,71680
59 | 57,783360,799744,73728
60 | 58,1002496,1048576,51200
61 | 59,889856,927744,67584
62 | 60,428032,450560,92160
63 | 61,450560,475136,92160
64 | 62,528384,563200,52224
65 | 63,593920,634880,43008
66 | 64,351232,391168,66560
67 | 65,841728,883712,46080
68 | 66,1022976,1048576,81920
69 | 67,206848,235520,77824
70 | 68,288768,322560,58368
71 | 69,579584,609280,61440
72 | 70,841728,883712,68608
73 | 71,779264,814080,64512
74 | 72,768000,805888,56320
75 | 73,643072,671744,48128
76 | 74,348160,376832,54272
77 | 75,655360,680960,100352
78 | 76,797696,829440,71680
79 | 77,814080,848896,69632
80 | 78,863232,889856,65536
81 | 79,254976,285696,53248
82 | 80,386048,408576,79872
83 | 81,286720,317440,62464
84 | 82,937984,973824,40960
85 | 83,926720,949248,76800
86 | 84,563200,592896,55296
87 | 85,1017856,1048576,75776
88 | 86,502784,533504,59392
89 | 87,889856,931840,63488
90 | 88,718848,742400,75776
91 | 89,1011712,1048576,64512
92 | 90,1006592,1048576,64512
93 | 91,503808,533504,80896
94 | 92,345088,386048,36864
95 | 93,657408,686080,97280
96 | 94,680960,703488,90112
97 | 95,712704,732160,87040
98 | 96,802816,821248,76800
99 | 97,799744,843776,52224
100 | 98,857088,883712,74752
101 | 99,965632,1002496,72704
102 | 100,883712,904192,68608
103 | 101,999424,1048576,45056
104 | 102,889856,931840,66560
105 | 103,533504,557056,64512
106 | 104,791552,829440,35840
107 | 105,706560,731136,117760
108 | 106,883712,925696,52224
109 | 107,1005568,1048576,60416
110 | 108,475136,503808,80896
111 | 109,965632,999424,58368
112 | 110,732160,758784,59392
113 | 111,671744,699392,53248
114 | 112,703488,732160,90112
115 | 113,858112,889856,51200
116 | 114,641024,666624,60416
117 | 115,666624,686080,90112
118 | 116,716800,768000,49152
119 | 117,712704,732160,84992
120 | 118,180224,214016,64512
121 | 119,805888,838656,49152
122 | 120,729088,768000,46080
123 | 121,531456,569344,66560
124 | 122,926720,965632,74752
125 | 123,643072,669696,68608
126 | 124,686080,732160,55296
127 | 125,451584,475136,81920
128 | 126,976896,1012736,53248
129 | 127,634880,666624,69632
130 | 128,768000,791552,76800
131 | 129,858112,889856,68608
132 | 130,643072,671744,58368
133 | 131,976896,1010688,54272
134 | 132,408576,431104,79872
135 | 133,315392,345088,58368
136 | 134,1012736,1048576,43008
137 | 135,615424,643072,68608
138 | 136,965632,1002496,50176
139 | 137,965632,999424,68608
140 | 138,759808,783360,73728
141 | 139,928768,965632,60416
142 | 140,565248,600064,51200
143 | 141,553984,579584,78848
144 | 142,603136,638976,64512
145 | 143,563200,592896,51200
146 | 144,593920,617472,67584
147 | 145,666624,706560,57344
148 | 146,768000,797696,71680
149 | 147,214016,254976,60416
150 | 148,883712,920576,57344
151 | 149,732160,769024,62464
152 | 150,261120,286720,62464
153 | 151,616448,643072,67584
154 | 152,638976,666624,64512
155 | 153,552960,579584,65536
156 | 154,475136,502784,59392
157 | 155,762880,799744,49152
158 | 156,0,51200,39936
159 | 157,536576,565248,54272
160 | 158,357376,386048,64512
161 | 159,821248,858112,41984
162 | 160,569344,603136,80896
163 | 161,848896,883712,71680
164 | 162,504832,533504,68608
165 | 163,768000,807936,54272
166 | 164,609280,638976,73728
167 | 165,686080,732160,39936
168 | 166,889856,914432,88064
169 | 167,945152,966656,64512
170 | 168,629760,651264,77824
171 | 169,925696,966656,41984
172 | 170,451584,477184,75776
173 | 171,477184,499712,72704
174 | 172,525312,565248,71680
175 | 173,376832,401408,65536
176 | 174,883712,903168,71680
177 | 175,593920,616448,67584
178 | 176,838656,862208,73728
179 | 177,686080,718848,53248
180 | 178,122880,145408,61440
181 | 179,687104,718848,60416
182 | 180,58368,77824,75776
183 | 181,557056,579584,64512
184 | 182,843776,889856,61440
185 | 183,286720,312320,64512
186 | 184,579584,611328,74752
187 | 185,499712,538624,56320
188 | 186,593920,634880,46080
189 | 187,503808,533504,67584
190 | 188,731136,768000,67584
191 | 189,729088,768000,50176
192 | 190,883712,906240,79872
193 | 191,126976,147456,81920
194 | 192,643072,683008,58368
195 | 193,807936,841728,55296
196 | 194,768000,805888,39936
197 | 195,425984,448512,82944
198 | 196,966656,1005568,69632
199 | 197,732160,769024,65536
200 | 198,718848,743424,74752
201 | 199,821248,856064,44032
202 | 200,920576,945152,64512
203 | 201,533504,552960,65536
204 | 202,617472,643072,67584
205 | 203,683008,716800,55296
206 | 204,461824,499712,71680
207 | 205,821248,858112,38912
208 | 206,782336,821248,67584
209 | 207,51200,83968,53248
210 | 208,768000,779264,64512
211 | 209,563200,593920,89088
212 | 210,395264,425984,64512
213 | 211,732160,769024,44032
214 | 212,838656,862208,89088
215 | 213,312320,329728,72704
216 | 214,474112,499712,63488
217 | 215,686080,712704,84992
218 | 216,732160,758784,84992
219 | 217,799744,841728,49152
220 | 218,533504,569344,62464
221 | 219,538624,563200,107520
222 | 220,862208,883712,89088
223 | 221,152576,172032,70656
224 | 222,699392,729088,80896
225 | 223,966656,1005568,53248
226 | 224,151552,174080,87040
227 | 225,732160,762880,44032
228 | 226,666624,687104,60416
229 | 227,145408,174080,74752
230 | 228,769024,821248,55296
231 | 229,536576,565248,52224
232 | 230,807936,841728,59392
233 | 231,430080,462848,78848
234 | 232,603136,634880,69632
235 | 233,799744,817152,81920
236 | 234,866304,889856,65536
237 | 235,391168,425984,80896
238 | 236,680960,705536,88064
239 | 237,889856,927744,69632
240 | 238,417792,442368,68608
241 | 239,235520,257024,68608
242 | 240,937984,973824,57344
243 | 241,817152,841728,81920
244 | 242,254976,286720,78848
245 | 243,976896,1012736,38912
246 | 244,841728,863232,65536
247 | 245,322560,349184,78848
248 | 246,528384,563200,35840
249 | 247,973824,1015808,45056
250 | 248,425984,451584,75776
251 | 249,230400,254976,77824
252 | 250,205824,235520,56320
253 | 251,822272,843776,67584
254 | 252,391168,444416,52224
255 | 253,993280,1017856,81920
256 | 254,821248,856064,40960
257 | 255,769024,799744,65536
258 | 256,262144,286720,80896
259 | 257,391168,417792,68608
260 | 258,731136,768000,50176
261 | 259,1010688,1048576,61440
262 | 260,705536,732160,88064
263 | 261,606208,634880,62464
264 | 262,391168,414720,55296
265 | 263,594944,629760,81920
266 | 264,928768,965632,77824
267 | 265,902144,928768,69632
268 | 266,499712,536576,63488
269 | 267,976896,1010688,78848
270 | 268,732160,759808,73728
271 | 269,533504,558080,68608
272 | 270,533504,569344,71680
273 | 271,807936,838656,66560
274 | 272,369664,399360,73728
275 | 273,931840,973824,67584
276 | 274,100352,126976,60416
277 | 275,579584,609280,72704
278 | 276,925696,966656,53248
279 | 277,592896,634880,53248
280 | 278,973824,1006592,64512
281 | 279,629760,655360,100352
282 | 280,1012736,1048576,49152
283 | 281,386048,408576,83968
284 | 282,499712,538624,51200
285 | 283,768000,807936,66560
286 | 284,883712,902144,69632
287 | 285,174080,193536,80896
288 | 286,468992,499712,54272
289 | 287,651264,680960,77824
290 | 288,931840,973824,62464
291 | 289,254976,286720,70656
292 | 290,427008,461824,61440
293 | 291,671744,699392,53248
294 | 292,475136,495616,77824
295 | 293,569344,606208,69632
296 | 294,180224,214016,50176
297 | 295,883712,905216,81920
298 | 296,936960,976896,46080
299 | 297,686080,718848,36864
300 | 298,207872,224256,71680
301 | 299,499712,531456,70656
302 | 300,949248,976896,64512
303 | 301,427008,461824,60416
304 | 302,442368,470016,73728
305 | 303,634880,657408,97280
306 | 304,1017856,1048576,58368
307 | 305,683008,716800,48128
308 | 306,461824,499712,50176
309 | 307,862208,883712,73728
310 | 308,903168,926720,71680
311 | 309,762880,799744,62464
312 | 310,799744,822272,67584
313 | 311,444416,468992,107520
314 | 312,174080,216064,63488
315 | 313,699392,729088,94208
316 | 314,729088,768000,44032
317 | 315,743424,768000,74752
318 |
--------------------------------------------------------------------------------
/benchmarks/challenging/I.1048576.csv:
--------------------------------------------------------------------------------
1 | id,lower,upper,size
2 | 0,408576,419840,435200
3 | 1,0,158720,29696
4 | 2,817152,839680,105472
5 | 3,0,1048576,1024
6 | 4,654336,819200,27648
7 | 5,177152,304128,12288
8 | 6,272384,304128,120832
9 | 7,401408,487424,52224
10 | 8,621568,1048576,10240
11 | 9,530432,667648,36864
12 | 10,177152,206848,89088
13 | 11,702464,752640,20480
14 | 12,101376,107520,111616
15 | 13,319488,354304,144384
16 | 14,487424,1048576,5120
17 | 15,9216,158720,27648
18 | 16,109568,118784,249856
19 | 17,58368,77824,182272
20 | 18,420864,428032,421888
21 | 19,177152,304128,31744
22 | 20,20480,21504,650240
23 | 21,131072,177152,26624
24 | 22,553984,681984,3072
25 | 23,487424,1048576,5120
26 | 24,158720,303104,4096
27 | 25,246784,252928,229376
28 | 26,160768,169984,157696
29 | 27,334848,487424,14336
30 | 28,872448,1048576,26624
31 | 29,334848,487424,3072
32 | 30,138240,177152,92160
33 | 31,950272,989184,12288
34 | 32,905216,954368,49152
35 | 33,900096,905216,155648
36 | 34,839680,857088,228352
37 | 35,231424,959488,6144
38 | 36,763904,817152,63488
39 | 37,941056,1000448,48128
40 | 38,99328,101376,839680
41 | 39,624640,711680,41984
42 | 40,169984,171008,157696
43 | 41,819200,840704,156672
44 | 42,178176,229376,56320
45 | 43,0,344064,7168
46 | 44,977920,1048576,67584
47 | 45,763904,817152,41984
48 | 46,553984,819200,17408
49 | 47,365568,371712,417792
50 | 48,487424,515072,58368
51 | 49,754688,791552,84992
52 | 50,451584,482304,118784
53 | 51,487424,515072,36864
54 | 52,553984,819200,18432
55 | 53,359424,365568,514048
56 | 54,487424,716800,13312
57 | 55,408576,409600,421888
58 | 56,553984,562176,75776
59 | 57,319488,335872,240640
60 | 58,445440,482304,104448
61 | 59,421888,433152,435200
62 | 60,0,231424,12288
63 | 61,840704,940032,40960
64 | 62,839680,872448,32768
65 | 63,731136,754688,73728
66 | 64,598016,633856,64512
67 | 65,487424,1048576,8192
68 | 66,857088,900096,40960
69 | 67,277504,304128,65536
70 | 68,172032,175104,146432
71 | 69,557056,609280,76800
72 | 70,774144,819200,35840
73 | 71,313344,359424,87040
74 | 72,857088,900096,94208
75 | 73,553984,819200,1024
76 | 74,316416,319488,447488
77 | 75,313344,359424,12288
78 | 76,828416,839680,66560
79 | 77,487424,852992,10240
80 | 78,839680,860160,166912
81 | 79,229376,304128,46080
82 | 80,228352,271360,107520
83 | 81,419840,421888,435200
84 | 82,304128,320512,102400
85 | 83,487424,1048576,4096
86 | 84,303104,334848,119808
87 | 85,1007616,1019904,164864
88 | 86,0,1048576,2048
89 | 87,872448,977920,11264
90 | 88,553984,819200,10240
91 | 89,271360,272384,163840
92 | 90,553984,819200,3072
93 | 91,131072,160768,157696
94 | 92,876544,1048576,15360
95 | 93,10240,12288,650240
96 | 94,0,1048576,4096
97 | 95,872448,1048576,24576
98 | 96,530432,839680,2048
99 | 97,778240,790528,260096
100 | 98,905216,927744,106496
101 | 99,487424,1048576,5120
102 | 100,989184,1048576,51200
103 | 101,872448,1048576,13312
104 | 102,839680,872448,39936
105 | 103,935936,1048576,41984
106 | 104,334848,357376,35840
107 | 105,371712,389120,140288
108 | 106,633856,654336,64512
109 | 107,487424,1048576,2048
110 | 108,872448,1048576,23552
111 | 109,177152,304128,30720
112 | 110,334848,401408,60416
113 | 111,1019904,1048576,9216
114 | 112,46080,54272,539648
115 | 113,313344,359424,50176
116 | 114,138240,177152,18432
117 | 115,711680,828416,41984
118 | 116,359424,395264,123904
119 | 117,857088,900096,80896
120 | 118,158720,239616,7168
121 | 119,693248,1048576,12288
122 | 120,989184,1048576,26624
123 | 121,927744,954368,106496
124 | 122,764928,778240,181248
125 | 123,415744,420864,421888
126 | 124,497664,502784,464896
127 | 125,962560,1007616,53248
128 | 126,448512,451584,241664
129 | 127,231424,959488,1024
130 | 128,940032,1048576,40960
131 | 129,904192,989184,37888
132 | 130,609280,624640,116736
133 | 131,304128,487424,10240
134 | 132,177152,304128,24576
135 | 133,622592,634880,97280
136 | 134,128000,172032,64512
137 | 135,530432,839680,13312
138 | 136,839680,872448,43008
139 | 137,487424,515072,55296
140 | 138,872448,941056,50176
141 | 139,128000,175104,97280
142 | 140,553984,819200,9216
143 | 141,915456,951296,77824
144 | 142,872448,1048576,2048
145 | 143,87040,88064,839680
146 | 144,297984,304128,204800
147 | 145,502784,508928,464896
148 | 146,487424,497664,464896
149 | 147,304128,319488,55296
150 | 148,448512,482304,65536
151 | 149,335872,337920,358400
152 | 150,304128,316416,370688
153 | 151,185344,241664,11264
154 | 152,745472,839680,27648
155 | 153,740352,764928,181248
156 | 154,553984,567296,108544
157 | 155,197632,241664,114688
158 | 156,442368,445440,703488
159 | 157,319488,335872,117760
160 | 158,530432,667648,30720
161 | 159,714752,740352,181248
162 | 160,158720,187392,69632
163 | 161,177152,278528,45056
164 | 162,334848,487424,1024
165 | 163,0,4096,600064
166 | 164,0,9216,53248
167 | 165,716800,1048576,5120
168 | 166,487424,989184,7168
169 | 167,239616,303104,76800
170 | 168,872448,977920,28672
171 | 169,661504,702464,105472
172 | 170,553984,654336,27648
173 | 171,41984,46080,539648
174 | 172,0,158720,8192
175 | 173,562176,681984,34816
176 | 174,445440,482304,89088
177 | 175,544768,553984,464896
178 | 176,187392,239616,69632
179 | 177,171008,177152,242688
180 | 178,344064,1048576,7168
181 | 179,487424,716800,14336
182 | 180,959488,1027072,12288
183 | 181,530432,667648,8192
184 | 182,520192,544768,33792
185 | 183,10240,21504,216064
186 | 184,177152,278528,37888
187 | 185,487424,1048576,8192
188 | 186,667648,731136,73728
189 | 187,951296,956416,77824
190 | 188,184320,246784,54272
191 | 189,553984,664576,41984
192 | 190,515072,527360,312320
193 | 191,177152,277504,40960
194 | 192,54272,58368,881664
195 | 193,667648,754688,11264
196 | 194,445440,448512,461824
197 | 195,487424,989184,7168
198 | 196,530432,661504,26624
199 | 197,716800,1048576,7168
200 | 198,872448,956416,11264
201 | 199,482304,487424,703488
202 | 200,487424,1048576,4096
203 | 201,252928,277504,73728
204 | 202,819200,839680,198656
205 | 203,9216,158720,14336
206 | 204,569344,622592,1024
207 | 205,408576,428032,14336
208 | 206,487424,1048576,5120
209 | 207,454656,487424,119808
210 | 208,112640,118784,614400
211 | 209,400384,408576,539648
212 | 210,87040,101376,41984
213 | 211,487424,621568,14336
214 | 212,654336,819200,15360
215 | 213,553984,819200,10240
216 | 214,359424,395264,43008
217 | 215,634880,664576,108544
218 | 216,530432,557056,116736
219 | 217,23552,54272,132096
220 | 218,357376,487424,35840
221 | 219,0,1048576,1024
222 | 220,840704,1048576,17408
223 | 221,334848,487424,5120
224 | 222,177152,278528,18432
225 | 223,428032,433152,436224
226 | 224,158720,303104,23552
227 | 225,941056,1048576,2048
228 | 226,569344,634880,11264
229 | 227,88064,99328,418816
230 | 228,29696,35840,563200
231 | 229,526336,544768,215040
232 | 230,118784,123904,881664
233 | 231,243712,333824,13312
234 | 232,177152,278528,47104
235 | 233,716800,788480,26624
236 | 234,128000,172032,81920
237 | 235,177152,304128,2048
238 | 236,131072,138240,212992
239 | 237,109568,118784,17408
240 | 238,977920,1048576,69632
241 | 239,553984,598016,64512
242 | 240,72704,243712,19456
243 | 241,451584,482304,64512
244 | 242,799744,1048576,11264
245 | 243,252928,277504,155648
246 | 244,1000448,1048576,48128
247 | 245,101376,107520,770048
248 | 246,448512,462848,152576
249 | 247,508928,520192,160768
250 | 248,1027072,1048576,12288
251 | 249,278528,304128,148480
252 | 250,21504,29696,563200
253 | 251,664576,704512,107520
254 | 252,557056,609280,39936
255 | 253,401408,487424,8192
256 | 254,487424,950272,5120
257 | 255,520192,544768,59392
258 | 256,10240,21504,15360
259 | 257,409600,415744,421888
260 | 258,977920,1048576,27648
261 | 259,840704,989184,13312
262 | 260,830464,839680,84992
263 | 261,530432,661504,29696
264 | 262,442368,454656,119808
265 | 263,487424,1048576,7168
266 | 264,177152,304128,2048
267 | 265,4096,10240,600064
268 | 266,304128,359424,34816
269 | 267,860160,872448,166912
270 | 268,337920,346112,358400
271 | 269,940032,1048576,26624
272 | 270,487424,1048576,3072
273 | 271,624640,828416,4096
274 | 272,131072,171008,21504
275 | 273,900096,962560,72704
276 | 274,131072,171008,63488
277 | 275,529408,807936,13312
278 | 276,58368,82944,115712
279 | 277,956416,1019904,77824
280 | 278,915456,1048576,19456
281 | 279,448512,482304,2048
282 | 280,82944,87040,881664
283 | 281,131072,177152,21504
284 | 282,107520,109568,881664
285 | 283,839680,863232,77824
286 | 284,962560,1007616,111616
287 | 285,1019904,1034240,306176
288 | 286,395264,408576,331776
289 | 287,530432,667648,9216
290 | 288,389120,395264,417792
291 | 289,354304,359424,502784
292 | 290,158720,303104,15360
293 | 291,857088,900096,12288
294 | 292,365568,395264,96256
295 | 293,433152,442368,444416
296 | 294,395264,400384,539648
297 | 295,624640,828416,20480
298 | 296,58368,76800,227328
299 | 297,128000,175104,104448
300 | 298,451584,482304,58368
301 | 299,128000,177152,29696
302 | 300,487424,1048576,2048
303 | 301,527360,530432,322560
304 | 302,621568,1048576,4096
305 | 303,12288,20480,346112
306 | 304,569344,622592,96256
307 | 305,313344,359424,10240
308 | 306,567296,569344,108544
309 | 307,359424,395264,24576
310 | 308,241664,246784,125952
311 | 309,188416,197632,114688
312 | 310,807936,915456,13312
313 | 311,508928,520192,304128
314 | 312,487424,819200,10240
315 | 313,0,158720,28672
316 | 314,681984,722944,78848
317 | 315,520192,544768,58368
318 | 316,553984,819200,17408
319 | 317,21504,23552,318464
320 | 318,840704,1048576,24576
321 | 319,654336,774144,35840
322 | 320,277504,297984,204800
323 | 321,128000,131072,503808
324 | 322,272384,304128,43008
325 | 323,433152,442368,427008
326 | 324,962560,1019904,63488
327 | 325,872448,935936,41984
328 | 326,487424,693248,12288
329 | 327,177152,304128,15360
330 | 328,304128,316416,76800
331 | 329,1034240,1048576,306176
332 | 330,320512,359424,102400
333 | 331,138240,177152,102400
334 | 332,487424,1019904,9216
335 | 333,175104,177152,348160
336 | 334,229376,304128,43008
337 | 335,333824,529408,13312
338 | 336,487424,852992,5120
339 | 337,58368,72704,356352
340 | 338,926720,977920,54272
341 | 339,624640,745472,27648
342 | 340,229376,271360,56320
343 | 341,231424,959488,5120
344 | 342,553984,819200,15360
345 | 343,520192,526336,290816
346 | 344,442368,487424,48128
347 | 345,664576,704512,73728
348 | 346,177152,304128,26624
349 | 347,206848,229376,89088
350 | 348,840704,904192,37888
351 | 349,371712,389120,277504
352 | 350,487424,527360,10240
353 | 351,445440,482304,48128
354 | 352,790528,804864,260096
355 | 353,0,10240,281600
356 | 354,654336,819200,21504
357 | 355,304128,359424,26624
358 | 356,520192,544768,22528
359 | 357,487424,819200,12288
360 | 358,526336,544768,75776
361 | 359,487424,716800,11264
362 | 360,123904,128000,881664
363 | 361,562176,681984,40960
364 | 362,752640,763904,105472
365 | 363,184320,246784,49152
366 | 364,872448,926720,54272
367 | 365,487424,1048576,4096
368 | 366,177152,211968,107520
369 | 367,304128,359424,45056
370 | 368,839680,872448,38912
371 | 369,177152,304128,15360
372 | 370,624640,839680,22528
373 | 371,109568,112640,614400
374 | 372,819200,839680,107520
375 | 373,704512,714752,181248
376 |
--------------------------------------------------------------------------------
/benchmarks/challenging/J.1048576.csv:
--------------------------------------------------------------------------------
1 | id,lower,upper,size
2 | 0,105472,267264,25600
3 | 1,373760,543744,18432
4 | 2,869376,885760,56320
5 | 3,111616,124928,8192
6 | 4,0,907264,1024
7 | 5,354304,367616,71680
8 | 6,928768,958464,32768
9 | 7,1008640,1017856,191488
10 | 8,950272,969728,153600
11 | 9,398336,606208,16384
12 | 10,612352,694272,44032
13 | 11,225280,606208,7168
14 | 12,0,907264,2048
15 | 13,111616,269312,25600
16 | 14,123904,250880,19456
17 | 15,126976,248832,24576
18 | 16,261120,408576,14336
19 | 17,678912,694272,92160
20 | 18,351232,496640,18432
21 | 19,664576,824320,21504
22 | 20,543744,1048576,6144
23 | 21,438272,543744,37888
24 | 22,867328,1010688,8192
25 | 23,799744,886784,41984
26 | 24,50176,587776,4096
27 | 25,236544,509952,7168
28 | 26,0,296960,8192
29 | 27,655360,751616,39936
30 | 28,147456,376832,11264
31 | 29,284672,367616,17408
32 | 30,587776,866304,11264
33 | 31,0,105472,9216
34 | 32,267264,690176,4096
35 | 33,438272,543744,12288
36 | 34,1017856,1024000,171008
37 | 35,907264,934912,48128
38 | 36,23552,111616,47104
39 | 37,636928,786432,21504
40 | 38,886784,990208,37888
41 | 39,778240,796672,48128
42 | 40,178176,373760,16384
43 | 41,50176,547840,5120
44 | 42,620544,691200,24576
45 | 43,587776,843776,14336
46 | 44,178176,869376,2048
47 | 45,852992,869376,40960
48 | 46,0,15360,142336
49 | 47,225280,606208,1024
50 | 48,343040,547840,15360
51 | 49,866304,985088,23552
52 | 50,588800,620544,24576
53 | 51,786432,860160,55296
54 | 52,728064,786432,31744
55 | 53,799744,990208,1024
56 | 54,674816,729088,27648
57 | 55,160768,230400,28672
58 | 56,986112,1002496,153600
59 | 57,236544,351232,18432
60 | 58,126976,591872,5120
61 | 59,799744,974848,14336
62 | 60,50176,136192,17408
63 | 61,898048,1048576,27648
64 | 62,15360,543744,1024
65 | 63,15360,138240,18432
66 | 64,408576,907264,6144
67 | 65,230400,516096,10240
68 | 66,267264,690176,6144
69 | 67,107520,563200,6144
70 | 68,52224,138240,2048
71 | 69,0,543744,6144
72 | 70,636928,786432,2048
73 | 71,126976,990208,1024
74 | 72,241664,344064,36864
75 | 73,263168,301056,45056
76 | 74,586752,636928,55296
77 | 75,886784,990208,16384
78 | 76,575488,684032,14336
79 | 77,0,543744,3072
80 | 78,730112,847872,20480
81 | 79,664576,824320,5120
82 | 80,343040,587776,6144
83 | 81,343040,606208,4096
84 | 82,438272,543744,8192
85 | 83,100352,111616,116736
86 | 84,334848,543744,10240
87 | 85,958464,990208,45056
88 | 86,1017856,1048576,20480
89 | 87,111616,418816,7168
90 | 88,322560,343040,18432
91 | 89,296960,924672,4096
92 | 90,486400,588800,24576
93 | 91,707584,728064,73728
94 | 92,418816,514048,21504
95 | 93,346112,418816,35840
96 | 94,111616,346112,10240
97 | 95,336896,702464,11264
98 | 96,111616,203776,18432
99 | 97,230400,275456,9216
100 | 98,178176,373760,7168
101 | 99,513024,694272,8192
102 | 100,691200,694272,24576
103 | 101,15360,126976,27648
104 | 102,0,543744,5120
105 | 103,869376,941056,37888
106 | 104,103424,140288,37888
107 | 105,0,934912,3072
108 | 106,0,168960,16384
109 | 107,664576,824320,14336
110 | 108,236544,509952,2048
111 | 109,799744,990208,5120
112 | 110,729088,753664,50176
113 | 111,144384,305152,15360
114 | 112,799744,928768,28672
115 | 113,547840,587776,34816
116 | 114,284672,354304,16384
117 | 115,504832,598016,13312
118 | 116,799744,958464,12288
119 | 117,0,105472,38912
120 | 118,0,575488,4096
121 | 119,607232,869376,15360
122 | 120,18432,33792,163840
123 | 121,799744,886784,29696
124 | 122,178176,655360,5120
125 | 123,376832,587776,11264
126 | 124,0,248832,1024
127 | 125,809984,1024000,14336
128 | 126,318464,543744,14336
129 | 127,793600,852992,40960
130 | 128,0,575488,2048
131 | 129,111616,418816,2048
132 | 130,241664,344064,12288
133 | 131,525312,990208,6144
134 | 132,543744,1048576,8192
135 | 133,0,751616,5120
136 | 134,301056,373760,45056
137 | 135,230400,236544,82944
138 | 136,0,168960,10240
139 | 137,1010688,1048576,73728
140 | 138,992256,1038336,47104
141 | 139,23552,100352,53248
142 | 140,753664,782336,141312
143 | 141,587776,674816,27648
144 | 142,992256,1038336,7168
145 | 143,728064,867328,27648
146 | 144,659456,729088,24576
147 | 145,985088,1039360,72704
148 | 146,867328,1010688,11264
149 | 147,0,543744,2048
150 | 148,309248,456704,24576
151 | 149,0,934912,2048
152 | 150,15360,138240,18432
153 | 151,980992,986112,153600
154 | 152,126976,990208,2048
155 | 153,0,18432,178176
156 | 154,79872,103424,37888
157 | 155,587776,1024000,2048
158 | 156,250880,457728,19456
159 | 157,336896,702464,6144
160 | 158,643072,664576,40960
161 | 159,126976,525312,6144
162 | 160,0,934912,2048
163 | 161,986112,990208,11264
164 | 162,126976,990208,4096
165 | 163,373760,543744,6144
166 | 164,937984,1048576,24576
167 | 165,671744,678912,92160
168 | 166,435200,437248,54272
169 | 167,55296,178176,24576
170 | 168,0,18432,19456
171 | 169,373760,486400,24576
172 | 170,336896,702464,3072
173 | 171,867328,1010688,21504
174 | 172,790528,799744,333824
175 | 173,55296,178176,16384
176 | 174,193536,230400,55296
177 | 175,883712,937984,24576
178 | 176,886784,990208,12288
179 | 177,1024,23552,171008
180 | 178,0,924672,3072
181 | 179,1047552,1048576,171008
182 | 180,0,504832,7168
183 | 181,870400,934912,63488
184 | 182,607232,869376,4096
185 | 183,269312,346112,25600
186 | 184,886784,990208,1024
187 | 185,914432,990208,38912
188 | 186,0,543744,3072
189 | 187,29696,52224,162816
190 | 188,685056,907264,16384
191 | 189,293888,526336,17408
192 | 190,50176,569344,5120
193 | 191,50176,587776,6144
194 | 192,509952,612352,4096
195 | 193,849920,907264,13312
196 | 194,107520,686080,6144
197 | 195,0,907264,3072
198 | 196,269312,660480,10240
199 | 197,236544,526336,4096
200 | 198,676864,874496,19456
201 | 199,0,575488,3072
202 | 200,236544,509952,1024
203 | 201,55296,178176,11264
204 | 202,753664,782336,27648
205 | 203,15360,126976,14336
206 | 204,0,934912,2048
207 | 205,126976,990208,1024
208 | 206,799744,886784,26624
209 | 207,0,168960,5120
210 | 208,0,334848,10240
211 | 209,0,199680,11264
212 | 210,649216,694272,61440
213 | 211,15360,126976,31744
214 | 212,429056,655360,14336
215 | 213,799744,990208,17408
216 | 214,248832,263168,143360
217 | 215,418816,514048,43008
218 | 216,580608,643072,50176
219 | 217,178176,224256,23552
220 | 218,869376,945152,16384
221 | 219,974848,990208,31744
222 | 220,796672,990208,21504
223 | 221,0,1024,171008
224 | 222,1009664,1048576,43008
225 | 223,0,168960,20480
226 | 224,543744,580608,63488
227 | 225,50176,547840,6144
228 | 226,576512,694272,20480
229 | 227,729088,747520,111616
230 | 228,373760,515072,17408
231 | 229,588800,712704,24576
232 | 230,643072,870400,9216
233 | 231,0,478208,8192
234 | 232,50176,547840,1024
235 | 233,294912,990208,4096
236 | 234,796672,990208,15360
237 | 235,111616,203776,31744
238 | 236,655360,793600,1024
239 | 237,0,378880,5120
240 | 238,267264,336896,20480
241 | 239,0,751616,4096
242 | 240,343040,398336,25600
243 | 241,803840,869376,24576
244 | 242,729088,898048,15360
245 | 243,0,107520,22528
246 | 244,660480,685056,14336
247 | 245,305152,418816,29696
248 | 246,992256,1038336,84992
249 | 247,50176,547840,3072
250 | 248,587776,676864,19456
251 | 249,874496,1048576,19456
252 | 250,0,126976,20480
253 | 251,702464,778240,48128
254 | 252,782336,790528,310272
255 | 253,607232,869376,2048
256 | 254,0,990208,1024
257 | 255,457728,515072,19456
258 | 256,945152,985088,72704
259 | 257,587776,866304,12288
260 | 258,230400,516096,6144
261 | 259,202752,587776,3072
262 | 260,563200,990208,6144
263 | 261,400384,435200,54272
264 | 262,136192,547840,2048
265 | 263,613376,707584,33792
266 | 264,126976,248832,32768
267 | 265,748544,934912,13312
268 | 266,908288,990208,14336
269 | 267,340992,702464,11264
270 | 268,138240,143360,142336
271 | 269,753664,782336,133120
272 | 270,50176,587776,2048
273 | 271,824320,870400,40960
274 | 272,344064,400384,54272
275 | 273,144384,305152,14336
276 | 274,437248,694272,5120
277 | 275,335872,606208,11264
278 | 276,691200,730112,43008
279 | 277,607232,869376,1024
280 | 278,52224,114688,29696
281 | 279,0,168960,6144
282 | 280,52224,114688,47104
283 | 281,105472,267264,22528
284 | 282,799744,836608,27648
285 | 283,1031168,1048576,153600
286 | 284,509952,612352,39936
287 | 285,587776,613376,58368
288 | 286,969728,980992,153600
289 | 287,636928,728064,31744
290 | 288,111616,144384,29696
291 | 289,0,543744,7168
292 | 290,598016,748544,13312
293 | 291,1024000,1048576,16384
294 | 292,799744,990208,16384
295 | 293,398336,606208,3072
296 | 294,592896,607232,22528
297 | 295,178176,492544,9216
298 | 296,870400,934912,19456
299 | 297,111616,694272,4096
300 | 298,124928,513024,8192
301 | 299,886784,990208,30720
302 | 300,1044480,1047552,171008
303 | 301,293888,526336,17408
304 | 302,569344,587776,43008
305 | 303,640000,691200,43008
306 | 304,378880,990208,5120
307 | 305,464896,476160,37888
308 | 306,126976,248832,14336
309 | 307,694272,790528,23552
310 | 308,799744,928768,4096
311 | 309,202752,587776,9216
312 | 310,50176,202752,12288
313 | 311,168960,178176,58368
314 | 312,275456,694272,9216
315 | 313,126976,248832,2048
316 | 314,236544,432128,15360
317 | 315,111616,225280,16384
318 | 316,140288,237568,37888
319 | 317,107520,990208,3072
320 | 318,237568,464896,3072
321 | 319,126976,248832,4096
322 | 320,728064,867328,24576
323 | 321,15360,288768,14336
324 | 322,373760,438272,58368
325 | 323,990208,1008640,191488
326 | 324,580608,643072,13312
327 | 325,799744,886784,32768
328 | 326,562176,627712,61440
329 | 327,941056,1039360,37888
330 | 328,0,751616,2048
331 | 329,437248,694272,4096
332 | 330,288768,318464,14336
333 | 331,686080,990208,6144
334 | 332,1011712,1038336,132096
335 | 333,111616,418816,12288
336 | 334,515072,580608,19456
337 | 335,418816,514048,24576
338 | 336,770048,870400,32768
339 | 337,178176,373760,20480
340 | 338,747520,753664,251904
341 | 339,799744,990208,7168
342 | 340,580608,643072,19456
343 | 341,799744,990208,12288
344 | 342,50176,587776,7168
345 | 343,587776,707584,15360
346 | 344,18432,123904,19456
347 | 345,338944,408576,12288
348 | 346,0,269312,14336
349 | 347,146432,309248,24576
350 | 348,718848,729088,310272
351 | 349,992256,1011712,132096
352 | 350,199680,543744,11264
353 | 351,1039360,1048576,110592
354 | 352,799744,914432,23552
355 | 353,267264,690176,6144
356 | 354,178176,655360,5120
357 | 355,362496,429056,23552
358 | 356,225280,335872,11264
359 | 357,515072,543744,36864
360 | 358,526336,694272,5120
361 | 359,606208,649216,61440
362 | 360,236544,293888,34816
363 | 361,684032,908288,14336
364 | 362,836608,990208,16384
365 | 363,0,685056,2048
366 | 364,225280,606208,4096
367 | 365,543744,659456,24576
368 | 366,33792,50176,163840
369 | 367,429056,655360,9216
370 | 368,521216,592896,22528
371 | 369,796672,990208,11264
372 | 370,885760,945152,56320
373 | 371,18432,261120,14336
374 | 372,437248,576512,20480
375 | 373,263168,373760,9216
376 | 374,985088,1022976,26624
377 | 375,543744,1048576,2048
378 | 376,225280,606208,4096
379 | 377,552960,694272,16384
380 | 378,427008,464896,19456
381 | 379,0,36864,52224
382 | 380,799744,974848,17408
383 | 381,616448,694272,33792
384 | 382,694272,718848,59392
385 | 383,52224,230400,20480
386 | 384,751616,849920,13312
387 | 385,50176,147456,11264
388 | 386,492544,869376,9216
389 | 387,729088,747520,140288
390 | 388,126976,990208,1024
391 | 389,694272,703488,250880
392 | 390,0,751616,2048
393 | 391,1002496,1016832,153600
394 | 392,990208,992256,271360
395 | 393,143360,193536,55296
396 | 394,916480,1009664,43008
397 | 395,591872,990208,5120
398 | 396,496640,509952,18432
399 | 397,627712,671744,92160
400 | 398,373760,543744,11264
401 | 399,843776,1048576,14336
402 | 400,924672,986112,11264
403 | 401,514048,627712,30720
404 | 402,61440,100352,57344
405 | 403,143360,160768,73728
406 | 404,50176,79872,37888
407 | 405,50176,322560,9216
408 | 406,728064,867328,21504
409 | 407,50176,322560,9216
410 | 408,575488,990208,3072
411 |
--------------------------------------------------------------------------------
/benchmarks/challenging/K.1048576.csv:
--------------------------------------------------------------------------------
1 | id,lower,upper,size
2 | 0,277504,279552,528384
3 | 1,503808,521216,138240
4 | 2,625664,658432,36864
5 | 3,288768,446464,10240
6 | 4,625664,690176,64512
7 | 5,476160,503808,36864
8 | 6,503808,563200,44032
9 | 7,703488,711680,141312
10 | 8,248832,249856,83968
11 | 9,575488,581632,336896
12 | 10,110592,117760,142336
13 | 11,35840,83968,46080
14 | 12,503808,507904,94208
15 | 13,86016,173056,44032
16 | 14,952320,1021952,41984
17 | 15,277504,288768,329728
18 | 16,305152,420864,34816
19 | 17,503808,510976,364544
20 | 18,86016,173056,31744
21 | 19,543744,569344,108544
22 | 20,459776,465920,486400
23 | 21,1047552,1048576,234496
24 | 22,854016,869376,112640
25 | 23,351232,398336,37888
26 | 24,189440,202752,58368
27 | 25,433152,540672,27648
28 | 26,625664,690176,23552
29 | 27,0,10240,15360
30 | 28,210944,275456,16384
31 | 29,355328,363520,76800
32 | 30,485376,503808,149504
33 | 31,561152,573440,153600
34 | 32,284672,433152,12288
35 | 33,780288,854016,35840
36 | 34,238592,246784,261120
37 | 35,503808,581632,16384
38 | 36,929792,1024000,25600
39 | 37,931840,945152,311296
40 | 38,476160,485376,188416
41 | 39,696320,701440,858112
42 | 40,500736,534528,55296
43 | 41,1002496,1007616,45056
44 | 42,309248,403456,40960
45 | 43,603136,678912,12288
46 | 44,992256,1013760,9216
47 | 45,233472,238592,812032
48 | 46,108544,134144,74752
49 | 47,780288,854016,4096
50 | 48,262144,269312,605184
51 | 49,882688,915456,71680
52 | 50,288768,337920,72704
53 | 51,20480,86016,59392
54 | 52,1030144,1048576,171008
55 | 53,284672,678912,1024
56 | 54,1032192,1048576,112640
57 | 55,0,45056,83968
58 | 56,621568,690176,5120
59 | 57,288768,347136,3072
60 | 58,812032,854016,27648
61 | 59,32768,506880,9216
62 | 60,284672,322560,48128
63 | 61,202752,204800,857088
64 | 62,971776,1024000,59392
65 | 63,20480,24576,200704
66 | 64,812032,832512,118784
67 | 65,476160,485376,422912
68 | 66,0,3072,842752
69 | 67,290816,373760,48128
70 | 68,884736,911360,124928
71 | 69,809984,854016,97280
72 | 70,711680,726016,11264
73 | 71,102400,124928,56320
74 | 72,0,153600,22528
75 | 73,994304,1048576,44032
76 | 74,952320,1021952,21504
77 | 75,173056,202752,70656
78 | 76,86016,110592,142336
79 | 77,384000,407552,66560
80 | 78,854016,884736,124928
81 | 79,246784,269312,173056
82 | 80,832512,854016,118784
83 | 81,39936,58368,161792
84 | 82,992256,1001472,396288
85 | 83,347136,398336,82944
86 | 84,989184,1038336,38912
87 | 85,726016,731136,650240
88 | 86,123904,143360,4096
89 | 87,222208,228352,81920
90 | 88,189440,229376,56320
91 | 89,731136,744448,217088
92 | 90,108544,169984,28672
93 | 91,780288,825344,66560
94 | 92,121856,148480,159744
95 | 93,446464,459776,69632
96 | 94,503808,575488,11264
97 | 95,121856,143360,48128
98 | 96,1001472,1004544,396288
99 | 97,863232,875520,88064
100 | 98,754688,763904,331776
101 | 99,953344,967680,161792
102 | 100,854016,880640,90112
103 | 101,103424,121856,101376
104 | 102,476160,503808,3072
105 | 103,276480,277504,858112
106 | 104,953344,992256,100352
107 | 105,271360,275456,858112
108 | 106,780288,796672,165888
109 | 107,476160,503808,133120
110 | 108,288768,295936,129024
111 | 109,305152,443392,3072
112 | 110,1014784,1030144,171008
113 | 111,605184,892928,6144
114 | 112,357376,384000,66560
115 | 113,246784,247808,605184
116 | 114,570368,573440,106496
117 | 115,88064,113664,171008
118 | 116,854016,882688,123904
119 | 117,503808,581632,33792
120 | 118,75776,248832,10240
121 | 119,523264,563200,94208
122 | 120,20480,39936,161792
123 | 121,228352,233472,812032
124 | 122,690176,691200,858112
125 | 123,188416,189440,787456
126 | 124,288768,378880,13312
127 | 125,856064,880640,54272
128 | 126,485376,503808,32768
129 | 127,780288,854016,4096
130 | 128,476160,503808,10240
131 | 129,588800,608256,218112
132 | 130,678912,757760,3072
133 | 131,915456,952320,71680
134 | 132,563200,575488,184320
135 | 133,279552,286720,528384
136 | 134,592896,619520,55296
137 | 135,540672,543744,108544
138 | 136,257024,262144,452608
139 | 137,625664,690176,15360
140 | 138,869376,929792,53248
141 | 139,15360,20480,858112
142 | 140,757760,777216,146432
143 | 141,238592,246784,539648
144 | 142,121856,166912,23552
145 | 143,450560,458752,214016
146 | 144,1024000,1032192,112640
147 | 145,605184,892928,11264
148 | 146,606208,621568,210944
149 | 147,103424,121856,183296
150 | 148,378880,381952,117760
151 | 149,825344,854016,66560
152 | 150,780288,854016,2048
153 | 151,891904,914432,57344
154 | 152,780288,793600,72704
155 | 153,967680,992256,161792
156 | 154,941056,1007616,47104
157 | 155,117760,121856,142336
158 | 156,625664,690176,56320
159 | 157,658432,673792,212992
160 | 158,86016,88064,171008
161 | 159,75776,248832,5120
162 | 160,510976,516096,364544
163 | 161,521216,575488,64512
164 | 162,1038336,1048576,95232
165 | 163,529408,561152,32768
166 | 164,229376,248832,56320
167 | 165,920576,989184,59392
168 | 166,269312,271360,858112
169 | 167,173056,188416,5120
170 | 168,636928,647168,207872
171 | 169,625664,668672,62464
172 | 170,190464,202752,348160
173 | 171,305152,309248,76800
174 | 172,746496,763904,12288
175 | 173,75776,248832,12288
176 | 174,458752,459776,416768
177 | 175,173056,177152,492544
178 | 176,887808,1048576,23552
179 | 177,458752,476160,214016
180 | 178,503808,563200,55296
181 | 179,378880,446464,10240
182 | 180,322560,405504,48128
183 | 181,588800,606208,210944
184 | 182,989184,1038336,56320
185 | 183,780288,854016,60416
186 | 184,211968,212992,858112
187 | 185,647168,658432,176128
188 | 186,702464,703488,858112
189 | 187,652288,690176,114688
190 | 188,32768,443392,7168
191 | 189,150528,166912,205824
192 | 190,1013760,1014784,171008
193 | 191,746496,753664,302080
194 | 192,503808,575488,3072
195 | 193,780288,854016,51200
196 | 194,20480,86016,58368
197 | 195,71680,86016,215040
198 | 196,0,249856,4096
199 | 197,703488,744448,105472
200 | 198,373760,405504,48128
201 | 199,32768,210944,16384
202 | 200,305152,404480,36864
203 | 201,407552,417792,160768
204 | 202,86016,169984,25600
205 | 203,347136,398336,34816
206 | 204,108544,169984,9216
207 | 205,288768,446464,23552
208 | 206,20480,30720,373760
209 | 207,75776,102400,56320
210 | 208,417792,443392,160768
211 | 209,647168,690176,93184
212 | 210,424960,443392,194560
213 | 211,398336,407552,226304
214 | 212,334848,343040,159744
215 | 213,592896,678912,22528
216 | 214,288768,337920,30720
217 | 215,731136,757760,100352
218 | 216,766976,774144,449536
219 | 217,169984,173056,138240
220 | 218,443392,446464,551936
221 | 219,123904,134144,307200
222 | 220,30720,35840,110592
223 | 221,780288,854016,9216
224 | 222,443392,506880,18432
225 | 223,605184,892928,6144
226 | 224,648192,666624,105472
227 | 225,347136,378880,106496
228 | 226,595968,621568,159744
229 | 227,153600,249856,36864
230 | 228,588800,621568,79872
231 | 229,625664,684032,18432
232 | 230,673792,684032,212992
233 | 231,666624,690176,138240
234 | 232,945152,953344,311296
235 | 233,605184,892928,12288
236 | 234,347136,351232,108544
237 | 235,711680,720896,367616
238 | 236,404480,443392,81920
239 | 237,148480,166912,159744
240 | 238,619520,678912,55296
241 | 239,684032,690176,231424
242 | 240,189440,190464,528384
243 | 241,880640,891904,231424
244 | 242,247808,257024,452608
245 | 243,446464,476160,48128
246 | 244,86016,113664,24576
247 | 245,892928,949248,36864
248 | 246,457728,569344,24576
249 | 247,266240,284672,146432
250 | 248,1013760,1031168,234496
251 | 249,503808,529408,12288
252 | 250,592896,678912,4096
253 | 251,212992,218112,858112
254 | 252,569344,580608,41984
255 | 253,621568,625664,506880
256 | 254,309248,443392,6144
257 | 255,113664,249856,21504
258 | 256,330752,429056,15360
259 | 257,288768,378880,23552
260 | 258,43008,73728,56320
261 | 259,534528,540672,80896
262 | 260,284672,457728,24576
263 | 261,569344,592896,91136
264 | 262,780288,854016,29696
265 | 263,124928,189440,56320
266 | 264,588800,621568,65536
267 | 265,351232,398336,70656
268 | 266,101376,103424,306176
269 | 267,911360,989184,17408
270 | 268,448512,458752,416768
271 | 269,854016,887808,23552
272 | 270,363520,429056,39936
273 | 271,765952,766976,858112
274 | 272,0,32768,44032
275 | 273,854016,1048576,12288
276 | 274,182272,188416,492544
277 | 275,189440,202752,196608
278 | 276,592896,678912,9216
279 | 277,875520,882688,88064
280 | 278,678912,699392,143360
281 | 279,407552,424960,194560
282 | 280,731136,744448,302080
283 | 281,43008,73728,144384
284 | 282,953344,992256,49152
285 | 283,573440,581632,376832
286 | 284,121856,150528,101376
287 | 285,225280,228352,730112
288 | 286,0,113664,21504
289 | 287,854016,1002496,9216
290 | 288,703488,711680,508928
291 | 289,763904,765952,858112
292 | 290,856064,880640,139264
293 | 291,420864,443392,34816
294 | 292,863232,947200,6144
295 | 293,711680,726016,271360
296 | 294,218112,238592,46080
297 | 295,720896,726016,367616
298 | 296,86016,87040,306176
299 | 297,222208,225280,730112
300 | 298,915456,994304,44032
301 | 299,446464,473088,60416
302 | 300,854016,1048576,11264
303 | 301,433152,500736,55296
304 | 302,854016,1007616,18432
305 | 303,563200,581632,94208
306 | 304,746496,763904,207872
307 | 305,882688,922624,88064
308 | 306,780288,854016,37888
309 | 307,780288,854016,23552
310 | 308,58368,86016,40960
311 | 309,854016,915456,44032
312 | 310,1021952,1048576,123904
313 | 311,766976,773120,408576
314 | 312,507904,523264,94208
315 | 313,529408,561152,120832
316 | 314,780288,854016,24576
317 | 315,284672,290816,48128
318 | 316,378880,446464,15360
319 | 317,30720,37888,263168
320 | 318,780288,809984,97280
321 | 319,516096,529408,55296
322 | 320,37888,49152,263168
323 | 321,295936,302080,551936
324 | 322,854016,863232,94208
325 | 323,625664,647168,176128
326 | 324,605184,892928,1024
327 | 325,854016,880640,27648
328 | 326,835584,854016,165888
329 | 327,911360,920576,59392
330 | 328,503808,563200,28672
331 | 329,529408,558080,116736
332 | 330,32768,438272,10240
333 | 331,473088,476160,546816
334 | 332,796672,809984,165888
335 | 333,529408,570368,106496
336 | 334,1007616,1048576,60416
337 | 335,1004544,1013760,396288
338 | 336,485376,503808,63488
339 | 337,202752,208896,1024
340 | 338,218112,222208,812032
341 | 339,166912,173056,644096
342 | 340,288768,295936,551936
343 | 341,695296,696320,858112
344 | 342,780288,854016,10240
345 | 343,691200,695296,858112
346 | 344,24576,43008,200704
347 | 345,773120,780288,408576
348 | 346,989184,1048576,29696
349 | 347,668672,690176,115712
350 | 348,381952,446464,55296
351 | 349,809984,815104,165888
352 | 350,446464,476160,15360
353 | 351,113664,121856,195584
354 | 352,854016,941056,47104
355 | 353,911360,989184,48128
356 | 354,1031168,1047552,234496
357 | 355,58368,86016,161792
358 | 356,780288,854016,55296
359 | 357,625664,668672,53248
360 | 358,506880,605184,44032
361 | 359,780288,854016,48128
362 | 360,305152,404480,45056
363 | 361,249856,266240,146432
364 | 362,891904,914432,174080
365 | 363,588800,595968,159744
366 | 364,363520,429056,36864
367 | 365,780288,854016,59392
368 | 366,516096,529408,309248
369 | 367,405504,433152,96256
370 | 368,305152,334848,118784
371 | 369,935936,947200,88064
372 | 370,869376,934912,59392
373 | 371,65536,75776,83968
374 | 372,173056,188416,8192
375 | 373,476160,503808,63488
376 | 374,914432,921600,231424
377 | 375,465920,473088,486400
378 | 376,86016,108544,112640
379 | 377,450560,476160,33792
380 | 378,922624,935936,88064
381 | 379,485376,503808,195584
382 | 380,854016,1002496,18432
383 | 381,134144,143360,307200
384 | 382,355328,429056,17408
385 | 383,336896,355328,94208
386 | 384,647168,652288,114688
387 | 385,621568,666624,32768
388 | 386,854016,856064,193536
389 | 387,429056,446464,129024
390 | 388,6144,10240,842752
391 | 389,190464,202752,180224
392 | 390,247808,262144,152576
393 | 391,246784,269312,79872
394 | 392,337920,347136,103424
395 | 393,621568,648192,105472
396 | 394,10240,15360,858112
397 | 395,815104,818176,165888
398 | 396,746496,754688,331776
399 | 397,1007616,1048576,86016
400 | 398,87040,101376,306176
401 | 399,927744,931840,311296
402 | 400,438272,443392,11264
403 | 401,143360,150528,359424
404 | 402,744448,746496,858112
405 | 403,854016,1002496,17408
406 | 404,275456,276480,858112
407 | 405,854016,1007616,27648
408 | 406,275456,506880,16384
409 | 407,58368,71680,215040
410 | 408,746496,763904,4096
411 | 409,621568,636928,207872
412 | 410,699392,731136,100352
413 | 411,701440,702464,858112
414 | 412,433152,534528,25600
415 | 413,305152,334848,40960
416 | 414,952320,1021952,60416
417 | 415,177152,182272,492544
418 | 416,605184,1048576,7168
419 | 417,83968,86016,110592
420 | 418,929792,1024000,27648
421 | 419,103424,121856,21504
422 | 420,20480,86016,4096
423 | 421,699392,757760,43008
424 | 422,305152,357376,66560
425 | 423,208896,211968,858112
426 | 424,588800,621568,123904
427 | 425,304128,330752,129024
428 | 426,381952,446464,62464
429 | 427,580608,678912,41984
430 | 428,731136,744448,131072
431 | 429,854016,1007616,8192
432 | 430,949248,1048576,36864
433 | 431,485376,503808,116736
434 | 432,521216,575488,73728
435 | 433,284672,603136,12288
436 | 434,3072,6144,842752
437 | 435,608256,621568,218112
438 | 436,558080,573440,116736
439 | 437,446464,448512,416768
440 | 438,309248,403456,29696
441 | 439,49152,86016,7168
442 | 440,295936,304128,129024
443 | 441,134144,169984,74752
444 | 442,403456,443392,70656
445 | 443,204800,208896,857088
446 | 444,45056,65536,83968
447 | 445,818176,835584,165888
448 | 446,753664,763904,302080
449 | 447,121856,123904,311296
450 | 448,356352,407552,62464
451 | 449,880640,927744,79872
452 | 450,49152,58368,256000
453 | 451,777216,803840,146432
454 | 452,581632,584704,858112
455 | 453,32768,438272,1024
456 |
--------------------------------------------------------------------------------
/benchmarks/examples/input.12.csv:
--------------------------------------------------------------------------------
1 | id,lower,upper,size
2 | b1,0,3,4
3 | b2,3,9,4
4 | b3,0,9,4
5 | b4,9,21,4
6 | b5,0,21,4
7 |
--------------------------------------------------------------------------------
/img/acm_badges.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/google/minimalloc/18d8590d548daf2574b57265b71307e92a7b559d/img/acm_badges.png
--------------------------------------------------------------------------------
/img/lattice.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/google/minimalloc/18d8590d548daf2574b57265b71307e92a7b559d/img/lattice.gif
--------------------------------------------------------------------------------
/img/minimalloc-with-badges.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/google/minimalloc/18d8590d548daf2574b57265b71307e92a7b559d/img/minimalloc-with-badges.png
--------------------------------------------------------------------------------
/img/minimalloc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/google/minimalloc/18d8590d548daf2574b57265b71307e92a7b559d/img/minimalloc.png
--------------------------------------------------------------------------------
/scripts/run-challenging.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | for input in benchmarks/challenging/*; do
4 | cmd="./minimalloc --capacity=1048576 --input=$input --output=out.txt"
5 | runtime=$( (eval "$cmd") 2>&1 )
6 | printf "%s %8s sec.\n" "$input" "$runtime"
7 | done
8 |
--------------------------------------------------------------------------------
/src/converter.cc:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2023 Google LLC
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #include "converter.h"
18 |
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 |
26 | #include "absl/container/flat_hash_map.h"
27 | #include "absl/status/status.h"
28 | #include "absl/status/statusor.h"
29 | #include "absl/strings/numbers.h"
30 | #include "absl/strings/str_cat.h"
31 | #include "absl/strings/str_join.h"
32 | #include "absl/strings/str_split.h"
33 | #include "absl/strings/string_view.h"
34 | #include "minimalloc.h"
35 |
36 | namespace minimalloc {
37 |
38 | namespace {
39 |
40 | constexpr absl::string_view kAlignment = "alignment";
41 | constexpr absl::string_view kBegin = "begin";
42 | constexpr absl::string_view kBuffer = "buffer";
43 | constexpr absl::string_view kBufferId = "buffer_id";
44 | constexpr absl::string_view kEnd = "end";
45 | constexpr absl::string_view kGaps = "gaps";
46 | constexpr absl::string_view kHint = "hint";
47 | constexpr absl::string_view kId = "id";
48 | constexpr absl::string_view kLower = "lower";
49 | constexpr absl::string_view kOffset = "offset";
50 | constexpr absl::string_view kSize = "size";
51 | constexpr absl::string_view kStart = "start";
52 | constexpr absl::string_view kUpper = "upper";
53 |
54 | bool IncludeAlignment(const Problem& problem) {
55 | for (const Buffer& buffer : problem.buffers) {
56 | if (buffer.alignment != 1) return true;
57 | }
58 | return false;
59 | }
60 |
61 | bool IncludeHint(const Problem& problem) {
62 | for (const Buffer& buffer : problem.buffers) {
63 | if (buffer.hint) return true;
64 | }
65 | return false;
66 | }
67 |
68 | bool IncludeGaps(const Problem& problem) {
69 | for (const Buffer& buffer : problem.buffers) {
70 | if (!buffer.gaps.empty()) return true;
71 | }
72 | return false;
73 | }
74 |
75 | } // namespace
76 |
77 | std::string ToCsv(const Problem& problem, Solution* solution, bool old_format) {
78 | const bool include_alignment = IncludeAlignment(problem);
79 | const bool include_hint = IncludeHint(problem);
80 | const bool include_gaps = IncludeGaps(problem);
81 | const int addend = old_format ? -1 : 0;
82 | std::vector header = {std::string(kId),
83 | std::string(old_format ? kStart : kLower),
84 | std::string(old_format ? kEnd : kUpper),
85 | std::string(kSize)};
86 | if (include_alignment) header.push_back(std::string(kAlignment));
87 | if (include_hint) header.push_back(std::string(kHint));
88 | if (include_gaps) header.push_back(std::string(kGaps));
89 | if (solution) header.push_back(std::string(kOffset));
90 | std::vector> input = { header };
91 | for (auto buffer_idx = 0; buffer_idx < problem.buffers.size(); ++buffer_idx) {
92 | const Buffer& buffer = problem.buffers[buffer_idx];
93 | const auto& lifespan = buffer.lifespan;
94 | std::vector gaps;
95 | gaps.reserve(buffer.gaps.size());
96 | for (const Gap& gap : buffer.gaps) {
97 | std::string gap_str = absl::StrCat(gap.lifespan.lower(), "-",
98 | gap.lifespan.upper() + addend);
99 | if (gap.window) {
100 | gap_str +=
101 | absl::StrCat("@", gap.window->lower(), ":", gap.window->upper());
102 | }
103 | gaps.push_back(gap_str);
104 | }
105 | std::vector record = {absl::StrCat(buffer.id),
106 | absl::StrCat(lifespan.lower()),
107 | absl::StrCat(lifespan.upper() + addend),
108 | absl::StrCat(buffer.size)};
109 | if (include_alignment) record.push_back(absl::StrCat(buffer.alignment));
110 | if (include_hint) record.push_back(absl::StrCat(buffer.hint.value_or(-1)));
111 | if (include_gaps) record.push_back(absl::StrJoin(gaps, " "));
112 | if (solution) record.push_back(absl::StrCat(solution->offsets[buffer_idx]));
113 | input.push_back(record);
114 | }
115 | std::ostringstream oss;
116 | for (const auto& record : input) {
117 | oss << absl::StrJoin(record, ",") << std::endl;
118 | }
119 | return oss.str();
120 | }
121 |
122 | absl::StatusOr FromCsv(absl::string_view input) {
123 | int64_t addend = 0;
124 | Problem problem;
125 | absl::flat_hash_map col_map;
126 | std::vector records = absl::StrSplit(input, '\n');
127 | for (const std::string_view& record : records) {
128 | if (record.empty()) break;
129 | std::vector fields = absl::StrSplit(record, ',');
130 | if (col_map.empty()) { // Need to read header row (to determine columns).
131 | for (int field_idx = 0; field_idx < fields.size(); ++field_idx) {
132 | // If column reads 'buffer_id', change it to 'buffer' for consistency.
133 | absl::string_view col_name = fields[field_idx];
134 | if (col_name == kBegin) col_name = kLower;
135 | if (col_name == kBuffer) col_name = kId;
136 | if (col_name == kBufferId) col_name = kId;
137 | if (col_name == kEnd) {
138 | col_name = kUpper;
139 | addend = 1; // Values of an "end" column are assumed to be off-by-one
140 | }
141 | if (col_name == kStart) col_name = kLower;
142 | col_map[col_name] = field_idx;
143 | }
144 | if (col_map.size() != fields.size()) {
145 | return absl::InvalidArgumentError("Duplicate column names");
146 | }
147 | if (!col_map.contains(kId) || !col_map.contains(kLower) ||
148 | !col_map.contains(kUpper) || !col_map.contains(kSize)) {
149 | return absl::NotFoundError("A required column is missing");
150 | }
151 | continue;
152 | }
153 | if (fields.size() != col_map.size()) {
154 | return absl::InvalidArgumentError("Too many fields");
155 | }
156 | const std::string& id = static_cast(fields[col_map[kId]]);
157 | int64_t lower = -1, upper = -1, size = -1;
158 | if (!absl::SimpleAtoi(fields[col_map[kLower]], &lower) ||
159 | !absl::SimpleAtoi(fields[col_map[kUpper]], &upper) ||
160 | !absl::SimpleAtoi(fields[col_map[kSize]], &size)) {
161 | return absl::InvalidArgumentError("Improperly formed integer");
162 | }
163 | int64_t alignment = 1;
164 | if (col_map.contains(kAlignment)) {
165 | if (!absl::SimpleAtoi(fields[col_map[kAlignment]], &alignment)) {
166 | return absl::InvalidArgumentError(
167 | absl::StrCat("Improperly formed alignment: ",
168 | fields[col_map[kAlignment]]));
169 | }
170 | }
171 | std::optional hint;
172 | if (col_map.contains(kHint)) {
173 | int hint_val = -1;
174 | if (!absl::SimpleAtoi(fields[col_map[kHint]], &hint_val)) {
175 | return absl::InvalidArgumentError("Improperly formed hint");
176 | }
177 | if (hint_val >= 0) hint = hint_val;
178 | }
179 | std::vector gaps;
180 | if (col_map.contains(kGaps)) {
181 | absl::string_view gaps_str = fields[col_map[kGaps]];
182 | std::vector gaps_list =
183 | absl::StrSplit(gaps_str, ' ', absl::SkipEmpty());
184 | for (absl::string_view gap : gaps_list) {
185 | std::vector at = absl::StrSplit(gap, '@');
186 | if (at.empty()) {
187 | return absl::InvalidArgumentError(
188 | absl::StrCat("Improperly formed gap: ", gap));
189 | }
190 | std::vector gap_pair = absl::StrSplit(at[0], '-');
191 | if (gap_pair.size() != 2) {
192 | return absl::InvalidArgumentError(
193 | absl::StrCat("Improperly formed gap: ", gap));
194 | }
195 | TimeValue gap_lower, gap_upper;
196 | if (!absl::SimpleAtoi(gap_pair[0], &gap_lower) ||
197 | !absl::SimpleAtoi(gap_pair[1], &gap_upper)) {
198 | return absl::InvalidArgumentError(
199 | absl::StrCat("Improperly formed gap: ", gap));
200 | }
201 | std::optional window;
202 | if (at.size() > 1) {
203 | std::vector at_pair = absl::StrSplit(at[1], ':');
204 | if (at_pair.size() != 2) {
205 | return absl::InvalidArgumentError(
206 | absl::StrCat("Improperly formed gap: ", gap));
207 | }
208 | int64_t window_lower, window_upper;
209 | if (!absl::SimpleAtoi(at_pair[0], &window_lower) ||
210 | !absl::SimpleAtoi(at_pair[1], &window_upper)) {
211 | return absl::InvalidArgumentError(
212 | absl::StrCat("Improperly formed gap: ", gap));
213 | }
214 | window = {window_lower, window_upper};
215 | }
216 | gaps.push_back({.lifespan = {gap_lower, gap_upper + addend},
217 | .window = window});
218 | }
219 | }
220 | std::optional offset;
221 | if (col_map.contains(kOffset)) {
222 | int offset_val = -1;
223 | if (!absl::SimpleAtoi(fields[col_map[kOffset]], &offset_val)) {
224 | return absl::InvalidArgumentError("Improperly formed offset");
225 | }
226 | offset = offset_val;
227 | }
228 | problem.buffers.push_back({.id = id,
229 | .lifespan = {lower, upper + addend},
230 | .size = size,
231 | .alignment = alignment,
232 | .gaps = gaps,
233 | .offset = offset,
234 | .hint = hint});
235 | }
236 | return problem;
237 | }
238 |
239 | } // namespace minimalloc
240 |
--------------------------------------------------------------------------------
/src/converter.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2023 Google LLC
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #ifndef MINIMALLOC_SRC_CONVERTER_H_
18 | #define MINIMALLOC_SRC_CONVERTER_H_
19 |
20 | #include
21 |
22 | #include "minimalloc.h"
23 | #include "absl/status/statusor.h"
24 | #include "absl/strings/string_view.h"
25 |
26 | namespace minimalloc {
27 |
28 | // Converts a Problem, along with an optional Solution, into a CSV like this:
29 | //
30 | // id,lower,upper,size,alignment
31 | // 0,10,20,1,1
32 | // 1,20,40,2,1
33 | // 2,10,40,3,2
34 | //
35 | // If a solution is provided, an additional "offset" column will be created.
36 | std::string ToCsv(const Problem& problem,
37 | Solution* solution = nullptr,
38 | bool old_format = false);
39 |
40 | // Given a CSV like the one below (with buffers listed in any order), converts
41 | // it into a Problem instance or returns a status if the problem is malformed:
42 | //
43 | // id,lower,upper,size,alignment
44 | // 1,20,20,2,1
45 | // 0,10,20,1,1
46 | // 2,10,40,3,2
47 | //
48 | // If an offset or hint column is provided, these values will be stored into
49 | // each buffer's offset or hint member field (respectively).
50 | absl::StatusOr FromCsv(absl::string_view input);
51 |
52 | } // namespace minimalloc
53 |
54 | #endif // MINIMALLOC_SRC_CONVERTER_H_
55 |
--------------------------------------------------------------------------------
/src/main.cc:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2023 Google LLC
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 |
28 | #include "absl/flags/flag.h"
29 | #include "absl/flags/parse.h"
30 | #include "absl/status/statusor.h"
31 | #include "absl/strings/str_split.h"
32 | #include "absl/strings/string_view.h"
33 | #include "absl/time/clock.h"
34 | #include "absl/time/time.h"
35 | #include "converter.h"
36 | #include "minimalloc.h"
37 | #include "solver.h"
38 | #include "validator.h"
39 |
40 | ABSL_FLAG(int64_t, capacity, 0, "The maximum memory capacity.");
41 | ABSL_FLAG(std::string, input, "", "The path to the input CSV file.");
42 | ABSL_FLAG(std::string, output, "", "The path to the output CSV file.");
43 | ABSL_FLAG(absl::Duration, timeout, absl::InfiniteDuration(),
44 | "The time limit enforced for the MiniMalloc solver.");
45 | ABSL_FLAG(bool, validate, false, "Validates the solver's output.");
46 |
47 | ABSL_FLAG(bool, canonical_only, true, "Explores canonical solutions only.");
48 | ABSL_FLAG(bool, section_inference, true, "Performs advanced inference.");
49 | ABSL_FLAG(bool, dynamic_ordering, true, "Dynamically orders buffers.");
50 | ABSL_FLAG(bool, check_dominance, true,
51 | "Checks for dominated solutions that leave gaps in the allocation.");
52 | ABSL_FLAG(bool, unallocated_floor, true,
53 | "Uses min offsets to establish lower bounds on section floors.");
54 | ABSL_FLAG(bool, static_preordering, true, "Statically preorders buffers.");
55 | ABSL_FLAG(bool, dynamic_decomposition, true, "Dynamically decomposes buffers.");
56 | ABSL_FLAG(bool, monotonic_floor, true,
57 | "Requires the solution floor to increase monotonically.");
58 | ABSL_FLAG(bool, hatless_pruning, true,
59 | "Prunes alternate solutions whenever a buffer has nothing overhead.");
60 |
61 | ABSL_FLAG(std::string, preordering_heuristics, "WAT,TAW,TWA",
62 | "Static preordering heuristics to attempt.");
63 |
64 | ABSL_FLAG(bool, print_solution, false, "Prints the solution in LaTeX");
65 |
66 | // Found using trial-and-error with the LaTeX 'tikzpicture' package.
67 | const float kWidth = 17;
68 | const float kHeight = 8.5;
69 |
70 | void PrintSolution(const minimalloc::Problem& problem,
71 | const minimalloc::Solution& solution) {
72 | std::ostream& os = std::cout;
73 | os << std::endl;
74 | os << "\\documentclass[tikz]{standalone}" << std::endl;
75 | os << "\\usepackage{tikz}" << std::endl;
76 | os << "\\usepackage{pgfplots}" << std::endl;
77 | os << "\\begin{document}" << std::endl;
78 | os << "\\begin{tikzpicture}" << std::endl;
79 | minimalloc::TimeValue min_time = INT_MAX;
80 | minimalloc::TimeValue max_time = 0;
81 | for (const minimalloc::Buffer& buffer : problem.buffers) {
82 | min_time = std::min(min_time, buffer.lifespan.lower());
83 | max_time = std::max(max_time, buffer.lifespan.upper());
84 | }
85 | const float scale_x = kWidth / (max_time - min_time);
86 | const float scale_y = kHeight / problem.capacity;
87 | for (int buffer_idx = 0; buffer_idx < problem.buffers.size(); ++buffer_idx) {
88 | const minimalloc::Buffer& buffer = problem.buffers[buffer_idx];
89 | for (int i = 0; i <= buffer.gaps.size(); ++i) {
90 | auto left = (i == 0) ? buffer.lifespan.lower()
91 | : buffer.gaps[i - 1].lifespan.upper();
92 | auto right = (i == buffer.gaps.size()) ? buffer.lifespan.upper()
93 | : buffer.gaps[i].lifespan.lower();
94 | if (left == right) continue;
95 | const float x = scale_x * (left - min_time);
96 | const float y = scale_y * solution.offsets[buffer_idx];
97 | const float w = scale_x * (right - left);
98 | const float h = scale_y * buffer.size;
99 | const std::string color = "lightgray";
100 | os << "\\fill[" << color << ",draw=darkgray] (" << x << "," << y
101 | << ")" << " rectangle (" << x + w << "," << y + h << "); % height = "
102 | << h << ", ID = " << buffer.id << std::endl;
103 |
104 | // If you don't want to see the buffer.id, comment this line
105 | os << "\\node at (" << x + w / 2 << "," << y + h / 2 << ")" << " {" << buffer.id << "};" << std::endl;
106 |
107 | }
108 | }
109 | const float w = scale_x * (max_time - min_time);
110 | const float h = scale_y * problem.capacity;
111 | os << "\\fill[draw=black,fill opacity=0,thick] (0,0) rectangle "
112 | << "(" << w << "," << h << ");" << std::endl;
113 | os << "\\end{tikzpicture}" << std::endl;
114 | os << "\\end{document}" << std::endl;
115 | }
116 |
117 | // Solves a given problem using the Solver.
118 | int main(int argc, char* argv[]) {
119 | absl::ParseCommandLine(argc, argv);
120 | minimalloc::SolverParams params = {
121 | .timeout = absl::GetFlag(FLAGS_timeout),
122 | .canonical_only = absl::GetFlag(FLAGS_canonical_only),
123 | .section_inference = absl::GetFlag(FLAGS_section_inference),
124 | .dynamic_ordering = absl::GetFlag(FLAGS_dynamic_ordering),
125 | .check_dominance = absl::GetFlag(FLAGS_check_dominance),
126 | .unallocated_floor = absl::GetFlag(FLAGS_unallocated_floor),
127 | .static_preordering = absl::GetFlag(FLAGS_static_preordering),
128 | .dynamic_decomposition = absl::GetFlag(FLAGS_dynamic_decomposition),
129 | .monotonic_floor = absl::GetFlag(FLAGS_monotonic_floor),
130 | .hatless_pruning = absl::GetFlag(FLAGS_hatless_pruning),
131 | .preordering_heuristics = absl::StrSplit(
132 | absl::GetFlag(FLAGS_preordering_heuristics), ',', absl::SkipEmpty()),
133 | };
134 | std::ifstream ifs(absl::GetFlag(FLAGS_input));
135 | std::string csv((std::istreambuf_iterator(ifs)),
136 | (std::istreambuf_iterator() ));
137 | absl::StatusOr problem = minimalloc::FromCsv(csv);
138 | if (!problem.ok()) return 1;
139 | problem->capacity = absl::GetFlag(FLAGS_capacity);
140 | minimalloc::Solver solver(params);
141 | const absl::Time start_time = absl::Now();
142 | absl::StatusOr solution = solver.Solve(*problem);
143 | const absl::Time end_time = absl::Now();
144 | std::cerr << std::fixed << std::setprecision(3)
145 | << absl::ToDoubleSeconds(end_time - start_time);
146 | if (!solution.ok()) return 1;
147 | if (absl::GetFlag(FLAGS_validate)) {
148 | minimalloc::ValidationResult validation_result =
149 | minimalloc::Validate(*problem, *solution);
150 | std::cerr << (validation_result == minimalloc::ValidationResult::kGood
151 | ? "PASS" : "FAIL") << std::endl;
152 | }
153 | if (absl::GetFlag(FLAGS_print_solution)) PrintSolution(*problem, *solution);
154 | std::string contents = minimalloc::ToCsv(*problem, &(*solution));
155 | std::ofstream ofs(absl::GetFlag(FLAGS_output));
156 | ofs << contents;
157 | ofs.close();
158 | return 0;
159 | }
160 |
--------------------------------------------------------------------------------
/src/minimalloc.cc:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | Copyright 2023 Google LLC
4 |
5 | Licensed under the Apache License, Version 2.0 (the "License");
6 | you may not use this file except in compliance with the License.
7 | You may obtain a copy of the License at
8 |
9 | https://www.apache.org/licenses/LICENSE-2.0
10 |
11 | Unless required by applicable law or agreed to in writing, software
12 | distributed under the License is distributed on an "AS IS" BASIS,
13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | See the License for the specific language governing permissions and
15 | limitations under the License.
16 | */
17 |
18 | #include "minimalloc.h"
19 |
20 | #include
21 | #include
22 | #include
23 | #include
24 |
25 | #include "absl/status/status.h"
26 | #include "absl/status/statusor.h"
27 |
28 | namespace minimalloc {
29 |
30 | namespace {
31 |
32 | enum PointType { kLeft, kLeftGap, kRightGap, kRight };
33 |
34 | struct Point {
35 | BufferIdx buffer_idx;
36 | TimeValue time_value;
37 | PointType point_type;
38 | std::optional window;
39 | bool operator<(const Point& x) const {
40 | if (time_value != x.time_value) return time_value < x.time_value;
41 | if (point_type != x.point_type) return point_type < x.point_type;
42 | return buffer_idx < x.buffer_idx;
43 | }
44 | };
45 |
46 | } // namespace
47 |
48 | bool Gap::operator==(const Gap& x) const {
49 | return lifespan == x.lifespan && window == x.window;
50 | }
51 |
52 | bool Buffer::operator==(const Buffer& x) const {
53 | return id == x.id
54 | && lifespan == x.lifespan
55 | && size == x.size
56 | && alignment == x.alignment
57 | && offset == x.offset
58 | && gaps == x.gaps;
59 | }
60 |
61 | bool Solution::operator==(const Solution& x) const {
62 | return offsets == x.offsets;
63 | }
64 |
65 | bool Problem::operator==(const Problem& x) const {
66 | return buffers == x.buffers
67 | && capacity == x.capacity;
68 | }
69 |
70 | Area Buffer::area() const {
71 | return size * (lifespan.upper() - lifespan.lower());
72 | }
73 |
74 | std::optional Buffer::effective_size(const Buffer& x) const {
75 | if (lifespan.upper() <= x.lifespan.lower()) return std::nullopt;
76 | if (x.lifespan.upper() <= lifespan.lower()) return std::nullopt;
77 | const Window window = {0, size};
78 | const Window x_window = {0, x.size};
79 | std::vector points = {{0, lifespan.lower(), kLeft, window},
80 | {0, lifespan.upper(), kRight, std::nullopt},
81 | {1, x.lifespan.lower(), kLeft, x_window},
82 | {1, x.lifespan.upper(), kRight, std::nullopt}};
83 | for (const Gap& gap : gaps) {
84 | points.push_back({0, gap.lifespan.lower(), kRightGap, gap.window});
85 | points.push_back({0, gap.lifespan.upper(), kLeftGap, window});
86 | }
87 | for (const Gap& gap : x.gaps) {
88 | points.push_back({1, gap.lifespan.lower(), kRightGap, gap.window});
89 | points.push_back({1, gap.lifespan.upper(), kLeftGap, x_window});
90 | }
91 | std::sort(points.begin(), points.end());
92 | std::optional windows[2];
93 | std::optional effective_size;
94 | std::optional last_time;
95 | for (const Point& point : points) {
96 | if (last_time && point.time_value > *last_time) { // We've moved right
97 | if (windows[0] && windows[1]) { // Both buffers are active, let's check
98 | const int64_t diff = windows[0]->upper() - windows[1]->lower();
99 | if (!effective_size || *effective_size < diff) effective_size = diff;
100 | }
101 | }
102 | last_time = point.time_value;
103 | windows[point.buffer_idx] = point.window;
104 | }
105 | return effective_size;
106 | }
107 |
108 | absl::StatusOr Problem::strip_solution() {
109 | Solution solution;
110 | for (Buffer& buffer : buffers) {
111 | if (!buffer.offset) {
112 | return absl::NotFoundError("Buffer found with no offset");
113 | }
114 | solution.offsets.push_back(*buffer.offset);
115 | buffer.offset.reset();
116 | }
117 | return solution;
118 | }
119 |
120 | } // namespace minimalloc
121 |
--------------------------------------------------------------------------------
/src/minimalloc.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2023 Google LLC
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #ifndef MINIMALLOC_SRC_MINIMALLOC_H_
18 | #define MINIMALLOC_SRC_MINIMALLOC_H_
19 |
20 | #include
21 |
22 | #include
23 | #include
24 | #include
25 |
26 | #include "absl/status/statusor.h"
27 |
28 | // MiniMalloc is a lightweight memory allocator for hardware-accelerated ML.
29 | namespace minimalloc {
30 |
31 | template
32 | struct Interval {
33 | T lower_ = 0;
34 | T upper_ = 0;
35 |
36 | T lower() const { return lower_; }
37 | T upper() const { return upper_; }
38 |
39 | bool operator==(const Interval& other) const {
40 | return lower_ == other.lower_ && upper_ == other.upper_;
41 | }
42 | bool operator<(const Interval& other) const {
43 | if (lower_ != other.lower_) return lower_ < other.lower_;
44 | return upper_ < other.upper_;
45 | }
46 | };
47 |
48 | using BufferIdx = int64_t; // An index into a Problem's list of buffers.
49 | using Capacity = int64_t; // A maximum memory capacity defined @ Problem level.
50 | using Offset = int64_t; // A memory address (eg in bytes) assigned to a buffer.
51 | using TimeValue = int64_t; // An abstract unitless start/end time of a buffer.
52 | using Area = int64_t; // The unitless product of a buffer's length and size.
53 | using Lifespan = Interval;
54 | using Window = Interval;
55 |
56 | struct Gap {
57 | Lifespan lifespan; // The interval where this gap applies.
58 | std::optional window; // The space (if any) consumed within this gap.
59 | bool operator==(const Gap& x) const;
60 | };
61 |
62 | struct Buffer {
63 | std::string id; // A unique identifier for this buffer (used in file I/O).
64 | Lifespan lifespan = {0, 0}; // Half-open.
65 | int64_t size = 0; // The amount of memory allocated during the lifespan.
66 | int64_t alignment = 1; // The lowest common denominator of assigned offsets.
67 | std::vector gaps; // Slots where this buffer is inactive.
68 | std::optional offset; // If present, the fixed pos. of this buffer.
69 | std::optional hint; // If present, provides a hint to the solver.
70 |
71 | // The product of this buffer's size and lifespan length.
72 | Area area() const;
73 |
74 | // The size assuming that buffer 'x' needs to be placed directly above. Might
75 | // be small if the windows of our gaps are low (or, if the windows of their
76 | // gaps are high). Might even be absent if the gaps line up "just so."
77 | std::optional effective_size(const Buffer& x) const;
78 |
79 | bool operator==(const Buffer& x) const;
80 | };
81 |
82 | struct Solution {
83 | std::vector offsets;
84 | bool operator==(const Solution& x) const;
85 | };
86 |
87 | struct Problem {
88 | std::vector buffers;
89 |
90 | // The total size of the memory address space (i.e. the maximum amount of
91 | // available memory that all buffers must be packed within). No buffer may be
92 | // assigned an offset such that offset + size > capacity.
93 | Capacity capacity = 0;
94 |
95 | // Extracts a solution from the offset value of each buffer, which is cleared.
96 | absl::StatusOr strip_solution();
97 |
98 | bool operator==(const Problem& x) const;
99 | };
100 |
101 | } // namespace minimalloc
102 |
103 | #endif // MINIMALLOC_SRC_MINIMALLOC_H_
104 |
--------------------------------------------------------------------------------
/src/solver.cc:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2023 Google LLC
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #include "solver.h"
18 |
19 | #include
20 |
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 |
28 | #include "absl/algorithm/container.h"
29 | #include "absl/container/flat_hash_set.h"
30 | #include "absl/status/status.h"
31 | #include "absl/status/statusor.h"
32 | #include "absl/time/clock.h"
33 | #include "absl/time/time.h"
34 | #include "minimalloc.h"
35 | #include "sweeper.h"
36 |
37 | namespace minimalloc {
38 | namespace {
39 |
40 | using PreorderIdx = int; // An index into a preordered buffer list.
41 |
42 | constexpr int kNoOffset = -1;
43 |
44 | // Used to incrementally maintain data about sections during search.
45 | struct SectionData {
46 | Offset floor = 0; // The lowest viable offset for any buffer in this section.
47 | int total = 0; // A sum of the total unallocated buffer sizes in the section.
48 | };
49 |
50 | // Data used to help establish a dynamic ordering of buffers.
51 | struct OrderData {
52 | Offset offset = 0;
53 | PreorderIdx preorder_idx = 0;
54 | };
55 |
56 | // A record of a buffer's minimum offset value prior to a change during search.
57 | struct OffsetChange {
58 | BufferIdx buffer_idx;
59 | Offset min_offset;
60 | };
61 |
62 | // A record of a section's floor value prior to a change during search.
63 | struct SectionChange {
64 | SectionIdx section_idx;
65 | Offset floor;
66 | };
67 |
68 | // Dynamically orders buffers by minimum offset, followed by preorder index.
69 | const auto kDynamicComparator =
70 | [](const OrderData& a, const OrderData& b) {
71 | if (a.offset != b.offset) return a.offset < b.offset;
72 | return a.preorder_idx < b.preorder_idx;
73 | };
74 |
75 | class SolverImpl {
76 | public:
77 | SolverImpl(const SolverParams& params, const absl::Time start_time,
78 | const Problem& problem, const SweepResult& sweep_result,
79 | int64_t* backtracks, std::atomic& cancelled) : params_(params),
80 | start_time_(start_time), problem_(problem), sweep_result_(sweep_result),
81 | backtracks_(*backtracks), cancelled_(cancelled) {}
82 |
83 | absl::StatusOr Solve() {
84 | if (problem_.buffers.empty()) return solution_;
85 | const auto num_buffers = problem_.buffers.size();
86 | assignment_.offsets.resize(num_buffers, kNoOffset);
87 | solution_.offsets.resize(num_buffers, kNoOffset);
88 | min_offsets_.resize(num_buffers);
89 | section_data_.resize(sweep_result_.sections.size());
90 | for (BufferIdx buffer_idx = 0; buffer_idx < num_buffers; ++buffer_idx) {
91 | const BufferData& buffer_data = sweep_result_.buffer_data[buffer_idx];
92 | for (const SectionSpan& section_span : buffer_data.section_spans) {
93 | const SectionRange& section_range = section_span.section_range;
94 | const Window& window = section_span.window;
95 | for (SectionIdx s_idx = section_range.lower();
96 | s_idx < section_range.upper(); ++s_idx) {
97 | section_data_[s_idx].total += window.upper() - window.lower();
98 | }
99 | }
100 | if (const Buffer& buffer = problem_.buffers[buffer_idx]; buffer.offset) {
101 | min_offsets_[buffer_idx] = *buffer.offset;
102 | }
103 | }
104 | cuts_ = sweep_result_.CalculateCuts();
105 | // If multiple heuristics were specified, use round robin to try them all.
106 | if (params_.preordering_heuristics.size() > 1) return RoundRobin();
107 | PreorderingComparator preordering_comparator(
108 | params_.preordering_heuristics.back());
109 | for (const Partition& partition : sweep_result_.partitions) {
110 | absl::Status status = SubSolve(partition, preordering_comparator);
111 | if (!status.ok()) return status;
112 | }
113 | return solution_;
114 | }
115 |
116 | private:
117 | absl::StatusOr RoundRobin() {
118 | // We'll start with a conservative node limit (in the hopes that one of
119 | // them will finish quickly), then progressively increase this threshold.
120 | int64_t node_limit = problem_.buffers.size();
121 | while (true) {
122 | node_limit *= 2;
123 | absl::Status status = absl::OkStatus();
124 | for (const auto& heuristic : params_.preordering_heuristics) {
125 | PreorderingComparator preordering_comparator(heuristic);
126 | nodes_remaining_ = node_limit;
127 | status = absl::OkStatus();
128 | for (const Partition& partition : sweep_result_.partitions) {
129 | status = SubSolve(partition, preordering_comparator);
130 | // The 'aborted' code means this strategy exhausted its node limit.
131 | if (status.code() == absl::StatusCode::kAborted) break;
132 | if (!status.ok()) return status;
133 | }
134 | if (status.ok()) break;
135 | }
136 | if (status.ok()) break;
137 | }
138 | return solution_;
139 | }
140 |
141 | // Prepopulates section data for this partition, then kicks into the recursive
142 | // depth-first search. Returns 'true' if a feasible solution has been found,
143 | // otherwise 'false'.
144 | absl::Status SubSolve(
145 | const Partition& partition,
146 | const PreorderingComparator& preordering_comparator) {
147 | std::vector preordering;
148 | preordering.reserve(partition.buffer_idxs.size());
149 | for (const BufferIdx buffer_idx : partition.buffer_idxs) {
150 | const Buffer& buffer = problem_.buffers[buffer_idx];
151 | int total = 0;
152 | const BufferData& buffer_data = sweep_result_.buffer_data[buffer_idx];
153 | const std::vector& section_spans = buffer_data.section_spans;
154 | for (const SectionSpan& section_span : section_spans) {
155 | const SectionRange& section_range = section_span.section_range;
156 | for (SectionIdx s_idx = section_range.lower();
157 | s_idx < section_range.upper(); ++s_idx) {
158 | total = std::max(total, section_data_[s_idx].total);
159 | }
160 | }
161 | int sections = section_spans.back().section_range.upper() -
162 | section_spans.front().section_range.lower();
163 | preordering.push_back({
164 | .area = buffer.area(),
165 | .lower = buffer.lifespan.lower(),
166 | .overlaps = buffer_data.overlaps.size(),
167 | .sections = sections,
168 | .size = buffer.size,
169 | .total = total,
170 | .upper = buffer.lifespan.upper(),
171 | .width = buffer.lifespan.upper() - buffer.lifespan.lower(),
172 | .buffer_idx = buffer_idx});
173 | }
174 | if (params_.static_preordering) {
175 | absl::c_sort(preordering, preordering_comparator);
176 | }
177 | std::vector ordering(preordering.size());
178 | for (PreorderIdx idx = 0; idx < preordering.size(); ++idx) {
179 | ordering[idx].preorder_idx = idx;
180 | }
181 | absl::StatusCode status_code =
182 | SearchSolutions(partition, preordering_comparator, preordering,
183 | ordering, /*min_offset=*/0, /*min_preorder_idx=*/0);
184 | return status_code == absl::StatusCode::kOk ? absl::OkStatus()
185 | : absl::Status(status_code, "Error encountered during search.");
186 | }
187 |
188 | // Updates section data given that 'buffer_idx' is the next item to be placed.
189 | std::vector UpdateSectionData(
190 | const absl::flat_hash_set& affected_sections,
191 | BufferIdx buffer_idx) {
192 | std::vector section_changes;
193 | const Offset offset = assignment_.offsets[buffer_idx];
194 | // For any section this buffer resides in, bump up the floor & drop the sum.
195 | const BufferData& buffer_data = sweep_result_.buffer_data[buffer_idx];
196 | for (const SectionSpan& section_span : buffer_data.section_spans) {
197 | const SectionRange& section_range = section_span.section_range;
198 | const Window& window = section_span.window;
199 | const Offset height = offset + window.upper();
200 | for (SectionIdx s_idx = section_range.lower();
201 | s_idx < section_range.upper(); ++s_idx) {
202 | section_changes.push_back(
203 | {.section_idx = s_idx, .floor = section_data_[s_idx].floor});
204 | section_data_[s_idx].floor = height;
205 | section_data_[s_idx].total -= window.upper() - window.lower();
206 | }
207 | }
208 | // The floor of any section cannot be lower than its lowest minimum offset.
209 | for (const SectionIdx s_idx : affected_sections) {
210 | Offset min_offset = INT_MAX;
211 | for (const BufferIdx other_idx : sweep_result_.sections[s_idx]) {
212 | if (assignment_.offsets[other_idx] == kNoOffset) {
213 | min_offset = std::min(min_offset, min_offsets_[other_idx]);
214 | }
215 | }
216 | if (min_offset != INT_MAX && section_data_[s_idx].floor < min_offset) {
217 | section_changes.push_back(
218 | {.section_idx = s_idx, .floor = section_data_[s_idx].floor});
219 | section_data_[s_idx].floor = min_offset;
220 | }
221 | }
222 | return section_changes;
223 | }
224 |
225 | // Restores the section data by reversing any recorded changes.
226 | void RestoreSectionData(
227 | const std::vector& section_changes,
228 | BufferIdx buffer_idx) {
229 | for (auto c = section_changes.rbegin(); c != section_changes.rend(); ++c) {
230 | section_data_[c->section_idx].floor = c->floor;
231 | }
232 | // For any section this buffer resides in, increase the sum.
233 | const BufferData& buffer_data = sweep_result_.buffer_data[buffer_idx];
234 | for (const SectionSpan& section_span : buffer_data.section_spans) {
235 | const SectionRange& section_range = section_span.section_range;
236 | const Window& window = section_span.window;
237 | for (SectionIdx s_idx = section_range.lower();
238 | s_idx < section_range.upper(); ++s_idx) {
239 | section_data_[s_idx].total += window.upper() - window.lower();
240 | }
241 | }
242 | }
243 |
244 | // Updates min offset data, given that 'buffer_idx' is the next to be placed.
245 | std::optional> UpdateMinOffsets(
246 | BufferIdx buffer_idx,
247 | absl::flat_hash_set& affected_sections,
248 | bool& fixed_offset_failure) {
249 | bool hatless = true;
250 | std::vector offset_changes;
251 | const Offset offset = assignment_.offsets[buffer_idx];
252 | // For any overlap this buffer participates in, bump up its minimum offset.
253 | const std::vector& buffer_data = sweep_result_.buffer_data;
254 | for (const Overlap& overlap : buffer_data[buffer_idx].overlaps) {
255 | const BufferIdx other_idx = overlap.buffer_idx;
256 | if (assignment_.offsets[other_idx] != kNoOffset) continue;
257 | hatless = false;
258 | const Offset height = offset + overlap.effective_size;
259 | if (min_offsets_[other_idx] >= height) continue;
260 | offset_changes.push_back(
261 | {.buffer_idx = other_idx, .min_offset = min_offsets_[other_idx]});
262 | min_offsets_[other_idx] = height;
263 | const Buffer& other_buffer = problem_.buffers[other_idx];
264 | Offset diff = min_offsets_[other_idx] % other_buffer.alignment;
265 | if (diff > 0) min_offsets_[other_idx] += other_buffer.alignment - diff;
266 | if (other_buffer.offset &&
267 | min_offsets_[other_idx] > *other_buffer.offset) {
268 | fixed_offset_failure = true;
269 | }
270 | if (!params_.unallocated_floor) continue; // Mutation safe.
271 | const BufferData& buffer_data = sweep_result_.buffer_data[other_idx];
272 | for (const SectionSpan& section_span : buffer_data.section_spans) {
273 | const SectionRange& section_range = section_span.section_range;
274 | for (SectionIdx s_idx = section_range.lower();
275 | s_idx < section_range.upper(); ++s_idx) {
276 | affected_sections.insert(s_idx);
277 | }
278 | }
279 | }
280 | if (hatless) return std::nullopt;
281 | return offset_changes;
282 | }
283 |
284 | // Restores the minimum offsets by reversing any recorded changes.
285 | void RestoreMinOffsets(const std::vector& offset_changes) {
286 | for (auto c = offset_changes.rbegin(); c != offset_changes.rend(); ++c) {
287 | min_offsets_[c->buffer_idx] = c->min_offset;
288 | }
289 | }
290 |
291 | // Returns 'true' if this partial solution satisfies consistency & inference
292 | // checks, otherwise 'false'.
293 | bool Check(const Partition& partition, Offset offset) {
294 | for (SectionIdx s_idx = partition.section_range.lower();
295 | s_idx < partition.section_range.upper(); ++s_idx) {
296 | // Note: by construction, the given section_data object is guaranteed to
297 | // have an element for every index in the partition's section_range.
298 | auto [floor, total] = section_data_[s_idx];
299 | if (params_.monotonic_floor) floor = std::max(offset, floor);
300 | if (params_.section_inference) floor += total;
301 | if (problem_.capacity < floor) return false;
302 | }
303 | return true;
304 | }
305 |
306 | // Orders unallocated buffers by their minimum possible offset values, using
307 | // buffer areas as a tie-breaker.
308 | std::vector ComputeOrdering(
309 | const std::vector& preordering,
310 | const std::vector& orig_ordering) {
311 | std::vector ordering;
312 | for (const auto [offset, preorder_idx] : orig_ordering) {
313 | const BufferIdx buffer_idx = preordering[preorder_idx].buffer_idx;
314 | // If this buffer has already been assigned, keep looking.
315 | if (assignment_.offsets[buffer_idx] != kNoOffset) continue;
316 | const Offset new_offset = min_offsets_[buffer_idx];
317 | ordering.push_back(
318 | {.offset = new_offset, .preorder_idx = preorder_idx});
319 | }
320 | if (params_.dynamic_ordering) absl::c_sort(ordering, kDynamicComparator);
321 | return ordering;
322 | }
323 |
324 | // Determines the minimum height of any unallocated buffer ... no other buffer
325 | // should be assigned to an offset at this value or greater.
326 | Offset CalcMinHeight(
327 | const std::vector& preordering,
328 | const std::vector& ordering) {
329 | Offset min_height = INT_MAX;
330 | for (const auto [offset, preorder_idx] : ordering) {
331 | const BufferIdx buffer_idx = preordering[preorder_idx].buffer_idx;
332 | const Buffer& buffer = problem_.buffers[buffer_idx];
333 | min_height = std::min(min_height, offset + buffer.size);
334 | }
335 | return min_height;
336 | }
337 |
338 | // A recursive depth-first search for buffer offset assignment. Returns 'kOk'
339 | // if a feasible solution has been found, otherwise 'kNotFound' or potentially
340 | // 'kDeadlineExceeded' / 'kAborted'.
341 | absl::StatusCode SearchSolutions(
342 | const Partition& partition,
343 | const PreorderingComparator& preordering_comparator,
344 | const std::vector& preordering,
345 | const std::vector& orig_ordering,
346 | Offset min_offset,
347 | PreorderIdx min_preorder_idx) {
348 | if (nodes_remaining_ <= 0) return absl::StatusCode::kAborted;
349 | --nodes_remaining_;
350 | if (absl::Now() - start_time_ > params_.timeout || cancelled_) {
351 | return absl::StatusCode::kDeadlineExceeded;
352 | }
353 | const std::vector ordering =
354 | ComputeOrdering(preordering, orig_ordering);
355 | if (ordering.empty()) {
356 | // Store offsets for all the buffers that participate in this partition.
357 | for (const BufferIdx buffer_idx : partition.buffer_idxs) {
358 | solution_.offsets[buffer_idx] = assignment_.offsets[buffer_idx];
359 | }
360 | return absl::StatusCode::kOk; // We've reached a leaf node.
361 | }
362 | const Offset min_height = CalcMinHeight(preordering, ordering);
363 | for (const auto [offset, preorder_idx] : ordering) {
364 | const BufferIdx buffer_idx = preordering[preorder_idx].buffer_idx;
365 | if (params_.canonical_only) {
366 | // Buffers should be placed in non-increasing order by area.
367 | if (offset < min_offset ||
368 | (offset == min_offset && preorder_idx < min_preorder_idx)) continue;
369 | }
370 | if (params_.check_dominance) {
371 | // Check if this solution would introduce an unnecessary gap.
372 | if (offset >= min_height) continue;
373 | }
374 | if (const Buffer& buffer = problem_.buffers[buffer_idx]; buffer.offset) {
375 | if (offset > *buffer.offset) continue;
376 | }
377 | assignment_.offsets[buffer_idx] = offset;
378 | absl::flat_hash_set affected_sections;
379 | bool fixed_offset_failure = false;
380 | auto offset_changes = UpdateMinOffsets(buffer_idx, affected_sections,
381 | fixed_offset_failure);
382 | std::vector section_changes =
383 | UpdateSectionData(affected_sections, buffer_idx);
384 | absl::StatusCode status_code = absl::StatusCode::kNotFound;
385 | if (!fixed_offset_failure && Check(partition, offset)) {
386 | status_code =
387 | params_.dynamic_decomposition
388 | ? DynamicallyDecompose(partition, preordering_comparator,
389 | preordering, ordering, offset, preorder_idx, buffer_idx)
390 | : SearchSolutions(partition, preordering_comparator,
391 | preordering, ordering, offset, preorder_idx);
392 | }
393 | RestoreSectionData(section_changes, buffer_idx);
394 | if (offset_changes) RestoreMinOffsets(*offset_changes);
395 | assignment_.offsets[buffer_idx] = kNoOffset; // Mark it unallocated.
396 | // If a feasible solution *or* timeout, abort search.
397 | if (status_code != absl::StatusCode::kNotFound) return status_code;
398 | if (!offset_changes && params_.hatless_pruning) break;
399 | }
400 | ++backtracks_;
401 | return absl::StatusCode::kNotFound; // No feasible solution found.
402 | }
403 |
404 | // Decomposes the problem into partitions and solves each independently. If
405 | // any subproblem is found to be infeasible, no further search is performed.
406 | absl::StatusCode DynamicallyDecompose(
407 | const Partition& partition,
408 | const PreorderingComparator& preordering_comparator,
409 | const std::vector& preordering,
410 | const std::vector& orig_ordering,
411 | Offset min_offset,
412 | PreorderIdx min_preorder_idx,
413 | BufferIdx buffer_idx) {
414 | solution_.offsets[buffer_idx] = assignment_.offsets[buffer_idx];
415 | // Reduce the cuts between sections spanned by this buffer (and store all
416 | // zero-cut section indices into 'cutpoints', to be solved separately).
417 | std::vector cutpoints = {partition.section_range.lower()};
418 | const BufferData& buffer_data = sweep_result_.buffer_data[buffer_idx];
419 | const std::vector& section_spans = buffer_data.section_spans;
420 | for (SectionIdx s_idx = section_spans.front().section_range.lower();
421 | s_idx + 1 < section_spans.back().section_range.upper(); ++s_idx) {
422 | if (--cuts_[s_idx] == 0) cutpoints.push_back(s_idx + 1);
423 | }
424 | absl::StatusCode status_code = absl::StatusCode::kOk;
425 | if (cutpoints.size() == 1) {
426 | status_code =
427 | SearchSolutions(partition, preordering_comparator, preordering,
428 | orig_ordering, min_offset, min_preorder_idx);
429 | } else {
430 | cutpoints.push_back(partition.section_range.upper());
431 | for (int c_idx = 1; c_idx < cutpoints.size(); ++c_idx) {
432 | // Determine the range of this sub-partition.
433 | const SectionRange section_range =
434 | {cutpoints[c_idx - 1], cutpoints[c_idx]};
435 | // Determine the contents of this sub-partition.
436 | std::vector buffer_idxs;
437 | for (const BufferIdx other_idx : partition.buffer_idxs) {
438 | // A minor optimization (mutants ok).
439 | if (assignment_.offsets[other_idx] != kNoOffset) continue;
440 | const BufferData& other_data = sweep_result_.buffer_data[other_idx];
441 | const SectionRange other_range = {
442 | other_data.section_spans.front().section_range.lower(),
443 | other_data.section_spans.back().section_range.upper()
444 | };
445 | if (!(other_range.upper() <= section_range.lower() ||
446 | section_range.upper() <= other_range.lower())) {
447 | buffer_idxs.push_back(other_idx);
448 | }
449 | }
450 | if (buffer_idxs.empty()) continue;
451 | // Create the sub-partition and solve it.
452 | const Partition sub_partition =
453 | {.buffer_idxs = buffer_idxs, .section_range = section_range};
454 | absl::Status status = SubSolve(sub_partition, preordering_comparator);
455 | if (!status.ok()) {
456 | status_code = status.code();
457 | break;
458 | }
459 | }
460 | }
461 | // Restore all section cuts to their previous values.
462 | for (SectionIdx s_idx = section_spans.front().section_range.lower();
463 | s_idx + 1 < section_spans.back().section_range.upper(); ++s_idx) {
464 | ++cuts_[s_idx];
465 | }
466 | return status_code;
467 | }
468 |
469 | const SolverParams& params_;
470 | const absl::Time start_time_;
471 | const Problem& problem_;
472 | const SweepResult& sweep_result_;
473 | int64_t& backtracks_;
474 | std::atomic& cancelled_;
475 |
476 | Solution assignment_;
477 | Solution solution_;
478 | std::vector min_offsets_;
479 | std::vector section_data_;
480 | std::vector cuts_;
481 | int64_t nodes_remaining_ = std::numeric_limits::max();
482 | }; // class SolverImpl
483 |
484 | } // namespace
485 |
486 | PreorderingComparator::PreorderingComparator(const PreorderingHeuristic& h) :
487 | preordering_heuristic_(h) {}
488 |
489 | bool PreorderingComparator::operator()(
490 | const PreorderData& a, const PreorderData& b) const {
491 | for (const char &c : preordering_heuristic_) {
492 | if (c == 'A' && a.area != b.area) return a.area > b.area;
493 | if (c == 'C' && a.sections != b.sections) return a.sections > b.sections;
494 | if (c == 'L' && a.lower != b.lower) return a.lower > b.lower;
495 | if (c == 'O' && a.overlaps != b.overlaps) return a.overlaps > b.overlaps;
496 | if (c == 'T' && a.total != b.total) return a.total > b.total;
497 | if (c == 'U' && a.upper != b.upper) return a.upper > b.upper;
498 | if (c == 'W' && a.width != b.width) return a.width > b.width;
499 | if (c == 'Z' && a.size != b.size) return a.size > b.size;
500 | }
501 | return a.buffer_idx < b.buffer_idx;
502 | }
503 |
504 | Solver::Solver() {}
505 |
506 | Solver::Solver(const SolverParams& params) : params_(params) {}
507 |
508 | // Calculates partitions, and then solves each subproblem independently. If
509 | // any subproblem is found to be infeasible, no further search is performed.
510 | absl::StatusOr Solver::Solve(const Problem& problem) {
511 | backtracks_ = 0; // Reset the backtrack counter.
512 | cancelled_ = false;
513 | return SolveWithStartTime(problem, absl::Now());
514 | }
515 |
516 | absl::StatusOr Solver::SolveWithStartTime(const Problem& problem,
517 | absl::Time start_time) {
518 | const SweepResult sweep_result = Sweep(problem);
519 | SolverImpl solver_impl(
520 | params_, start_time, problem, sweep_result, &backtracks_, cancelled_);
521 | return solver_impl.Solve();
522 | }
523 |
524 | int64_t Solver::get_backtracks() const { return backtracks_; }
525 |
526 | void Solver::Cancel() { cancelled_ = true; }
527 |
528 | absl::StatusOr>
529 | Solver::ComputeIrreducibleInfeasibleSubset(const Problem& problem) {
530 | backtracks_ = 0; // Reset the backtrack counter.
531 | cancelled_ = false;
532 | const absl::Time start_time = absl::Now();
533 | std::vector include(problem.buffers.size(), true);
534 | std::vector subset;
535 | for (auto buffer_idx = 0; buffer_idx < problem.buffers.size(); ++buffer_idx) {
536 | include[buffer_idx] = false; // Try removing this buffer from the problem.
537 | Problem subproblem = {.capacity = problem.capacity};
538 | for (BufferIdx idx = 0; idx < problem.buffers.size(); ++idx) {
539 | if (include[idx]) subproblem.buffers.push_back(problem.buffers[idx]);
540 | }
541 | auto solution = SolveWithStartTime(subproblem, start_time);
542 | if (absl::IsDeadlineExceeded(solution.status())) return solution.status();
543 | if ((include[buffer_idx] = solution.ok())) subset.push_back(buffer_idx);
544 | }
545 | return subset;
546 | }
547 |
548 | } // namespace minimalloc
549 |
--------------------------------------------------------------------------------
/src/solver.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2023 Google LLC
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #ifndef MINIMALLOC_SRC_SOLVER_H_
18 | #define MINIMALLOC_SRC_SOLVER_H_
19 |
20 | #include
21 | #include
22 | #include
23 | #include
24 |
25 | #include "minimalloc.h"
26 | #include "absl/status/statusor.h"
27 | #include "absl/time/time.h"
28 |
29 | namespace minimalloc {
30 |
31 | using CanonicalOnlyParam = bool;
32 | using SectionInferenceParam = bool;
33 | using DynamicOrderingParam = bool;
34 | using CheckDominanceParam = bool;
35 | using UnallocatedFloorParam = bool;
36 | using StaticPreorderingParam = bool;
37 | using DynamicDecompositionParam = bool;
38 | using MonotonicFloorParam = bool;
39 | using HatlessPruningParam = bool;
40 | using PreorderingHeuristic = std::string;
41 |
42 | // Various settings that enable / disable certain advanced search & inference
43 | // techniques (for benchmarking) that are employed by the solver. Unless
44 | // directed otherwise, users should stick with these defaults.
45 | struct SolverParams {
46 | // The amount of time before the solver gives up on its search.
47 | absl::Duration timeout = absl::InfiniteDuration();
48 |
49 | // Requires that partial assignments conform to a "canonical" (i.e., non-
50 | // redundant) solution structure.
51 | CanonicalOnlyParam canonical_only = true;
52 |
53 | // Prunes any partial solutions in which the lower bound of some section
54 | // height eclipses the maximum memory capacity.
55 | SectionInferenceParam section_inference = true;
56 |
57 | // Prefer blocks with smaller viable offset values, using area to break ties.
58 | DynamicOrderingParam dynamic_ordering = true;
59 |
60 | // Prunes any partial solutions that result in some gap(s) where unallocated
61 | // buffers could be easily placed.
62 | CheckDominanceParam check_dominance = true;
63 |
64 | // Uses the minimum offset of unallocated buffers to establish stronger lower
65 | // bounds on each section's floor.
66 | UnallocatedFloorParam unallocated_floor = true;
67 |
68 | // Performs an initial sort by maximum section total, followed by area.
69 | StaticPreorderingParam static_preordering = true;
70 |
71 | // Performs dynamic temporal decomposition.
72 | DynamicDecompositionParam dynamic_decomposition = true;
73 |
74 | // Requires that the floor of the entire solution increase monotonically.
75 | MonotonicFloorParam monotonic_floor = true;
76 |
77 | // Prunes alternate solutions whenever a buffer has nothing overhead.
78 | HatlessPruningParam hatless_pruning = true;
79 |
80 | // The static preordering heuristics to attempt.
81 | std::vector preordering_heuristics =
82 | {"WAT", "TAW", "TWA"};
83 | };
84 |
85 | // Data used to help establish a static preordering of buffers.
86 | struct PreorderData {
87 | Area area; // The total area (i.e., space x time) consumed by this buffer.
88 | TimeValue lower; // When does the buffer start?
89 | uint64_t overlaps; // The number of pairwise overlaps with other buffers.
90 | int sections; // The number of sections spanned by this buffer.
91 | int64_t size; // The size of the buffer.
92 | int total; // The (maximum) total sum in any of this buffer's sections.
93 | TimeValue upper; // When does the buffer end?
94 | int64_t width; // The width of this buffer's lifespan.
95 | BufferIdx buffer_idx; // An index into a Problem's list of buffers.
96 | };
97 |
98 | class PreorderingComparator {
99 | public:
100 | explicit PreorderingComparator(const PreorderingHeuristic& h);
101 | bool operator()(const PreorderData& a, const PreorderData& b) const;
102 |
103 | private:
104 | PreorderingHeuristic preordering_heuristic_;
105 | };
106 |
107 | class Solver {
108 | public:
109 | Solver();
110 | virtual ~Solver() = default;
111 | explicit Solver(const SolverParams& params);
112 | absl::StatusOr Solve(const Problem& problem);
113 |
114 | // Returns the number of backtracks in the solver's latest invocation.
115 | int64_t get_backtracks() const;
116 |
117 | // Cancels search.
118 | void Cancel();
119 |
120 | // A naïve approach to compute an irreducible infeasible subset of buffers.
121 | absl::StatusOr> ComputeIrreducibleInfeasibleSubset(
122 | const Problem& problem);
123 |
124 | protected:
125 | virtual absl::StatusOr SolveWithStartTime(const Problem& problem,
126 | absl::Time start_time);
127 |
128 | const SolverParams params_;
129 | int64_t backtracks_ = 0; // A counter that maintains backtrack count.
130 | std::atomic cancelled_ = false;
131 | };
132 |
133 | } // namespace minimalloc
134 |
135 | #endif // MINIMALLOC_SRC_SOLVER_H_
136 |
--------------------------------------------------------------------------------
/src/sweeper.cc:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2023 Google LLC
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #include "sweeper.h"
18 |
19 | #include
20 | #include
21 | #include
22 | #include
23 |
24 | #include "absl/container/btree_set.h"
25 | #include "absl/container/flat_hash_set.h"
26 | #include "minimalloc.h"
27 |
28 | namespace minimalloc {
29 |
30 | bool SweepPoint::operator==(const SweepPoint& x) const {
31 | return buffer_idx == x.buffer_idx && time_value == x.time_value &&
32 | point_type == x.point_type && window == x.window &&
33 | endpoint == x.endpoint;
34 | }
35 |
36 | bool SweepPoint::operator<(const SweepPoint& x) const {
37 | // First, order by time, then direction (right vs. left), then buffer idx.
38 | if (time_value != x.time_value) return time_value < x.time_value;
39 | if (point_type != x.point_type) return point_type < x.point_type;
40 | return buffer_idx < x.buffer_idx;
41 | }
42 |
43 | bool SectionSpan::operator==(const SectionSpan& x) const {
44 | return section_range == x.section_range && window == x.window;
45 | }
46 |
47 | bool Partition::operator==(const Partition& x) const {
48 | return buffer_idxs == x.buffer_idxs &&
49 | section_range == x.section_range;
50 | }
51 |
52 | bool Overlap::operator==(const Overlap& x) const {
53 | return buffer_idx == x.buffer_idx && effective_size == x.effective_size;
54 | }
55 |
56 | bool Overlap::operator<(const Overlap& x) const {
57 | if (buffer_idx != x.buffer_idx) return buffer_idx < x.buffer_idx;
58 | return effective_size < x.effective_size;
59 | }
60 |
61 | bool BufferData::operator==(const BufferData& x) const {
62 | return section_spans == x.section_spans &&
63 | overlaps == x.overlaps;
64 | }
65 |
66 | bool SweepResult::operator==(const SweepResult& x) const {
67 | return sections == x.sections &&
68 | partitions == x.partitions &&
69 | buffer_data == x.buffer_data;
70 | }
71 |
72 | // For a given problem, places all start & end times into a list sorted by time
73 | // value, then point type, then buffer index. For a buffer with gaps, there are
74 | // six *potential* points of interest:
75 | //
76 | // A BC DE F
77 | // |-------|
78 | // |--------|| gap ||--------|
79 | // |-------|
80 | //
81 | // Point 'A' may not need to be created if it's co-occurrent with point 'B',
82 | // points 'C' and 'D' may not need to be created unless there's a window, etc.
83 | std::vector CreatePoints(const Problem& problem) {
84 | std::vector all_points;
85 | all_points.reserve(problem.buffers.size() * 2); // Reserve 2 spots per buffer
86 | for (auto buffer_idx = 0; buffer_idx < problem.buffers.size(); ++buffer_idx) {
87 | const Buffer& buffer = problem.buffers[buffer_idx];
88 | const Lifespan& lifespan = buffer.lifespan;
89 | const Window window = {0, buffer.size};
90 | std::deque points;
91 | absl::flat_hash_set leftTimes, rightTimes;
92 | // Insert left & right endpoints for all *windowed* gaps.
93 | for (const Gap& gap : buffer.gaps) {
94 | if (!gap.window) continue;
95 | points.push_back({buffer_idx, gap.lifespan.lower(), kLeft, *gap.window});
96 | points.push_back({buffer_idx, gap.lifespan.upper(), kRight, *gap.window});
97 | leftTimes.insert(gap.lifespan.lower());
98 | rightTimes.insert(gap.lifespan.upper());
99 | }
100 | // If needed, insert new points for the buffer's start & end times.
101 | if (points.empty() || points.front().time_value != lifespan.lower()) {
102 | points.push_front({buffer_idx, lifespan.lower(), kLeft, window});
103 | }
104 | if (points.empty() || points.back().time_value != lifespan.upper()) {
105 | points.push_back({buffer_idx, lifespan.upper(), kRight, window});
106 | }
107 | // Mark the endpoints.
108 | points.front().endpoint = points.back().endpoint = true;
109 | rightTimes.insert(lifespan.lower());
110 | leftTimes.insert(lifespan.upper());
111 | // Insert left & right endpoints for all *non-windowed* gaps.
112 | for (const Gap& gap : buffer.gaps) {
113 | if (gap.window) continue;
114 | if (!rightTimes.contains(gap.lifespan.lower())) {
115 | points.push_back({buffer_idx, gap.lifespan.lower(), kRight, window});
116 | rightTimes.insert(gap.lifespan.lower());
117 | }
118 | if (!leftTimes.contains(gap.lifespan.upper())) {
119 | points.push_back({buffer_idx, gap.lifespan.upper(), kLeft, window});
120 | leftTimes.insert(gap.lifespan.upper());
121 | }
122 | leftTimes.insert(gap.lifespan.lower());
123 | rightTimes.insert(gap.lifespan.upper());
124 | }
125 | // Insert left & right endpoints for any implicitly active buffer sections.
126 | for (const Gap& gap : buffer.gaps) {
127 | if (!rightTimes.contains(gap.lifespan.lower())) {
128 | points.push_back({buffer_idx, gap.lifespan.lower(), kRight, window});
129 | }
130 | if (!leftTimes.contains(gap.lifespan.upper())) {
131 | points.push_back({buffer_idx, gap.lifespan.upper(), kLeft, window});
132 | }
133 | }
134 | // Add these into the list of all points.
135 | all_points.insert(all_points.end(), points.begin(), points.end());
136 | }
137 | std::sort(all_points.begin(), all_points.end());
138 | return all_points;
139 | }
140 |
141 | SweepResult Sweep(const Problem& problem) {
142 | SweepResult result;
143 | const auto num_buffers = problem.buffers.size();
144 | const std::vector points = CreatePoints(problem);
145 | Section actives, alive;
146 | TimeValue last_section_time = -1;
147 | SectionIdx last_section_idx = 0;
148 | // Create a reverse index (from buffers to sections) for quick lookup.
149 | result.buffer_data.resize(num_buffers);
150 | std::vector buffer_idx_to_section_start(num_buffers, -1);
151 | for (const SweepPoint& point : points) {
152 | const BufferIdx buffer_idx = point.buffer_idx;
153 | const Buffer& buffer = problem.buffers[buffer_idx];
154 | if (last_section_time == -1) last_section_time = point.time_value;
155 | if (point.point_type == kRight) {
156 | // Create a new cross section of buffers if one doesn't yet exist.
157 | if (last_section_time < point.time_value) {
158 | last_section_time = point.time_value;
159 | result.sections.push_back(actives);
160 | }
161 | // If it's a right endpoint, remove it from the set of active buffers.
162 | actives.erase(buffer_idx);
163 | if (point.endpoint) alive.erase(buffer_idx);
164 | const SectionRange section_range =
165 | {buffer_idx_to_section_start[buffer_idx],
166 | (int)result.sections.size()};
167 | const SectionSpan section_span = {section_range, point.window};
168 | result.buffer_data[buffer_idx].section_spans.push_back(section_span);
169 | // If the alives are empty, the span of this partition is now known.
170 | if (alive.empty()) {
171 | result.partitions.back().section_range =
172 | {last_section_idx, (int)result.sections.size()};
173 | last_section_idx = result.sections.size();
174 | }
175 | }
176 | if (point.point_type == kLeft) {
177 | // If it's a left endpoint, check if a new partition should be established
178 | if (alive.empty()) result.partitions.push_back(Partition());
179 | // Record any overlaps, and then add this buffer to the set of actives.
180 | if (point.endpoint) {
181 | result.partitions.back().buffer_idxs.push_back(buffer_idx);
182 | for (auto alive_idx : alive) {
183 | const Buffer& alive = problem.buffers[alive_idx];
184 | auto alive_effective_size = alive.effective_size(buffer);
185 | if (alive_effective_size) {
186 | result.buffer_data[alive_idx].overlaps.insert(
187 | {buffer_idx, *alive_effective_size});
188 | }
189 | auto effective_size = buffer.effective_size(alive);
190 | if (effective_size) {
191 | result.buffer_data[buffer_idx].overlaps.insert({alive_idx,
192 | *effective_size});
193 | }
194 | }
195 | }
196 | actives.insert(buffer_idx);
197 | // Mutants OK for following line; performance tweak to prevent reinsertion
198 | if (point.endpoint) alive.insert(buffer_idx);
199 | buffer_idx_to_section_start[buffer_idx] = result.sections.size();
200 | }
201 | }
202 | return result;
203 | }
204 |
205 | // Calculates the number of "cuts," i.e., buffers that are active between
206 | // adjacent sections. If there are zero cuts between sections i and i+1, it
207 | // implies that the sections {..., i-2, i-1, i} and {i+1, i+2, ...} may be
208 | // solved separately.
209 | std::vector SweepResult::CalculateCuts() const {
210 | std::vector cuts(sections.size() - 1);
211 | for (const BufferData& buffer_data : buffer_data) {
212 | const std::vector& section_spans = buffer_data.section_spans;
213 | for (SectionIdx s_idx = section_spans.front().section_range.lower();
214 | s_idx + 1 < section_spans.back().section_range.upper(); ++s_idx) {
215 | ++cuts[s_idx];
216 | }
217 | }
218 | return cuts;
219 | }
220 |
221 | } // namespace minimalloc
222 |
--------------------------------------------------------------------------------
/src/sweeper.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2023 Google LLC
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #ifndef MINIMALLOC_SRC_SWEEPER_H_
18 | #define MINIMALLOC_SRC_SWEEPER_H_
19 |
20 | #include
21 |
22 | #include "minimalloc.h"
23 | #include "absl/container/btree_set.h"
24 | #include "absl/container/flat_hash_set.h"
25 |
26 | namespace minimalloc {
27 |
28 | // An index into a list of schedule "cross sections."
29 | using SectionIdx = int;
30 |
31 | // A count of buffers crossing between adjacent sections.
32 | using CutCount = int;
33 |
34 | // An interval that defines a subset of ranges (e.g., where a buffer is
35 | // continuously active).
36 | using SectionRange = Interval;
37 |
38 | // Defines a range that a buffer is active and its window during this interval.
39 | struct SectionSpan {
40 | SectionRange section_range;
41 | Window window;
42 | bool operator==(const SectionSpan& x) const;
43 | };
44 |
45 | // Sections store subsets of buffers that interact with one another at some
46 | // point in time. As an example, consider the following problem:
47 | //
48 | // Buffer buffer_0 = {.lifespan = [1, 2)};
49 | // Buffer buffer_1 = {.lifespan = [2, 4)};
50 | // Buffer buffer_2 = {.lifespan = [0, 5)};
51 | // Buffer buffer_3 = {.lifespan = [5, 9)};
52 | // Problem problem = {.buffers = {buffer_0, buffer_1, buffer_2, buffer_3}};
53 | //
54 | // Here is a visualization of these four buffers:
55 | //
56 | // t=0 t=1 t=2 t=3 t=4 t=5 t=6 t=7 t=8 t=9
57 | // |======|======|======|======|======|======|======|======|======|
58 | // offset=3 |XXXXXX| b0 |XXXXXX|XXXXXX|XXXXXX|XXXXXX|XXXXXX|XXXXXX|XXXXXX|
59 | // |------|------|------|------|------|------|------|------|------|
60 | // offset=2 |XXXXXX|XXXXXX| b1 |XXXXXX|XXXXXX|XXXXXX|XXXXXX|XXXXXX|
61 | // |------|------|------|------|------|------|------|------|------|
62 | // offset=1 | b2 |XXXXXX|XXXXXX|XXXXXX|XXXXXX|
63 | // |------|------|------|------|------|------|------|------|------|
64 | // offset=0 |XXXXXX|XXXXXX|XXXXXX|XXXXXX|XXXXXX| b3 |
65 | // |======|======|======|======|======|======|======|======|======|
66 | //
67 | // Buffers 0 and 2 interact with one another from t=0 to t=2, forming our first
68 | // section. From t=2 to t=4, buffers 1 and 2 are both active. A total of four
69 | // sections result from these interactions:
70 | //
71 | // |======|======|======|======|======|======|======|======|======|
72 | // sections: | sec0 | sec1 | sec2 | sec3 |
73 | // |======|======|======|======|======|======|======|======|======|
74 |
75 | using Section = absl::flat_hash_set;
76 |
77 | // Partitions store various preprocessed attributes for a subset of a Problem's
78 | // buffers. Partitions are mutually exclusive -- that is, any buffer belongs to
79 | // exactly one partition -- and they are guaranteed not to overlap in time (so
80 | // may be solved independently). In our example, buffer 3 never interacts with
81 | // the others, and so a total of two partitions are created:
82 | //
83 | // |======|======|======|======|======|======|======|======|======|
84 | // partitions: | p0 | p1 |
85 | // |======|======|======|======|======|======|======|======|======|
86 | //
87 | // Here is how these relationships are expressed in the Partition objects:
88 | //
89 | // Partition partition_a = {
90 | // .buffer_idxs = {0, 1, 2},
91 | // .section_range = {0, 3}, // <---- up to (but not including) section 3
92 | // };
93 | // Partition partition_b = {
94 | // .buffer_idxs = {3},
95 | // .section_range = {3, 4}, // <---- up to (but not including) section 4
96 | // };
97 |
98 | struct Partition {
99 | // The buffers participating in this partition (indexes into problem.buffers).
100 | std::vector buffer_idxs;
101 |
102 | // A half-open interval specifying which sections this partition spans.
103 | SectionRange section_range;
104 |
105 | bool operator==(const Partition& x) const;
106 | };
107 |
108 | // Details regarding a buffer that overlaps with another.
109 | struct Overlap {
110 | BufferIdx buffer_idx = -1;
111 | int64_t effective_size = 0;
112 |
113 | bool operator==(const Overlap& x) const;
114 | bool operator<(const Overlap& x) const;
115 | };
116 |
117 | // The BufferData object stores various preprocessed attributes of an individual
118 | // buffer (i.e., its relationships with sections and any overlapping buffers).
119 | // Given the above example, buffer 2 is active from section 0 up to (but not
120 | // including) section 3. Likewise, it overlaps in time with two other buffers
121 | // (0 and 1). Hence, its buffer data would be as follows:
122 | //
123 | // BufferData buffer_data_0 = {
124 | // .section_spans = {{.section_range = {0, 3}, .size = 1},
125 | // .overlaps = {0, 1}
126 | // };
127 |
128 | struct BufferData {
129 | // Half-open intervals specifying an exhaustive list of sections that this
130 | // buffer participates in. Note: just because a buffer is live during a
131 | // given section does not necessarily mean it is live for the full duration.
132 | std::vector section_spans;
133 |
134 | // Contains a set of buffers that overlap at some point in time with this one.
135 | absl::btree_set overlaps;
136 |
137 | bool operator==(const BufferData& x) const;
138 | };
139 |
140 | // The SweepResult object encapsulates all of the data above. Its primary
141 | // client is the Solver, which uses these indices when propagating offset
142 | // updates during its recursive depth-first search.
143 |
144 | struct SweepResult {
145 | // Cross sections of buffers that are "active" at particular moments in the
146 | // schedule.
147 | std::vector sections;
148 |
149 | // The list of (mutually-exclusive) partitions over a problem's buffers.
150 | std::vector partitions;
151 |
152 | // Maps each buffer to various properties (e.g, sections & pairwise overlaps).
153 | std::vector buffer_data;
154 |
155 | // Returns a vector of length sections.size() - 1 where the ith element is the
156 | // number of buffers that are active in both section i and section i + 1.
157 | std::vector CalculateCuts() const;
158 |
159 | bool operator==(const SweepResult& x) const;
160 | };
161 |
162 | enum SweepPointType { kRight, kLeft };
163 |
164 | struct SweepPoint {
165 | BufferIdx buffer_idx;
166 | TimeValue time_value;
167 | SweepPointType point_type;
168 | Window window;
169 | bool endpoint = false;
170 | bool operator==(const SweepPoint& x) const;
171 | bool operator<(const SweepPoint& x) const;
172 | };
173 |
174 | // For a given problem, places all start & end times into a list sorted by time
175 | // value, then point type, then buffer index.
176 | std::vector CreatePoints(const Problem& problem);
177 |
178 | // Maintains an "active" set of buffers to determine disjoint partitions. For
179 | // each partition, records the list of buffers + pairwise overlaps + unique
180 | // cross sections.
181 | SweepResult Sweep(const Problem& problem);
182 |
183 | } // namespace minimalloc
184 |
185 | #endif // MINIMALLOC_SRC_SWEEPER_H_
186 |
--------------------------------------------------------------------------------
/src/validator.cc:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2023 Google LLC
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #include "validator.h"
18 |
19 | #include
20 | #include
21 |
22 | #include "minimalloc.h"
23 |
24 | namespace minimalloc {
25 |
26 | ValidationResult Validate(const Problem& problem, const Solution& solution) {
27 | // Check that the number of buffers matches the number of offsets.
28 | if (problem.buffers.size() != solution.offsets.size()) return kBadSolution;
29 | // Check fixed buffers & check that offsets are within the allowable range.
30 | for (auto buffer_idx = 0; buffer_idx < problem.buffers.size(); ++buffer_idx) {
31 | const Buffer& buffer = problem.buffers[buffer_idx];
32 | const Offset offset = solution.offsets[buffer_idx];
33 | if (buffer.offset && *buffer.offset != offset) return kBadFixed;
34 | if (offset < 0) return kBadOffset;
35 | if (offset + buffer.size > problem.capacity) return kBadOffset;
36 | if (offset % buffer.alignment != 0) return kBadAlignment;
37 | }
38 | // Check that no two buffers overlap in both space and time, the O(n^2) way.
39 | for (BufferIdx i = 0; i < problem.buffers.size(); ++i) {
40 | const Buffer& buffer_i = problem.buffers[i];
41 | const Offset offset_i = solution.offsets[i];
42 | for (BufferIdx j = i + 1; j < problem.buffers.size(); ++j) {
43 | const Buffer& buffer_j = problem.buffers[j];
44 | const Offset offset_j = solution.offsets[j];
45 | const auto buffer_i_size = buffer_i.effective_size(buffer_j);
46 | const auto buffer_j_size = buffer_j.effective_size(buffer_i);
47 | if (!buffer_i_size || offset_i + *buffer_i_size <= offset_j) continue;
48 | if (!buffer_j_size || offset_j + *buffer_j_size <= offset_i) continue;
49 | return kBadOverlap;
50 | }
51 | }
52 | return kGood;
53 | }
54 |
55 | } // namespace minimalloc
56 |
--------------------------------------------------------------------------------
/src/validator.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2023 Google LLC
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #ifndef MINIMALLOC_SRC_VALIDATOR_H_
18 | #define MINIMALLOC_SRC_VALIDATOR_H_
19 |
20 | #include "minimalloc.h"
21 | #include "absl/base/attributes.h"
22 |
23 | namespace minimalloc {
24 |
25 | enum ValidationResult {
26 | kGood = 0,
27 | kBadSolution = 1, // Solution structure is incorrect, eg. wrong # of offsets.
28 | kBadFixed = 2, // A buffer w/ a fixed offset is assigned somewhere else.
29 | kBadOffset = 3, // The offset is out-of-bounds, ie. negative or beyond cap.
30 | kBadOverlap = 4, // At least one pair of buffers overlaps in space and time.
31 | kBadAlignment = 5 // At least one buffer was not properly aligned.
32 | };
33 |
34 | ValidationResult Validate(
35 | const Problem& problem, const Solution& solution) ABSL_MUST_USE_RESULT;
36 |
37 | } // namespace minimalloc
38 |
39 | #endif // MINIMALLOC_SRC_VALIDATOR_H_
40 |
--------------------------------------------------------------------------------
/tests/converter_test.cc:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2023 Google LLC
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #include "../src/converter.h"
18 |
19 | #include "../src/minimalloc.h"
20 | #include "gmock/gmock.h"
21 | #include "gtest/gtest.h"
22 | #include "absl/status/status.h"
23 |
24 | namespace minimalloc {
25 | namespace {
26 |
27 | TEST(ConverterTest, ToCsv) {
28 | EXPECT_EQ(
29 | ToCsv({
30 | .buffers = {
31 | {.id = "0", .lifespan = {5, 10}, .size = 15, .hint = 0},
32 | {
33 | .id = "1",
34 | .lifespan = {6, 12},
35 | .size = 18,
36 | .alignment = 2,
37 | .gaps = {{.lifespan = {7, 8}},
38 | {.lifespan = {9, 10}, .window = {{1, 17}}}}
39 | },
40 | },
41 | .capacity = 40
42 | }),
43 | "id,lower,upper,size,alignment,hint,gaps\n"
44 | "0,5,10,15,1,0,\n1,6,12,18,2,-1,7-8 9-10@1:17\n");
45 | }
46 |
47 | TEST(ConverterTest, ToCsvWithoutAlignment) {
48 | EXPECT_EQ(
49 | ToCsv({
50 | .buffers = {
51 | {.id = "0", .lifespan = {5, 10}, .size = 15, .hint = 0},
52 | {
53 | .id = "1",
54 | .lifespan = {6, 12},
55 | .size = 18,
56 | .gaps = {{.lifespan = {7, 8}}, {.lifespan = {9, 10}}}
57 | },
58 | },
59 | .capacity = 40
60 | }),
61 | "id,lower,upper,size,hint,gaps\n"
62 | "0,5,10,15,0,\n1,6,12,18,-1,7-8 9-10\n");
63 | }
64 |
65 | TEST(ConverterTest, ToCsvWithoutHint) {
66 | EXPECT_EQ(
67 | ToCsv({
68 | .buffers = {
69 | {.id = "0", .lifespan = {5, 10}, .size = 15},
70 | {
71 | .id = "1",
72 | .lifespan = {6, 12},
73 | .size = 18,
74 | .alignment = 2,
75 | .gaps = {{.lifespan = {7, 8}},
76 | {.lifespan = {9, 10}, .window = {{1, 17}}}}
77 | },
78 | },
79 | .capacity = 40
80 | }),
81 | "id,lower,upper,size,alignment,gaps\n"
82 | "0,5,10,15,1,\n1,6,12,18,2,7-8 9-10@1:17\n");
83 | }
84 |
85 | TEST(ConverterTest, ToCsvWithoutGaps) {
86 | EXPECT_EQ(
87 | ToCsv({
88 | .buffers = {
89 | {.id = "0", .lifespan = {5, 10}, .size = 15, .hint = 0},
90 | {
91 | .id = "1",
92 | .lifespan = {6, 12},
93 | .size = 18,
94 | .alignment = 2,
95 | },
96 | },
97 | .capacity = 40
98 | }),
99 | "id,lower,upper,size,alignment,hint\n"
100 | "0,5,10,15,1,0\n1,6,12,18,2,-1\n");
101 | }
102 |
103 | TEST(ConverterTest, ToCsvWithSolution) {
104 | Solution solution = {.offsets = {1, 21}};
105 | EXPECT_EQ(
106 | ToCsv({
107 | .buffers = {
108 | {.id = "0", .lifespan = {5, 10}, .size = 15},
109 | {
110 | .id = "1",
111 | .lifespan = {6, 12},
112 | .size = 18,
113 | .alignment = 2,
114 | .gaps = {{.lifespan = {7, 8}}, {.lifespan = {9, 10}}}
115 | },
116 | },
117 | .capacity = 40
118 | },
119 | &solution),
120 | "id,lower,upper,size,alignment,gaps,offset\n"
121 | "0,5,10,15,1,,1\n1,6,12,18,2,7-8 9-10,21\n");
122 | }
123 |
124 | TEST(ConverterTest, ToCsvWeirdIDs) {
125 | EXPECT_EQ(
126 | ToCsv({
127 | .buffers = {
128 | {.id = "10", .lifespan = {5, 10}, .size = 15},
129 | {
130 | .id = "20",
131 | .lifespan = {6, 12},
132 | .size = 18,
133 | .alignment = 2,
134 | .gaps = {{.lifespan = {7, 8}}, {.lifespan = {9, 10}}}
135 | },
136 | },
137 | .capacity = 40
138 | }),
139 | "id,lower,upper,size,alignment,gaps\n"
140 | "10,5,10,15,1,\n20,6,12,18,2,7-8 9-10\n");
141 | }
142 |
143 | TEST(ConverterTest, ToCsvStringIDs) {
144 | EXPECT_EQ(
145 | ToCsv({
146 | .buffers = {
147 | {.id = "Little", .lifespan = {5, 10}, .size = 15},
148 | {
149 | .id = "Big",
150 | .lifespan = {6, 12},
151 | .size = 18,
152 | .alignment = 2,
153 | .gaps = {{.lifespan = {7, 8}}, {.lifespan = {9, 10}}}
154 | },
155 | },
156 | .capacity = 40
157 | }),
158 | "id,lower,upper,size,alignment,gaps\n"
159 | "Little,5,10,15,1,\nBig,6,12,18,2,7-8 9-10\n");
160 | }
161 |
162 | TEST(ConverterTest, ToCsvOldFormat) {
163 | EXPECT_EQ(
164 | ToCsv({
165 | .buffers = {
166 | {.id = "Little", .lifespan = {5, 10}, .size = 15},
167 | {
168 | .id = "Big",
169 | .lifespan = {6, 12},
170 | .size = 18,
171 | .alignment = 2,
172 | .gaps = {{.lifespan = {7, 8}}, {.lifespan = {9, 10}}}
173 | },
174 | },
175 | .capacity = 40
176 | }, nullptr, true),
177 | "id,start,end,size,alignment,gaps\n"
178 | "Little,5,9,15,1,\nBig,6,11,18,2,7-7 9-9\n");
179 | }
180 |
181 | TEST(ConverterTest, FromCsvProblemOnly) {
182 | EXPECT_EQ(
183 | *FromCsv("lower,size,id,upper\n6,18,1,12\n5,15,0,10\n"),
184 | (Problem{
185 | .buffers = {
186 | {.id = "1", .lifespan = {6, 12}, .size = 18},
187 | {.id = "0", .lifespan = {5, 10}, .size = 15},
188 | },
189 | }));
190 | }
191 |
192 | TEST(ConverterTest, FromCsvWithAlignment) {
193 | EXPECT_THAT(
194 | *FromCsv("begin,size,buffer,upper,alignment\n6,18,1,12,2\n5,15,0,10,1\n"),
195 | (Problem{
196 | .buffers = {
197 | {.id = "1", .lifespan = {6, 12}, .size = 18, .alignment = 2},
198 | {.id = "0", .lifespan = {5, 10}, .size = 15, .alignment = 1},
199 | },
200 | }));
201 | }
202 |
203 | TEST(ConverterTest, FromCsvWithHints) {
204 | EXPECT_THAT(
205 | *FromCsv("begin,size,buffer,upper,alignment,hint\n"
206 | "6,18,1,12,2,0\n5,15,0,10,1,-1\n"),
207 | (Problem{
208 | .buffers = {
209 | {
210 | .id = "1",
211 | .lifespan = {6, 12},
212 | .size = 18,
213 | .alignment = 2,
214 | .hint = 0
215 | },
216 | {.id = "0", .lifespan = {5, 10}, .size = 15, .alignment = 1},
217 | },
218 | }));
219 | }
220 |
221 | TEST(ConverterTest, FromCsvWithEmptyGaps) {
222 | EXPECT_THAT(
223 | *FromCsv("start,size,buffer_id,upper,alignment,gaps\n"
224 | "6,18,1,12,2,\n5,15,0,10,1,\n"),
225 | (Problem{
226 | .buffers = {
227 | {.id = "1", .lifespan = {6, 12}, .size = 18, .alignment = 2},
228 | {.id = "0", .lifespan = {5, 10}, .size = 15, .alignment = 1},
229 | },
230 | }));
231 | }
232 |
233 | TEST(ConverterTest, FromCsvWithGaps) {
234 | EXPECT_THAT(
235 | *FromCsv("start,size,buffer,upper,alignment,gaps\n"
236 | "6,18,1,12,2,7-9 \n5,15,0,10,1,9-11 12-14@2:13\n"),
237 | (Problem{
238 | .buffers = {
239 | {
240 | .id = "1",
241 | .lifespan = {6, 12},
242 | .size = 18,
243 | .alignment = 2,
244 | .gaps = {{.lifespan = {7, 9}}}
245 | },
246 | {
247 | .id = "0",
248 | .lifespan = {5, 10},
249 | .size = 15,
250 | .alignment = 1,
251 | .gaps = {{.lifespan = {9, 11}},
252 | {.lifespan = {12, 14}, .window = {{2, 13}}}}
253 | },
254 | },
255 | }));
256 | }
257 |
258 | TEST(ConverterTest, FromCsvWithEndColumn) {
259 | EXPECT_THAT(
260 | *FromCsv("start,size,buffer,end,alignment,gaps\n"
261 | "6,18,1,11,2,7-8 \n5,15,0,9,1,9-10 12-13\n"),
262 | (Problem{
263 | .buffers = {
264 | {
265 | .id = "1",
266 | .lifespan = {6, 12},
267 | .size = 18,
268 | .alignment = 2,
269 | .gaps = {{.lifespan = {7, 9}}}
270 | },
271 | {
272 | .id = "0",
273 | .lifespan = {5, 10},
274 | .size = 15,
275 | .alignment = 1,
276 | .gaps = {{.lifespan = {9, 11}}, {.lifespan = {12, 14}}}
277 | },
278 | },
279 | }));
280 | }
281 |
282 | TEST(ConverterTest, FromCsvWithSolution) {
283 | EXPECT_THAT(
284 | *FromCsv("start,size,offset,buffer,upper\n6,18,21,1,12\n5,15,1,0,10\n"),
285 | (Problem{
286 | .buffers = {
287 | {.id = "1", .lifespan = {6, 12}, .size = 18, .offset = 21},
288 | {.id = "0", .lifespan = {5, 10}, .size = 15, .offset = 1},
289 | },
290 | }));
291 | }
292 |
293 | TEST(ConverterTest, FromCsvBufferId) {
294 | EXPECT_THAT(
295 | *FromCsv("start,size,buffer_id,upper\n6,18,1,12\n5,15,0,10\n"),
296 | (Problem{
297 | .buffers = {
298 | {.id = "1", .lifespan = {6, 12}, .size = 18},
299 | {.id = "0", .lifespan = {5, 10}, .size = 15},
300 | },
301 | }));
302 | }
303 |
304 | TEST(ConverterTest, FromCsvWeirdIDs) {
305 | EXPECT_THAT(
306 | *FromCsv("start,size,buffer,upper\n6,18,20,12\n5,15,10,10\n"),
307 | (Problem{
308 | .buffers = {
309 | {.id = "20", .lifespan = {6, 12}, .size = 18},
310 | {.id = "10", .lifespan = {5, 10}, .size = 15},
311 | },
312 | }));
313 | }
314 |
315 | TEST(ConverterTest, FromCsvStringIDs) {
316 | EXPECT_THAT(
317 | *FromCsv("start,size,buffer,upper\n6,18,Big,12\n5,15,Little,10\n"),
318 | (Problem{
319 | .buffers = {
320 | {.id = "Big", .lifespan = {6, 12}, .size = 18},
321 | {.id = "Little", .lifespan = {5, 10}, .size = 15},
322 | },
323 | }));
324 | }
325 |
326 | TEST(ConverterTest, BogusInputs) {
327 | EXPECT_EQ(
328 | FromCsv("start,size,buffer,upper\n"
329 | "a,b,c,d\ne,f,g,h\n").status().code(),
330 | absl::StatusCode::kInvalidArgument);
331 | }
332 |
333 | TEST(ConverterTest, BogusOffsets) {
334 | EXPECT_EQ(
335 | FromCsv("start,size,offset,buffer,upper\n"
336 | "6,18,a,1,12\n5,15,b,0,10\n").status().code(),
337 | absl::StatusCode::kInvalidArgument);
338 | }
339 |
340 | TEST(ConverterTest, BogusGaps) {
341 | EXPECT_EQ(
342 | FromCsv("start,size,buffer,upper,gaps\n"
343 | "6,18,1,12,1-2-3\n5,15,0,10,\n").status().code(),
344 | absl::StatusCode::kInvalidArgument);
345 | }
346 |
347 | TEST(ConverterTest, MoreBogusGaps) {
348 | EXPECT_EQ(
349 | FromCsv("start,size,buffer,upper,gaps\n"
350 | "6,18,1,12,A-B\n5,15,0,10,\n").status().code(),
351 | absl::StatusCode::kInvalidArgument);
352 | }
353 |
354 | TEST(ConverterTest, MissingColumn) {
355 | EXPECT_EQ(
356 | FromCsv("start,size,upper\n"
357 | "6,18,1,12\n5,15,10\n").status().code(),
358 | absl::StatusCode::kNotFound);
359 | }
360 |
361 | TEST(ConverterTest, DuplicateColumn) {
362 | EXPECT_EQ(
363 | FromCsv("start,size,offset,buffer,upper,upper\n"
364 | "6,18,21,1,12\n5,15,1,0,10\n").status().code(),
365 | absl::StatusCode::kInvalidArgument);
366 | }
367 |
368 | TEST(ConverterTest, ExtraFields) {
369 | EXPECT_EQ(
370 | FromCsv("start,size,offset,buffer,upper\n"
371 | "6,18,21,1,12\n5,15,1,0,10,100\n").status().code(),
372 | absl::StatusCode::kInvalidArgument);
373 | }
374 |
375 | } // namespace
376 | } // namespace minimalloc
377 |
--------------------------------------------------------------------------------
/tests/minimalloc_test.cc:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2023 Google LLC
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #include "../src/minimalloc.h"
18 |
19 | #include
20 |
21 | #include "gtest/gtest.h"
22 | #include "absl/status/status.h"
23 | #include "absl/status/statusor.h"
24 |
25 | namespace minimalloc {
26 | namespace {
27 |
28 | TEST(BufferTest, EffectiveSizeWithOverlap) {
29 | const Buffer bufferA = {.lifespan = {0, 2}, .size = 4};
30 | const Buffer bufferB = {.lifespan = {1, 3}, .size = 5};
31 | EXPECT_EQ(bufferA.effective_size(bufferB), 4);
32 | EXPECT_EQ(bufferB.effective_size(bufferA), 5);
33 | }
34 |
35 | TEST(BufferTest, EffectiveSizeWithoutOverlap) {
36 | const Buffer bufferA = {.lifespan = {0, 2}, .size = 4};
37 | const Buffer bufferB = {.lifespan = {3, 5}, .size = 5};
38 | EXPECT_EQ(bufferA.effective_size(bufferB), std::nullopt);
39 | EXPECT_EQ(bufferB.effective_size(bufferA), std::nullopt);
40 | }
41 |
42 | TEST(BufferTest, EffectiveSizeWithoutOverlapEdgeCase) {
43 | const Buffer bufferA = {.lifespan = {0, 2}, .size = 4};
44 | const Buffer bufferB = {.lifespan = {2, 4}, .size = 5};
45 | EXPECT_EQ(bufferA.effective_size(bufferB), std::nullopt);
46 | EXPECT_EQ(bufferB.effective_size(bufferA), std::nullopt);
47 | }
48 |
49 | TEST(BufferTest, EffectiveSizeGapsWithOverlap) {
50 | const Buffer bufferA = {.lifespan = {0, 10},
51 | .size = 4,
52 | .gaps = {{.lifespan = {1, 4}},
53 | {.lifespan = {6, 9}}}};
54 | const Buffer bufferB = {.lifespan = {5, 15},
55 | .size = 5,
56 | .gaps = {{.lifespan = {6, 9}},
57 | {.lifespan = {11, 14}}}};
58 | EXPECT_EQ(bufferA.effective_size(bufferB), 4);
59 | EXPECT_EQ(bufferB.effective_size(bufferA), 5);
60 | }
61 |
62 | TEST(BufferTest, EffectiveSizeGapsWithoutOverlap) {
63 | const Buffer bufferA = {.lifespan = {0, 10},
64 | .size = 4,
65 | .gaps = {{.lifespan = {1, 9}}}};
66 | const Buffer bufferB = {.lifespan = {5, 15},
67 | .size = 5,
68 | .gaps = {{.lifespan = {6, 14}}}};
69 | EXPECT_EQ(bufferA.effective_size(bufferB), std::nullopt);
70 | EXPECT_EQ(bufferB.effective_size(bufferA), std::nullopt);
71 | }
72 |
73 | TEST(BufferTest, EffectiveSizeGapsWithoutOverlapEdgeCaseFirst) {
74 | const Buffer bufferA = {.lifespan = {0, 10}, .size = 4};
75 | const Buffer bufferB = {.lifespan = {5, 15},
76 | .size = 5,
77 | .gaps = {{.lifespan = {5, 10}}}};
78 | EXPECT_EQ(bufferA.effective_size(bufferB), std::nullopt);
79 | EXPECT_EQ(bufferB.effective_size(bufferA), std::nullopt);
80 | }
81 |
82 | TEST(BufferTest, EffectiveSizeGapsWithoutOverlapEdgeCaseSecond) {
83 | const Buffer bufferA = {.lifespan = {0, 10},
84 | .size = 4,
85 | .gaps = {{.lifespan = {5, 10}}}};
86 | const Buffer bufferB = {.lifespan = {5, 15}, .size = 5};
87 | EXPECT_EQ(bufferA.effective_size(bufferB), std::nullopt);
88 | EXPECT_EQ(bufferB.effective_size(bufferA), std::nullopt);
89 | }
90 |
91 | TEST(BufferTest, EffectiveSizeTetris) {
92 | const Buffer bufferA = {.lifespan = {0, 10},
93 | .size = 2,
94 | .gaps = {{.lifespan = {0, 5}, .window = {{0, 1}}}}};
95 | const Buffer bufferB = {.lifespan = {0, 10},
96 | .size = 2,
97 | .gaps = {{.lifespan = {5, 10}, .window = {{1, 2}}}}};
98 | EXPECT_EQ(bufferA.effective_size(bufferB), 1);
99 | }
100 |
101 | TEST(BufferTest, EffectiveSizeStairs) {
102 | const Buffer bufferA = {.lifespan = {0, 15},
103 | .size = 3,
104 | .gaps = {{.lifespan = {0, 5}, .window = {{0, 1}}},
105 | {.lifespan = {5, 10}, .window = {{0, 2}}}}};
106 | const Buffer bufferB = {.lifespan = {0, 15},
107 | .size = 3,
108 | .gaps = {{.lifespan = {5, 10}, .window = {{1, 3}}},
109 | {.lifespan = {10, 15}, .window = {{2, 3}}}}};
110 | EXPECT_EQ(bufferA.effective_size(bufferB), 1);
111 | }
112 |
113 | TEST(ProblemTest, StripSolutionOk) {
114 | Problem problem = {
115 | .buffers = {
116 | {.lifespan = {0, 1}, .size = 2, .offset = 3},
117 | {.lifespan = {1, 2}, .size = 3, .offset = 4},
118 | },
119 | .capacity = 5
120 | };
121 | const auto solution = problem.strip_solution();
122 | EXPECT_EQ(solution.status().code(), absl::StatusCode::kOk);
123 | EXPECT_EQ(*solution, (Solution{.offsets = {3, 4}}));
124 | }
125 |
126 | TEST(ProblemTest, StripSolutionNotFound) {
127 | Problem problem = {
128 | .buffers = {
129 | {.lifespan = {0, 1}, .size = 2, .offset = 3},
130 | {.lifespan = {1, 2}, .size = 3},
131 | },
132 | .capacity = 5
133 | };
134 | const auto solution = problem.strip_solution();
135 | EXPECT_EQ(solution.status().code(), absl::StatusCode::kNotFound);
136 | }
137 |
138 | } // namespace
139 | } // namespace minimalloc
140 |
--------------------------------------------------------------------------------
/tests/solver_test.cc:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2023 Google LLC
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #include "../src/solver.h"
18 |
19 | #include
20 | #include
21 | #include
22 |
23 | #include "../src/minimalloc.h"
24 | #include "gmock/gmock.h"
25 | #include "gtest/gtest.h"
26 | #include "absl/status/status.h"
27 | #include "absl/status/statusor.h"
28 | #include "absl/time/time.h"
29 |
30 | namespace minimalloc {
31 | namespace {
32 |
33 | TEST(PreorderingComparator, ComparesCorrectly) {
34 | PreorderData data_a = {.area = 1, .total = 3, .width = 2, .buffer_idx = 0};
35 | PreorderData data_b = {.area = 0, .total = 4, .width = 1, .buffer_idx = 0};
36 | PreorderData data_c = {.area = 0, .total = 3, .width = 3, .buffer_idx = 0};
37 | PreorderData data_d = {.area = 2, .total = 3, .width = 2, .buffer_idx = 0};
38 | PreorderData data_e = {.area = 1, .total = 3, .width = 2, .buffer_idx = 1};
39 | PreorderingComparator preordering_comparator("TWA");
40 | EXPECT_TRUE(preordering_comparator(data_b, data_a));
41 | EXPECT_TRUE(preordering_comparator(data_c, data_a));
42 | EXPECT_TRUE(preordering_comparator(data_d, data_a));
43 | EXPECT_TRUE(preordering_comparator(data_a, data_e));
44 | }
45 |
46 | SolverParams getDisabledParams() {
47 | return {
48 | .canonical_only = false,
49 | .section_inference = false,
50 | .dynamic_ordering = false,
51 | .check_dominance = false,
52 | .unallocated_floor = false,
53 | .static_preordering = false,
54 | .dynamic_decomposition = false,
55 | .monotonic_floor = false,
56 | .hatless_pruning = false,
57 | .preordering_heuristics = {"TWA"},
58 | };
59 | }
60 |
61 | // Checks that the solver produces the expected result for each possible
62 | // combination of parameters.
63 | class SolverTest
64 | : public ::testing::TestWithParam> {
68 | protected:
69 | void test_feasible(const Problem& problem) {
70 | Solver solver(getParams());
71 | const auto solution = solver.Solve(problem);
72 | EXPECT_EQ(solution.status().code(), absl::StatusCode::kOk);
73 | }
74 |
75 | void test_infeasible(const Problem& problem) {
76 | Solver solver(getParams());
77 | const auto solution = solver.Solve(problem);
78 | EXPECT_EQ(solution.status().code(), absl::StatusCode::kNotFound);
79 | EXPECT_GT(solver.get_backtracks(), 0);
80 | }
81 |
82 | SolverParams getParams(
83 | absl::Duration timeout = absl::InfiniteDuration()) {
84 | return SolverParams{
85 | .timeout = timeout,
86 | .canonical_only = std::get<0>(GetParam()),
87 | .section_inference = std::get<1>(GetParam()),
88 | .dynamic_ordering = std::get<2>(GetParam()),
89 | .check_dominance = std::get<3>(GetParam()),
90 | .unallocated_floor = std::get<4>(GetParam()),
91 | .static_preordering = std::get<5>(GetParam()),
92 | .dynamic_decomposition = std::get<6>(GetParam()),
93 | .monotonic_floor = std::get<7>(GetParam()),
94 | .hatless_pruning = false,
95 | };
96 | }
97 | };
98 |
99 | INSTANTIATE_TEST_SUITE_P(
100 | SolverTest, SolverTest,
101 | ::testing::Combine(::testing::Bool(), ::testing::Bool(), ::testing::Bool(),
102 | ::testing::Bool(), ::testing::Bool(), ::testing::Bool(),
103 | ::testing::Bool(), ::testing::Bool()));
104 |
105 | TEST_P(SolverTest, InfeasibleBufferTooBig) {
106 | const Problem problem = {
107 | .buffers = {{.lifespan = {0, 2}, .size = 3}},
108 | .capacity = 2
109 | };
110 | test_infeasible(problem);
111 | }
112 |
113 | TEST_P(SolverTest, InfeasibleTrivial) {
114 | const Problem problem = {
115 | .buffers = {
116 | {.lifespan = {0, 2}, .size = 2},
117 | {.lifespan = {0, 2}, .size = 2},
118 | },
119 | .capacity = 3
120 | };
121 | test_infeasible(problem);
122 | }
123 |
124 | TEST_P(SolverTest, InfeasibleTricky) {
125 | const Problem problem = {
126 | .buffers = {
127 | {.lifespan = {0, 1}, .size = 3},
128 | {.lifespan = {0, 3}, .size = 1},
129 | {.lifespan = {4, 5}, .size = 3},
130 | {.lifespan = {2, 5}, .size = 1},
131 | {.lifespan = {1, 2}, .size = 2},
132 | {.lifespan = {3, 4}, .size = 2},
133 | {.lifespan = {1, 4}, .size = 1},
134 | },
135 | .capacity = 4
136 | };
137 | test_infeasible(problem);
138 | }
139 |
140 | TEST_P(SolverTest, EmptyProblem) {
141 | const Problem problem;
142 | test_feasible(problem);
143 | }
144 |
145 | TEST_P(SolverTest, SingleBuffer) {
146 | const Problem problem = {
147 | .buffers = {{.lifespan = {0, 2}, .size = 2}},
148 | .capacity = 2
149 | };
150 | test_feasible(problem);
151 | }
152 |
153 | TEST_P(SolverTest, TwoBuffers) {
154 | const Problem problem = {
155 | .buffers = {
156 | {.lifespan = {0, 2}, .size = 2},
157 | {.lifespan = {1, 3}, .size = 2},
158 | },
159 | .capacity = 4
160 | };
161 | test_feasible(problem);
162 | }
163 |
164 | TEST_P(SolverTest, FiveBuffers) {
165 | const Problem problem = {
166 | .buffers = {
167 | {.lifespan = {1, 2}, .size = 1},
168 | {.lifespan = {0, 2}, .size = 1},
169 | {.lifespan = {2, 3}, .size = 2},
170 | {.lifespan = {1, 3}, .size = 1},
171 | {.lifespan = {0, 1}, .size = 2},
172 | },
173 | .capacity = 3
174 | };
175 | test_feasible(problem);
176 | }
177 |
178 | TEST_P(SolverTest, FixedBufferFeasible) {
179 | const Problem problem = {
180 | .buffers = {
181 | {.lifespan = {1, 2}, .size = 1},
182 | {.lifespan = {0, 2}, .size = 1},
183 | {.lifespan = {2, 3}, .size = 2, .offset = 1},
184 | {.lifespan = {1, 3}, .size = 1},
185 | {.lifespan = {0, 1}, .size = 2},
186 | },
187 | .capacity = 3
188 | };
189 | Solver solver(getParams());
190 | const auto solution = solver.Solve(problem);
191 | EXPECT_EQ(solution->offsets[2], 1);
192 | }
193 |
194 | TEST_P(SolverTest, FixedBufferInfeasible) {
195 | const Problem problem = {
196 | .buffers = {
197 | {.lifespan = {1, 2}, .size = 1, .offset = 0},
198 | {.lifespan = {0, 2}, .size = 1},
199 | {.lifespan = {2, 3}, .size = 2},
200 | {.lifespan = {1, 3}, .size = 1},
201 | {.lifespan = {0, 1}, .size = 2},
202 | },
203 | .capacity = 3
204 | };
205 | test_infeasible(problem);
206 | }
207 |
208 | TEST_P(SolverTest, TwoPartitions) {
209 | const Problem problem = {
210 | .buffers = {
211 | {.lifespan = {0, 2}, .size = 2},
212 | {.lifespan = {1, 3}, .size = 2},
213 | {.lifespan = {3, 5}, .size = 2},
214 | {.lifespan = {4, 6}, .size = 2},
215 | },
216 | .capacity = 4
217 | };
218 | test_feasible(problem);
219 | }
220 |
221 | TEST_P(SolverTest, EvenAlignment) {
222 | const Problem problem = {
223 | .buffers = {
224 | {.lifespan = {0, 2}, .size = 1, .alignment = 2},
225 | {.lifespan = {0, 2}, .size = 1, .alignment = 2},
226 | },
227 | .capacity = 4
228 | };
229 | test_feasible(problem);
230 | }
231 |
232 | TEST_P(SolverTest, BuffersWithGaps) {
233 | const Problem problem = {
234 | .buffers = {
235 | {.lifespan = {0, 4}, .size = 2, .gaps = {{.lifespan = {1, 3}}}},
236 | {.lifespan = {1, 3}, .size = 2},
237 | },
238 | .capacity = 2
239 | };
240 | test_feasible(problem);
241 | }
242 |
243 | TEST_P(SolverTest, Tetris) {
244 | const Problem problem = {
245 | .buffers = {
246 | {.lifespan = {0, 10}, .size = 2, .gaps = {{.lifespan = {0, 5},
247 | .window = {{0, 1}}}}},
248 | {.lifespan = {0, 10}, .size = 2, .gaps = {{.lifespan = {5, 10},
249 | .window = {{1, 2}}}}},
250 | },
251 | .capacity = 3
252 | };
253 | test_feasible(problem);
254 | }
255 |
256 | TEST_P(SolverTest, Stairs) {
257 | const Problem problem = {
258 | .buffers = {
259 | {.lifespan = {0, 108}, .size = 30, .gaps = {{.lifespan = {36, 72},
260 | .window = {{10, 30}}},
261 | {.lifespan = {72, 108},
262 | .window = {{20, 30}}}}},
263 | {.lifespan = {36, 144}, .size = 50, .gaps = {{.lifespan = {36, 72},
264 | .window = {{20, 30}}},
265 | {.lifespan = {72, 108},
266 | .window = {{10, 40}}}}},
267 | {.lifespan = {84, 144}, .size = 42, .gaps = {{.lifespan = {114, 129},
268 | .window = {{0, 28}}},
269 | {.lifespan = {129, 144},
270 | .window = {{0, 14}}}}},
271 | {.lifespan = {84, 129}, .size = 42, .gaps = {{.lifespan = {99, 114},
272 | .window = {{14, 42}}},
273 | {.lifespan = {114, 129},
274 | .window = {{28, 42}}}}},
275 | {.lifespan = {99, 144}, .size = 70, .gaps = {{.lifespan = {99, 114},
276 | .window = {{28, 42}}},
277 | {.lifespan = {114, 129},
278 | .window = {{14, 56}}}}},
279 | {.lifespan = {0, 144}, .size = 30, .gaps = {{.lifespan = {72, 108},
280 | .window = {{0, 20}}},
281 | {.lifespan = {108, 144},
282 | .window = {{0, 10}}}}},
283 | },
284 | .capacity = 144
285 | };
286 | test_feasible(problem);
287 | }
288 |
289 | TEST(SolverTest, CountsBacktracks) {
290 | const Problem problem = {
291 | .buffers = {
292 | {.lifespan = {0, 2}, .size = 2},
293 | {.lifespan = {0, 2}, .size = 2},
294 | },
295 | .capacity = 3
296 | };
297 | Solver solver(getDisabledParams());
298 | EXPECT_EQ(solver.Solve(problem).status().code(), absl::StatusCode::kNotFound);
299 | EXPECT_EQ(solver.get_backtracks(), 3);
300 | // Now solve it again to see if it resets.
301 | EXPECT_EQ(solver.Solve(problem).status().code(), absl::StatusCode::kNotFound);
302 | EXPECT_EQ(solver.get_backtracks(), 3);
303 | }
304 |
305 | using ReducesBacktracksTest =
306 | testing::TestWithParam>;
307 |
308 | INSTANTIATE_TEST_SUITE_P(
309 | ReducesBacktracksTests, ReducesBacktracksTest,
310 | testing::ValuesIn>({
311 | [](auto& params) { params.canonical_only = true; },
312 | [](auto& params) { params.section_inference = true; },
313 | [](auto& params) { params.dynamic_ordering = true; },
314 | [](auto& params) { params.check_dominance = true; },
315 | [](auto& params) { params.static_preordering = true; },
316 | [](auto& params) { params.dynamic_decomposition = true; },
317 | }));
318 |
319 | TEST_P(ReducesBacktracksTest, ReducesBacktracks) {
320 | const Problem problem = {
321 | .buffers = {
322 | {.lifespan = {2, 3}, .size = 2},
323 | {.lifespan = {0, 1}, .size = 2},
324 | {.lifespan = {1, 2}, .size = 1},
325 | {.lifespan = {0, 2}, .size = 1},
326 | {.lifespan = {1, 3}, .size = 1},
327 | },
328 | .capacity = 3
329 | };
330 |
331 | SolverParams params = getDisabledParams();
332 | GetParam()(params); // Update the appropriate parameter being tested.
333 | Solver solver(params);
334 | EXPECT_THAT(solver.Solve(problem).status().code(), absl::StatusCode::kOk);
335 |
336 | Solver disabled_solver(getDisabledParams());
337 | EXPECT_THAT(disabled_solver.Solve(problem).status().code(),
338 | absl::StatusCode::kOk);
339 | EXPECT_GT(disabled_solver.get_backtracks(), solver.get_backtracks());
340 | }
341 |
342 | TEST(SolverTest, ComputeIrreducibleInfeasibleSubset) {
343 | const Problem problem = {
344 | .buffers = {
345 | {.lifespan = {0, 2}, .size = 2}, // Not part of the IIS.
346 | {.lifespan = {0, 2}, .size = 2}, // Not part of the IIS.
347 | {.lifespan = {2, 5}, .size = 2}, // Part of the IIS.
348 | {.lifespan = {3, 6}, .size = 2}, // Part of the IIS.
349 | {.lifespan = {4, 7}, .size = 2}, // Part of the IIS.
350 | },
351 | .capacity = 4
352 | };
353 | Solver solver;
354 | auto subset = solver.ComputeIrreducibleInfeasibleSubset(problem);
355 | std::vector expected_subset = {2, 3, 4};
356 | EXPECT_THAT(*subset, expected_subset);
357 | }
358 |
359 | } // namespace
360 | } // namespace minimalloc
361 |
--------------------------------------------------------------------------------
/tests/validator_test.cc:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2023 Google LLC
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | https://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #include "../src/validator.h"
18 |
19 | #include "../src/minimalloc.h"
20 | #include "gtest/gtest.h"
21 |
22 | namespace minimalloc {
23 | namespace {
24 |
25 | TEST(ValidatorTest, ValidatesGoodSolution) {
26 | const Problem problem = {
27 | .buffers = {
28 | {.lifespan = {0, 1}, .size = 2},
29 | {.lifespan = {1, 3}, .size = 1},
30 | {.lifespan = {2, 4}, .size = 1},
31 | {.lifespan = {3, 5}, .size = 1},
32 | },
33 | .capacity = 2
34 | };
35 | // right # of offsets, in range, no overlaps
36 | const Solution solution = {.offsets = {0, 0, 1, 0}};
37 | EXPECT_EQ(Validate(problem, solution), kGood);
38 | }
39 |
40 | TEST(ValidatorTest, ValidatesGoodSolutionWithGaps) {
41 | const Problem problem = {
42 | .buffers = {
43 | {.lifespan = {0, 10}, .size = 2, .gaps = {{.lifespan = {1, 9}}}},
44 | {.lifespan = {5, 15}, .size = 2, .gaps = {{.lifespan = {6, 14}}}},
45 | },
46 | .capacity = 2
47 | };
48 | // right # of offsets, in range, no overlaps
49 | const Solution solution = {.offsets = {0, 0}};
50 | EXPECT_EQ(Validate(problem, solution), kGood);
51 | }
52 |
53 | TEST(ValidatorTest, ValidatesGoodSolutionWithGapsEdgeCase) {
54 | const Problem problem = {
55 | .buffers = {
56 | {.lifespan = {0, 10}, .size = 2, .gaps = {{.lifespan = {1, 8}}}},
57 | {.lifespan = {5, 15}, .size = 2, .gaps = {{.lifespan = {8, 14}}}},
58 | },
59 | .capacity = 2
60 | };
61 | // right # of offsets, in range, no overlaps
62 | const Solution solution = {.offsets = {0, 0}};
63 | EXPECT_EQ(Validate(problem, solution), kGood);
64 | }
65 |
66 | TEST(ValidatorTest, ValidatesTetris) {
67 | const Problem problem = {
68 | .buffers = {
69 | {.lifespan = {0, 10}, .size = 2, .gaps = {{.lifespan = {0, 5},
70 | .window = {{0, 1}}}}},
71 | {.lifespan = {0, 10}, .size = 2, .gaps = {{.lifespan = {5, 10},
72 | .window = {{1, 2}}}}},
73 | },
74 | .capacity = 3
75 | };
76 | // right # of offsets, in range, no overlaps
77 | const Solution solution = {.offsets = {0, 1}};
78 | EXPECT_EQ(Validate(problem, solution), kGood);
79 | }
80 |
81 | TEST(ValidatorTest, ValidatesStairs) {
82 | const Problem problem = {
83 | .buffers = {
84 | {.lifespan = {0, 108}, .size = 30, .gaps = {{.lifespan = {36, 72},
85 | .window = {{10, 30}}},
86 | {.lifespan = {72, 108},
87 | .window = {{20, 30}}}}},
88 | {.lifespan = {36, 144}, .size = 50, .gaps = {{.lifespan = {36, 72},
89 | .window = {{20, 30}}},
90 | {.lifespan = {72, 108},
91 | .window = {{10, 40}}}}},
92 | {.lifespan = {84, 144}, .size = 42, .gaps = {{.lifespan = {114, 129},
93 | .window = {{0, 28}}},
94 | {.lifespan = {129, 144},
95 | .window = {{0, 14}}}}},
96 | {.lifespan = {84, 129}, .size = 42, .gaps = {{.lifespan = {99, 114},
97 | .window = {{14, 42}}},
98 | {.lifespan = {114, 129},
99 | .window = {{28, 42}}}}},
100 | {.lifespan = {99, 144}, .size = 70, .gaps = {{.lifespan = {99, 114},
101 | .window = {{28, 42}}},
102 | {.lifespan = {114, 129},
103 | .window = {{14, 56}}}}},
104 | {.lifespan = {0, 144}, .size = 30, .gaps = {{.lifespan = {72, 108},
105 | .window = {{0, 20}}},
106 | {.lifespan = {108, 144},
107 | .window = {{0, 10}}}}},
108 | },
109 | .capacity = 144
110 | };
111 | const Solution solution = {.offsets = {30, 10, 60, 102, 74, 0}};
112 | EXPECT_EQ(Validate(problem, solution), kGood);
113 | }
114 |
115 | TEST(ValidatorTest, InvalidatesBadSolution) {
116 | const Problem problem = {
117 | .buffers = {
118 | {.lifespan = {0, 1}, .size = 2},
119 | {.lifespan = {1, 2}, .size = 1},
120 | {.lifespan = {1, 2}, .size = 1},
121 | },
122 | .capacity = 2
123 | };
124 | const Solution solution = {.offsets = {0, 0}}; // wrong # of offsets
125 | EXPECT_EQ(Validate(problem, solution), kBadSolution);
126 | }
127 |
128 | TEST(ValidatorTest, InvalidatesFixedBuffer) {
129 | const Problem problem = {
130 | .buffers = {
131 | {.lifespan = {0, 1}, .size = 2},
132 | {.lifespan = {1, 2}, .size = 1},
133 | {.lifespan = {1, 2}, .size = 1, .offset = 0},
134 | },
135 | .capacity = 2
136 | };
137 | // last buffer needs offset @ 0
138 | const Solution solution = {.offsets = {0, 0, 1}};
139 | EXPECT_EQ(Validate(problem, solution), kBadFixed);
140 | }
141 |
142 | TEST(ValidatorTest, InvalidatesNegativeOffset) {
143 | const Problem problem = {
144 | .buffers = {
145 | {.lifespan = {0, 1}, .size = 2},
146 | {.lifespan = {1, 2}, .size = 1},
147 | {.lifespan = {1, 2}, .size = 1},
148 | },
149 | .capacity = 2
150 | };
151 | const Solution solution = {.offsets = {0, 0, -1}}; // offset is negative
152 | EXPECT_EQ(Validate(problem, solution), kBadOffset);
153 | }
154 |
155 | TEST(ValidatorTest, InvalidatesOutOfRangeOffset) {
156 | const Problem problem = {
157 | .buffers = {
158 | {.lifespan = {0, 1}, .size = 2},
159 | {.lifespan = {1, 2}, .size = 1},
160 | {.lifespan = {1, 2}, .size = 1},
161 | },
162 | .capacity = 2
163 | };
164 | // buffer lies outside range
165 | const Solution solution = {.offsets = {0, 0, 2}};
166 | EXPECT_EQ(Validate(problem, solution), kBadOffset);
167 | }
168 |
169 | TEST(ValidatorTest, InvalidatesOverlap) {
170 | const Problem problem = {
171 | .buffers = {
172 | {.lifespan = {0, 1}, .size = 2},
173 | {.lifespan = {1, 2}, .size = 1},
174 | {.lifespan = {1, 2}, .size = 1},
175 | },
176 | .capacity = 2
177 | };
178 | // final two buffers overlap
179 | const Solution solution = {.offsets = {0, 0, 0}};
180 | EXPECT_EQ(Validate(problem, solution), kBadOverlap);
181 | }
182 |
183 | TEST(ValidatorTest, InvalidatesMisalignment) {
184 | const Problem problem = {
185 | .buffers = {
186 | {.lifespan = {0, 1}, .size = 2},
187 | {.lifespan = {1, 2}, .size = 1, .alignment = 2},
188 | },
189 | .capacity = 2
190 | };
191 | // offset of 1 isn't a multiple of 2
192 | const Solution solution = {.offsets = {0, 1}};
193 | EXPECT_EQ(Validate(problem, solution), kBadAlignment);
194 | }
195 |
196 | TEST(ValidatorTest, InvalidatesGapOverlap) {
197 | const Problem problem = {
198 | .buffers = {
199 | {.lifespan = {0, 10}, .size = 2, .gaps = {{.lifespan = {1, 7}}}},
200 | {.lifespan = {5, 15}, .size = 2, .gaps = {{.lifespan = {8, 14}}}},
201 | },
202 | .capacity = 2
203 | };
204 | // right # of offsets, in range, no overlaps
205 | const Solution solution = {.offsets = {0, 0}};
206 | EXPECT_EQ(Validate(problem, solution), kBadOverlap);
207 | }
208 |
209 | } // namespace
210 | } // namespace minimalloc
211 |
--------------------------------------------------------------------------------