├── .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 | --------------------------------------------------------------------------------