1 /**
2 * @file unit-SubarrayPartitioner-sparse.cc
3 *
4 * @section LICENSE
5 *
6 * The MIT License
7 *
8 * @copyright Copyright (c) 2017-2021 TileDB, Inc.
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 * THE SOFTWARE.
27 *
28 * @section DESCRIPTION
29 *
30 * Tests the `SubarrayPartitioner` class for sparse arrays.
31 */
32
33 #include "test/src/helpers.h"
34 #include "test/src/vfs_helpers.h"
35 #include "tiledb/sm/c_api/tiledb_struct_def.h"
36 #include "tiledb/sm/subarray/subarray_partitioner.h"
37
38 #ifdef _WIN32
39 #include "tiledb/sm/filesystem/win.h"
40 #else
41 #include "tiledb/sm/filesystem/posix.h"
42 #endif
43
44 #include <catch.hpp>
45 #include <iostream>
46
47 using namespace tiledb::common;
48 using namespace tiledb::sm;
49 using namespace tiledb::test;
50
51 /* ********************************* */
52 /* STRUCT DEFINITION */
53 /* ********************************* */
54
55 struct SubarrayPartitionerSparseFx {
56 tiledb_ctx_t* ctx_;
57 tiledb_vfs_t* vfs_;
58 const std::vector<std::unique_ptr<SupportedFs>> fs_vec_;
59 std::string temp_dir_;
60 std::string array_name_;
61 const char* ARRAY_NAME = "subarray_partitioner_sparse";
62 tiledb_array_t* array_ = nullptr;
63 uint64_t memory_budget_ = 1024 * 1024 * 1024;
64 uint64_t memory_budget_var_ = 1024 * 1024 * 1024;
65
66 SubarrayPartitionerSparseFx();
67 ~SubarrayPartitionerSparseFx();
68
69 /**
70 * Helper function that creates a default 1D array, with the
71 * input tile and cell order.
72 */
73 void create_default_1d_array(
74 tiledb_layout_t tile_order, tiledb_layout_t cell_order);
75
76 /**
77 * Helper function that creates a default 1D array, with float
78 * dimension and the input tile and cell order.
79 */
80 void create_default_1d_float_array(
81 tiledb_layout_t tile_order, tiledb_layout_t cell_order);
82
83 /**
84 * Helper function that creates a default 2D array, with the
85 * input tile and cell order.
86 */
87 void create_default_2d_array(
88 tiledb_layout_t tile_order, tiledb_layout_t cell_order);
89
90 /** Helper function that writes to the default 1D array. */
91 void write_default_1d_array();
92
93 /** Helper function that writes to a second default 1D array. */
94 void write_default_1d_array_2();
95
96 /** Helper function that writes to the default 1D float array. */
97 void write_default_1d_float_array();
98
99 /** Helper function that writes to the default 2D array. */
100 void write_default_2d_array();
101
102 /**
103 * Helper function to test the subarray partitioner for the given arguments.
104 */
105 template <class T>
106 void test_subarray_partitioner(
107 Layout subarray_layout,
108 const SubarrayRanges<T>& ranges,
109 const std::vector<SubarrayRanges<T>>& partitions,
110 const std::string& attr, // Attribute to set the budget for
111 uint64_t budget,
112 bool unsplittable = false);
113
114 /**
115 * Helper function to test the subarray partitioner for the given arguments.
116 */
117 template <class T>
118 void test_subarray_partitioner(
119 Layout subarray_layout,
120 const SubarrayRanges<T>& ranges,
121 const std::vector<SubarrayRanges<T>>& partitions,
122 const std::string& attr, // Attribute to set the budget for
123 uint64_t result_budget,
124 uint64_t memory_budget,
125 uint64_t memory_budget_var,
126 bool unsplittable = false);
127
128 /**
129 * Helper function to test the subarray partitioner for the given arguments.
130 * This is different from the above in that it tests the memory
131 * budget.
132 */
133 template <class T>
134 void test_subarray_partitioner(
135 Layout subarray_layout,
136 const SubarrayRanges<T>& ranges,
137 const std::vector<SubarrayRanges<T>>& partitions,
138 uint64_t budget,
139 uint64_t budget_var,
140 bool unsplittable = false);
141 };
142
SubarrayPartitionerSparseFx()143 SubarrayPartitionerSparseFx::SubarrayPartitionerSparseFx()
144 : fs_vec_(vfs_test_get_fs_vec()) {
145 // Initialize vfs test
146 REQUIRE(vfs_test_init(fs_vec_, &ctx_, &vfs_).ok());
147
148 // Create temporary directory based on the supported filesystem
149 #ifdef _WIN32
150 SupportedFsLocal windows_fs;
151 temp_dir_ = windows_fs.file_prefix() + windows_fs.temp_dir();
152 #else
153 SupportedFsLocal posix_fs;
154 temp_dir_ = posix_fs.file_prefix() + posix_fs.temp_dir();
155 #endif
156
157 create_dir(temp_dir_, ctx_, vfs_);
158
159 array_name_ = temp_dir_ + ARRAY_NAME;
160 int rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array_);
161 CHECK(rc == TILEDB_OK);
162 }
163
~SubarrayPartitionerSparseFx()164 SubarrayPartitionerSparseFx::~SubarrayPartitionerSparseFx() {
165 tiledb_array_free(&array_);
166 remove_dir(temp_dir_, ctx_, vfs_);
167 tiledb_ctx_free(&ctx_);
168 tiledb_vfs_free(&vfs_);
169 }
170
create_default_1d_array(tiledb_layout_t tile_order,tiledb_layout_t cell_order)171 void SubarrayPartitionerSparseFx::create_default_1d_array(
172 tiledb_layout_t tile_order, tiledb_layout_t cell_order) {
173 uint64_t domain[] = {1, 100};
174 uint64_t tile_extent = 10;
175 create_array(
176 ctx_,
177 array_name_,
178 TILEDB_SPARSE,
179 {"d"},
180 {TILEDB_UINT64},
181 {domain},
182 {&tile_extent},
183 {"a", "b"},
184 {TILEDB_INT32, TILEDB_INT32},
185 {1, TILEDB_VAR_NUM},
186 {tiledb::test::Compressor(TILEDB_FILTER_LZ4, -1),
187 tiledb::test::Compressor(TILEDB_FILTER_LZ4, -1)},
188 tile_order,
189 cell_order,
190 2);
191 }
192
create_default_1d_float_array(tiledb_layout_t tile_order,tiledb_layout_t cell_order)193 void SubarrayPartitionerSparseFx::create_default_1d_float_array(
194 tiledb_layout_t tile_order, tiledb_layout_t cell_order) {
195 float domain[] = {1.0f, 100.0f};
196 float tile_extent = 100.0f;
197 create_array(
198 ctx_,
199 array_name_,
200 TILEDB_SPARSE,
201 {"d"},
202 {TILEDB_FLOAT32},
203 {domain},
204 {&tile_extent},
205 {"a", "b"},
206 {TILEDB_INT32, TILEDB_INT32},
207 {1, TILEDB_VAR_NUM},
208 {tiledb::test::Compressor(TILEDB_FILTER_LZ4, -1),
209 tiledb::test::Compressor(TILEDB_FILTER_LZ4, -1)},
210 tile_order,
211 cell_order,
212 2);
213 }
214
create_default_2d_array(tiledb_layout_t tile_order,tiledb_layout_t cell_order)215 void SubarrayPartitionerSparseFx::create_default_2d_array(
216 tiledb_layout_t tile_order, tiledb_layout_t cell_order) {
217 uint64_t domain[] = {1, 10};
218 uint64_t tile_extent = 2;
219 create_array(
220 ctx_,
221 array_name_,
222 TILEDB_SPARSE,
223 {"d1", "d2"},
224 {TILEDB_UINT64, TILEDB_UINT64},
225 {domain, domain},
226 {&tile_extent, &tile_extent},
227 {"a", "b"},
228 {TILEDB_INT32, TILEDB_INT32},
229 {1, TILEDB_VAR_NUM},
230 {tiledb::test::Compressor(TILEDB_FILTER_LZ4, -1),
231 tiledb::test::Compressor(TILEDB_FILTER_LZ4, -1)},
232 tile_order,
233 cell_order,
234 2);
235 }
236
write_default_1d_array()237 void SubarrayPartitionerSparseFx::write_default_1d_array() {
238 tiledb::test::QueryBuffers buffers;
239 std::vector<uint64_t> coords = {2, 4, 5, 10, 12, 18};
240 uint64_t coords_size = coords.size() * sizeof(uint64_t);
241 std::vector<int> a = {1, 2, 3, 4, 5, 6};
242 uint64_t a_size = a.size() * sizeof(int);
243 std::vector<uint64_t> b_off = {0,
244 sizeof(int),
245 3 * sizeof(int),
246 6 * sizeof(int),
247 9 * sizeof(int),
248 11 * sizeof(int)};
249 uint64_t b_off_size = b_off.size() * sizeof(uint64_t);
250 std::vector<int> b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6};
251 uint64_t b_val_size = b_val.size() * sizeof(int);
252 buffers[TILEDB_COORDS] =
253 tiledb::test::QueryBuffer({&coords[0], coords_size, nullptr, 0});
254 buffers["a"] = tiledb::test::QueryBuffer({&a[0], a_size, nullptr, 0});
255 buffers["b"] =
256 tiledb::test::QueryBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size});
257 write_array(ctx_, array_name_, TILEDB_UNORDERED, buffers);
258 }
259
write_default_1d_array_2()260 void SubarrayPartitionerSparseFx::write_default_1d_array_2() {
261 tiledb::test::QueryBuffers buffers;
262 std::vector<uint64_t> coords = {2, 4, 5, 10, 12, 18, 25, 27, 33, 40};
263 uint64_t coords_size = coords.size() * sizeof(uint64_t);
264 std::vector<int> a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
265 uint64_t a_size = a.size() * sizeof(int);
266 std::vector<uint64_t> b_off = {0,
267 sizeof(int),
268 3 * sizeof(int),
269 6 * sizeof(int),
270 9 * sizeof(int),
271 11 * sizeof(int),
272 15 * sizeof(int),
273 16 * sizeof(int),
274 17 * sizeof(int),
275 18 * sizeof(int)};
276 uint64_t b_off_size = b_off.size() * sizeof(uint64_t);
277 std::vector<int> b_val = {
278 1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6, 7, 8, 9, 10};
279 uint64_t b_val_size = b_val.size() * sizeof(int);
280 buffers[TILEDB_COORDS] =
281 tiledb::test::QueryBuffer({&coords[0], coords_size, nullptr, 0});
282 buffers["a"] = tiledb::test::QueryBuffer({&a[0], a_size, nullptr, 0});
283 buffers["b"] =
284 tiledb::test::QueryBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size});
285 write_array(ctx_, array_name_, TILEDB_UNORDERED, buffers);
286 }
287
write_default_1d_float_array()288 void SubarrayPartitionerSparseFx::write_default_1d_float_array() {
289 tiledb::test::QueryBuffers buffers;
290 std::vector<float> coords = {2.0f, 4.0f, 5.0f, 10.0f, 12.0f, 18.0f};
291 uint64_t coords_size = coords.size() * sizeof(float);
292 std::vector<int> a = {1, 2, 3, 4, 5, 6};
293 uint64_t a_size = a.size() * sizeof(int);
294 std::vector<uint64_t> b_off = {0,
295 sizeof(int),
296 3 * sizeof(int),
297 6 * sizeof(int),
298 9 * sizeof(int),
299 11 * sizeof(int)};
300 uint64_t b_off_size = b_off.size() * sizeof(uint64_t);
301 std::vector<int> b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6};
302 uint64_t b_val_size = b_val.size() * sizeof(int);
303 buffers[TILEDB_COORDS] =
304 tiledb::test::QueryBuffer({&coords[0], coords_size, nullptr, 0});
305 buffers["a"] = tiledb::test::QueryBuffer({&a[0], a_size, nullptr, 0});
306 buffers["b"] =
307 tiledb::test::QueryBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size});
308 write_array(ctx_, array_name_, TILEDB_UNORDERED, buffers);
309 }
310
write_default_2d_array()311 void SubarrayPartitionerSparseFx::write_default_2d_array() {
312 tiledb::test::QueryBuffers buffers;
313 std::vector<uint64_t> coords = {1, 2, 2, 5, 3, 3, 3, 9, 4, 1, 4, 7};
314 uint64_t coords_size = coords.size() * sizeof(uint64_t);
315 std::vector<int> a = {1, 2, 3, 4, 5, 6};
316 uint64_t a_size = a.size() * sizeof(int);
317 std::vector<uint64_t> b_off = {0,
318 sizeof(int),
319 3 * sizeof(int),
320 6 * sizeof(int),
321 9 * sizeof(int),
322 11 * sizeof(int)};
323 uint64_t b_off_size = b_off.size() * sizeof(uint64_t);
324 std::vector<int> b_val = {1, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 6};
325 uint64_t b_val_size = b_val.size() * sizeof(int);
326 buffers[TILEDB_COORDS] =
327 tiledb::test::QueryBuffer({&coords[0], coords_size, nullptr, 0});
328 buffers["a"] = tiledb::test::QueryBuffer({&a[0], a_size, nullptr, 0});
329 buffers["b"] =
330 tiledb::test::QueryBuffer({&b_off[0], b_off_size, &b_val[0], b_val_size});
331 write_array(ctx_, array_name_, TILEDB_UNORDERED, buffers);
332 }
333
334 template <class T>
test_subarray_partitioner(Layout subarray_layout,const SubarrayRanges<T> & ranges,const std::vector<SubarrayRanges<T>> & partitions,const std::string & attr,uint64_t budget,bool unsplittable)335 void SubarrayPartitionerSparseFx::test_subarray_partitioner(
336 Layout subarray_layout,
337 const SubarrayRanges<T>& ranges,
338 const std::vector<SubarrayRanges<T>>& partitions,
339 const std::string& attr,
340 uint64_t budget,
341 bool unsplittable) {
342 Subarray subarray;
343 create_subarray(array_->array_, ranges, subarray_layout, &subarray);
344
345 ThreadPool tp;
346 CHECK(tp.init(4).ok());
347 Config config;
348 SubarrayPartitioner subarray_partitioner(
349 &config,
350 subarray,
351 memory_budget_,
352 memory_budget_var_,
353 0,
354 &tp,
355 &g_helper_stats,
356 g_helper_logger());
357 auto st = subarray_partitioner.set_result_budget(attr.c_str(), budget);
358 CHECK(st.ok());
359
360 check_partitions(subarray_partitioner, partitions, unsplittable);
361 }
362
363 template <class T>
test_subarray_partitioner(Layout subarray_layout,const SubarrayRanges<T> & ranges,const std::vector<SubarrayRanges<T>> & partitions,const std::string & attr,uint64_t result_budget,uint64_t memory_budget,uint64_t memory_budget_var,bool unsplittable)364 void SubarrayPartitionerSparseFx::test_subarray_partitioner(
365 Layout subarray_layout,
366 const SubarrayRanges<T>& ranges,
367 const std::vector<SubarrayRanges<T>>& partitions,
368 const std::string& attr,
369 uint64_t result_budget,
370 uint64_t memory_budget,
371 uint64_t memory_budget_var,
372 bool unsplittable) {
373 Subarray subarray;
374 create_subarray(array_->array_, ranges, subarray_layout, &subarray);
375
376 ThreadPool tp;
377 CHECK(tp.init(4).ok());
378 Config config;
379 SubarrayPartitioner subarray_partitioner(
380 &config,
381 subarray,
382 memory_budget,
383 memory_budget_var,
384 0,
385 &tp,
386 &g_helper_stats,
387 g_helper_logger());
388 auto st = subarray_partitioner.set_result_budget(attr.c_str(), result_budget);
389 CHECK(st.ok());
390
391 check_partitions(subarray_partitioner, partitions, unsplittable);
392 }
393
394 template <class T>
test_subarray_partitioner(Layout subarray_layout,const SubarrayRanges<T> & ranges,const std::vector<SubarrayRanges<T>> & partitions,uint64_t budget,uint64_t budget_var,bool unsplittable)395 void SubarrayPartitionerSparseFx::test_subarray_partitioner(
396 Layout subarray_layout,
397 const SubarrayRanges<T>& ranges,
398 const std::vector<SubarrayRanges<T>>& partitions,
399 uint64_t budget,
400 uint64_t budget_var,
401 bool unsplittable) {
402 Subarray subarray;
403 create_subarray(array_->array_, ranges, subarray_layout, &subarray);
404
405 ThreadPool tp;
406 CHECK(tp.init(4).ok());
407 Config config;
408 SubarrayPartitioner subarray_partitioner(
409 &config,
410 subarray,
411 memory_budget_,
412 memory_budget_var_,
413 0,
414 &tp,
415 &g_helper_stats,
416 g_helper_logger());
417
418 // Note: this is necessary, otherwise the subarray partitioner does
419 // not check if the memory budget is exceeded for attributes whose
420 // result budget is not set.
421 auto st = subarray_partitioner.set_result_budget(TILEDB_COORDS, 1000000);
422 CHECK(st.ok());
423 st = subarray_partitioner.set_result_budget("a", 1000000);
424 CHECK(st.ok());
425 st = subarray_partitioner.set_result_budget("b", 1000000, 1000000);
426 CHECK(st.ok());
427
428 st = subarray_partitioner.set_memory_budget(budget, budget_var, 0);
429 CHECK(st.ok());
430
431 check_partitions(subarray_partitioner, partitions, unsplittable);
432 }
433
434 /* ********************************* */
435 /* TESTS */
436 /* ********************************* */
437
438 TEST_CASE_METHOD(
439 SubarrayPartitionerSparseFx,
440 "SubarrayPartitioner (Sparse): 1D, single-range, empty array",
441 "[SubarrayPartitioner][sparse][1D][1R][empty_array]") {
442 Layout subarray_layout;
443 SubarrayRanges<uint64_t> ranges = {};
444 std::vector<SubarrayRanges<uint64_t>> partitions = {{{1, 100}}};
445 uint64_t budget = 1000 * sizeof(uint64_t);
446 std::string attr = TILEDB_COORDS;
447 bool unsplittable = false;
448
449 create_default_1d_array(TILEDB_ROW_MAJOR, TILEDB_ROW_MAJOR);
450 open_array(ctx_, array_, TILEDB_READ);
451
452 // subarray: global
453 subarray_layout = Layout::GLOBAL_ORDER;
454 test_subarray_partitioner(
455 subarray_layout, ranges, partitions, attr, budget, unsplittable);
456
457 // subarray: row
458 subarray_layout = Layout::ROW_MAJOR;
459 test_subarray_partitioner(
460 subarray_layout, ranges, partitions, attr, budget, unsplittable);
461
462 // subarray: col
463 subarray_layout = Layout::COL_MAJOR;
464 test_subarray_partitioner(
465 subarray_layout, ranges, partitions, attr, budget, unsplittable);
466
467 // subarray: unordered
468 subarray_layout = Layout::UNORDERED;
469 test_subarray_partitioner(
470 subarray_layout, ranges, partitions, attr, budget, unsplittable);
471
472 close_array(ctx_, array_);
473 }
474
475 TEST_CASE_METHOD(
476 SubarrayPartitionerSparseFx,
477 "SubarrayPartitioner (Sparse): 1D, single-range, whole subarray fits",
478 "[SubarrayPartitioner][sparse][1D][1R][whole_subarray_fits]") {
479 Layout subarray_layout;
480 SubarrayRanges<uint64_t> ranges = {};
481 std::vector<SubarrayRanges<uint64_t>> partitions = {{{1, 100}}};
482 uint64_t budget = 1000 * sizeof(uint64_t);
483 std::string attr = TILEDB_COORDS;
484 bool unsplittable = false;
485
486 create_default_1d_array(TILEDB_ROW_MAJOR, TILEDB_ROW_MAJOR);
487 write_default_1d_array();
488 open_array(ctx_, array_, TILEDB_READ);
489
490 // subarray: global
491 subarray_layout = Layout::GLOBAL_ORDER;
492 test_subarray_partitioner(
493 subarray_layout, ranges, partitions, attr, budget, unsplittable);
494
495 // subarray: row
496 subarray_layout = Layout::ROW_MAJOR;
497 test_subarray_partitioner(
498 subarray_layout, ranges, partitions, attr, budget, unsplittable);
499
500 // subarray: col
501 subarray_layout = Layout::COL_MAJOR;
502 test_subarray_partitioner(
503 subarray_layout, ranges, partitions, attr, budget, unsplittable);
504
505 // subarray: unordered
506 subarray_layout = Layout::UNORDERED;
507 test_subarray_partitioner(
508 subarray_layout, ranges, partitions, attr, budget, unsplittable);
509
510 close_array(ctx_, array_);
511 }
512
513 TEST_CASE_METHOD(
514 SubarrayPartitionerSparseFx,
515 "SubarrayPartitioner (Sparse): 1D, single-range, split once",
516 "[SubarrayPartitioner][sparse][1D][1R][split_once]") {
517 Layout subarray_layout;
518 SubarrayRanges<uint64_t> ranges = {{3, 11}};
519 std::vector<SubarrayRanges<uint64_t>> partitions = {{{1, 100}}};
520 uint64_t budget = 3 * sizeof(int);
521 std::string attr = "a";
522 bool unsplittable = false;
523
524 create_default_1d_array(TILEDB_ROW_MAJOR, TILEDB_ROW_MAJOR);
525 write_default_1d_array();
526 open_array(ctx_, array_, TILEDB_READ);
527
528 // subarray: global
529 subarray_layout = Layout::GLOBAL_ORDER;
530 partitions = {{{3, 6}}, {{7, 10}}, {{11, 11}}};
531 test_subarray_partitioner(
532 subarray_layout, ranges, partitions, attr, budget, unsplittable);
533
534 // subarray: row
535 subarray_layout = Layout::ROW_MAJOR;
536 partitions = {{{3, 7}}, {{8, 11}}};
537 test_subarray_partitioner(
538 subarray_layout, ranges, partitions, attr, budget, unsplittable);
539
540 // subarray: col
541 subarray_layout = Layout::COL_MAJOR;
542 test_subarray_partitioner(
543 subarray_layout, ranges, partitions, attr, budget, unsplittable);
544
545 // subarray: unordered
546 subarray_layout = Layout::UNORDERED;
547 test_subarray_partitioner(
548 subarray_layout, ranges, partitions, attr, budget, unsplittable);
549
550 close_array(ctx_, array_);
551 }
552
553 TEST_CASE_METHOD(
554 SubarrayPartitionerSparseFx,
555 "SubarrayPartitioner (Sparse): 1D, single-range, unsplittable at once",
556 "[SubarrayPartitioner][sparse][1D][1R][unsplittable_at_once]") {
557 Layout subarray_layout;
558 SubarrayRanges<uint64_t> ranges = {{4, 4}};
559 std::vector<SubarrayRanges<uint64_t>> partitions = {{{4, 4}}};
560 uint64_t budget = 1;
561 std::string attr = "a";
562 bool unsplittable = true;
563
564 create_default_1d_array(TILEDB_ROW_MAJOR, TILEDB_ROW_MAJOR);
565 write_default_1d_array();
566 open_array(ctx_, array_, TILEDB_READ);
567
568 // subarray: global
569 subarray_layout = Layout::GLOBAL_ORDER;
570 test_subarray_partitioner(
571 subarray_layout, ranges, partitions, attr, budget, unsplittable);
572
573 // subarray: row
574 subarray_layout = Layout::ROW_MAJOR;
575 test_subarray_partitioner(
576 subarray_layout, ranges, partitions, attr, budget, unsplittable);
577
578 // subarray: col
579 subarray_layout = Layout::COL_MAJOR;
580 test_subarray_partitioner(
581 subarray_layout, ranges, partitions, attr, budget, unsplittable);
582
583 // subarray: unordered
584 subarray_layout = Layout::UNORDERED;
585 test_subarray_partitioner(
586 subarray_layout, ranges, partitions, attr, budget, unsplittable);
587
588 close_array(ctx_, array_);
589 }
590
591 TEST_CASE_METHOD(
592 SubarrayPartitionerSparseFx,
593 "SubarrayPartitioner (Sparse): 1D, single-range, split multiple",
594 "[SubarrayPartitioner][sparse][1D][1R][split_multiple]") {
595 Layout subarray_layout;
596 SubarrayRanges<uint64_t> ranges = {{2, 18}};
597 std::vector<SubarrayRanges<uint64_t>> partitions = {
598 {{2, 4}}, {{5, 6}}, {{7, 10}}, {{11, 18}}};
599 uint64_t budget = 2 * sizeof(int);
600 std::string attr = "a";
601 bool unsplittable = false;
602
603 create_default_1d_array(TILEDB_ROW_MAJOR, TILEDB_ROW_MAJOR);
604 write_default_1d_array();
605 open_array(ctx_, array_, TILEDB_READ);
606
607 // subarray: global
608 subarray_layout = Layout::GLOBAL_ORDER;
609 test_subarray_partitioner(
610 subarray_layout, ranges, partitions, attr, budget, unsplittable);
611
612 // subarray: row
613 subarray_layout = Layout::ROW_MAJOR;
614 test_subarray_partitioner(
615 subarray_layout, ranges, partitions, attr, budget, unsplittable);
616
617 // subarray: col
618 subarray_layout = Layout::COL_MAJOR;
619 test_subarray_partitioner(
620 subarray_layout, ranges, partitions, attr, budget, unsplittable);
621
622 // subarray: unordered
623 subarray_layout = Layout::UNORDERED;
624 test_subarray_partitioner(
625 subarray_layout, ranges, partitions, attr, budget, unsplittable);
626
627 close_array(ctx_, array_);
628 }
629
630 TEST_CASE_METHOD(
631 SubarrayPartitionerSparseFx,
632 "SubarrayPartitioner (Sparse): 1D, single-range, unsplittable after "
633 "multiple",
634 "[SubarrayPartitioner][sparse][1D][1R][unsplittable_after_multiple]") {
635 Layout subarray_layout;
636 SubarrayRanges<uint64_t> ranges = {{2, 18}};
637 std::vector<SubarrayRanges<uint64_t>> partitions = {{{2, 2}}};
638 uint64_t budget = 1;
639 std::string attr = "a";
640 bool unsplittable = true;
641
642 create_default_1d_array(TILEDB_ROW_MAJOR, TILEDB_ROW_MAJOR);
643 write_default_1d_array();
644 open_array(ctx_, array_, TILEDB_READ);
645
646 // subarray: global
647 subarray_layout = Layout::GLOBAL_ORDER;
648 test_subarray_partitioner(
649 subarray_layout, ranges, partitions, attr, budget, unsplittable);
650
651 // subarray: row
652 subarray_layout = Layout::ROW_MAJOR;
653 test_subarray_partitioner(
654 subarray_layout, ranges, partitions, attr, budget, unsplittable);
655
656 // subarray: col
657 subarray_layout = Layout::COL_MAJOR;
658 test_subarray_partitioner(
659 subarray_layout, ranges, partitions, attr, budget, unsplittable);
660
661 // subarray: unordered
662 subarray_layout = Layout::UNORDERED;
663 test_subarray_partitioner(
664 subarray_layout, ranges, partitions, attr, budget, unsplittable);
665
666 close_array(ctx_, array_);
667 }
668
669 TEST_CASE_METHOD(
670 SubarrayPartitionerSparseFx,
671 "SubarrayPartitioner (Sparse): 1D, single-range, unsplittable but ok after "
672 "budget reset",
673 "[SubarrayPartitioner][sparse][1D][1R][unsplittable_but_then_ok]") {
674 create_default_1d_array(TILEDB_ROW_MAJOR, TILEDB_ROW_MAJOR);
675 write_default_1d_array();
676 open_array(ctx_, array_, TILEDB_READ);
677
678 Subarray subarray;
679 SubarrayRanges<uint64_t> ranges = {{2, 18}};
680 Layout subarray_layout = Layout::GLOBAL_ORDER;
681 std::vector<SubarrayRanges<uint64_t>> partitions = {{{2, 2}}};
682 std::vector<SubarrayRanges<uint64_t>> partitions_after = {
683 {{3, 3}}, {{4, 4}}, {{5, 6}}, {{7, 10}}, {{11, 18}}};
684
685 create_subarray(array_->array_, ranges, subarray_layout, &subarray);
686
687 ThreadPool tp;
688 CHECK(tp.init(4).ok());
689 Config config;
690 SubarrayPartitioner subarray_partitioner(
691 &config,
692 subarray,
693 memory_budget_,
694 memory_budget_var_,
695 0,
696 &tp,
697 &g_helper_stats,
698 g_helper_logger());
699 auto st = subarray_partitioner.set_result_budget("a", 100);
700 CHECK(st.ok());
701 st = subarray_partitioner.set_result_budget("b", 1, 1);
702 CHECK(st.ok());
703
704 check_partitions(subarray_partitioner, partitions, true);
705
706 st = subarray_partitioner.set_result_budget("b", 100, 100);
707 CHECK(st.ok());
708
709 check_partitions(subarray_partitioner, partitions_after, false);
710
711 close_array(ctx_, array_);
712 }
713
714 TEST_CASE_METHOD(
715 SubarrayPartitionerSparseFx,
716 "SubarrayPartitioner (Sparse): 1D, single-range, float, split multiple",
717 "[SubarrayPartitioner][sparse][1D][1R][float][split_multiple]") {
718 Layout subarray_layout;
719 auto max = std::numeric_limits<float>::max();
720 SubarrayRanges<float> ranges = {{2.0f, 18.0f}};
721 std::vector<SubarrayRanges<float>> partitions = {
722 {{2.0f, 4.0f}},
723 {{std::nextafter(4.0f, max), 6.0f}},
724 {{std::nextafter(6.0f, max), 10.0f}},
725 {{std::nextafter(10.0f, max), 18.0f}}};
726 uint64_t budget = 2 * sizeof(int);
727 std::string attr = "a";
728 bool unsplittable = false;
729
730 create_default_1d_float_array(TILEDB_ROW_MAJOR, TILEDB_ROW_MAJOR);
731 write_default_1d_float_array();
732 open_array(ctx_, array_, TILEDB_READ);
733
734 // subarray: global
735 subarray_layout = Layout::GLOBAL_ORDER;
736 test_subarray_partitioner(
737 subarray_layout, ranges, partitions, attr, budget, unsplittable);
738
739 // subarray: row
740 subarray_layout = Layout::ROW_MAJOR;
741 test_subarray_partitioner(
742 subarray_layout, ranges, partitions, attr, budget, unsplittable);
743
744 // subarray: col
745 subarray_layout = Layout::COL_MAJOR;
746 test_subarray_partitioner(
747 subarray_layout, ranges, partitions, attr, budget, unsplittable);
748
749 // subarray: unordered
750 subarray_layout = Layout::UNORDERED;
751 test_subarray_partitioner(
752 subarray_layout, ranges, partitions, attr, budget, unsplittable);
753
754 close_array(ctx_, array_);
755 }
756
757 TEST_CASE_METHOD(
758 SubarrayPartitionerSparseFx,
759 "SubarrayPartitioner (Sparse): 1D, single-range, float, unsplittable after "
760 "multiple",
761 "[SubarrayPartitioner][sparse][1D][1R][float][unsplittable_after_"
762 "multiple]") {
763 Layout subarray_layout;
764 SubarrayRanges<float> ranges = {{2.0f, 18.0f}};
765 std::vector<SubarrayRanges<float>> partitions = {{{2.0f, 2.0f}}};
766 uint64_t budget = 0;
767 std::string attr = "a";
768 bool unsplittable = true;
769
770 create_default_1d_float_array(TILEDB_ROW_MAJOR, TILEDB_ROW_MAJOR);
771 write_default_1d_float_array();
772 open_array(ctx_, array_, TILEDB_READ);
773
774 // subarray: global
775 subarray_layout = Layout::GLOBAL_ORDER;
776 test_subarray_partitioner(
777 subarray_layout, ranges, partitions, attr, budget, unsplittable);
778
779 // subarray: row
780 subarray_layout = Layout::ROW_MAJOR;
781 test_subarray_partitioner(
782 subarray_layout, ranges, partitions, attr, budget, unsplittable);
783
784 // subarray: col
785 subarray_layout = Layout::COL_MAJOR;
786 test_subarray_partitioner(
787 subarray_layout, ranges, partitions, attr, budget, unsplittable);
788
789 // subarray: unordered
790 subarray_layout = Layout::UNORDERED;
791 test_subarray_partitioner(
792 subarray_layout, ranges, partitions, attr, budget, unsplittable);
793
794 close_array(ctx_, array_);
795 }
796
797 TEST_CASE_METHOD(
798 SubarrayPartitionerSparseFx,
799 "SubarrayPartitioner (Sparse): 1D, single-range, float, whole subarray "
800 "fits",
801 "[SubarrayPartitioner][sparse][1D][1R][float][whole_subarray_fits]") {
802 Layout subarray_layout;
803 SubarrayRanges<float> ranges = {{2.0f, 18.0f}};
804 std::vector<SubarrayRanges<float>> partitions = {{{2.0f, 18.0f}}};
805 uint64_t budget = 100000;
806 std::string attr = "a";
807 bool unsplittable = false;
808
809 create_default_1d_float_array(TILEDB_ROW_MAJOR, TILEDB_ROW_MAJOR);
810 write_default_1d_float_array();
811 open_array(ctx_, array_, TILEDB_READ);
812
813 // subarray: global
814 subarray_layout = Layout::GLOBAL_ORDER;
815 test_subarray_partitioner(
816 subarray_layout, ranges, partitions, attr, budget, unsplittable);
817
818 // subarray: row
819 subarray_layout = Layout::ROW_MAJOR;
820 test_subarray_partitioner(
821 subarray_layout, ranges, partitions, attr, budget, unsplittable);
822
823 // subarray: col
824 subarray_layout = Layout::COL_MAJOR;
825 test_subarray_partitioner(
826 subarray_layout, ranges, partitions, attr, budget, unsplittable);
827
828 // subarray: unordered
829 subarray_layout = Layout::UNORDERED;
830 test_subarray_partitioner(
831 subarray_layout, ranges, partitions, attr, budget, unsplittable);
832
833 close_array(ctx_, array_);
834 }
835
836 TEST_CASE_METHOD(
837 SubarrayPartitionerSparseFx,
838 "SubarrayPartitioner (Sparse): 1D, single-range, memory budget",
839 "[SubarrayPartitioner][sparse][1D][1R][memory_budget]") {
840 Layout subarray_layout;
841 SubarrayRanges<uint64_t> ranges = {};
842 std::vector<SubarrayRanges<uint64_t>> partitions = {};
843 uint64_t budget = 16;
844 uint64_t budget_var = 100000;
845 bool unsplittable = false;
846
847 create_default_1d_array(TILEDB_ROW_MAJOR, TILEDB_ROW_MAJOR);
848 write_default_1d_array_2();
849 open_array(ctx_, array_, TILEDB_READ);
850
851 // subarray: global
852 subarray_layout = Layout::GLOBAL_ORDER;
853 partitions = {
854 {{1, 3}},
855 {{4, 4}},
856 {{5, 5}},
857 {{6, 10}},
858 {{11, 20}},
859 {{21, 30}},
860 {{31, 40}},
861 {{41, 100}},
862 };
863 test_subarray_partitioner(
864 subarray_layout, ranges, partitions, budget, budget_var, unsplittable);
865
866 // subarray: row
867 subarray_layout = Layout::ROW_MAJOR;
868 partitions = {
869 {{1, 4}},
870 {{5, 7}},
871 {{8, 10}},
872 {{11, 13}},
873 {{14, 19}},
874 {{20, 25}},
875 {{26, 32}},
876 {{33, 38}},
877 {{39, 50}},
878 {{51, 100}},
879 };
880 test_subarray_partitioner(
881 subarray_layout, ranges, partitions, budget, budget_var, unsplittable);
882
883 // subarray: col
884 subarray_layout = Layout::COL_MAJOR;
885 test_subarray_partitioner(
886 subarray_layout, ranges, partitions, budget, budget_var, unsplittable);
887
888 // subarray: unordered
889 subarray_layout = Layout::UNORDERED;
890 test_subarray_partitioner(
891 subarray_layout, ranges, partitions, budget, budget_var, unsplittable);
892
893 close_array(ctx_, array_);
894 }
895
896 TEST_CASE_METHOD(
897 SubarrayPartitionerSparseFx,
898 "SubarrayPartitioner (Sparse): 1D, multi-range, whole subarray fits",
899 "[SubarrayPartitioner][sparse][1D][MR][whole_subarray_fits]") {
900 Layout subarray_layout;
901 SubarrayRanges<uint64_t> ranges = {{5, 10, 25, 27, 33, 50}};
902 std::vector<SubarrayRanges<uint64_t>> partitions = {
903 {{5, 10, 25, 27, 33, 50}}};
904 uint64_t budget = 100000;
905 std::string attr = "a";
906 bool unsplittable = false;
907
908 create_default_1d_array(TILEDB_ROW_MAJOR, TILEDB_ROW_MAJOR);
909 write_default_1d_array_2();
910 open_array(ctx_, array_, TILEDB_READ);
911
912 // subarray: row
913 subarray_layout = Layout::ROW_MAJOR;
914 test_subarray_partitioner(
915 subarray_layout, ranges, partitions, attr, budget, unsplittable);
916
917 // subarray: col
918 subarray_layout = Layout::COL_MAJOR;
919 test_subarray_partitioner(
920 subarray_layout, ranges, partitions, attr, budget, unsplittable);
921
922 // subarray: unordered
923 subarray_layout = Layout::UNORDERED;
924 test_subarray_partitioner(
925 subarray_layout, ranges, partitions, attr, budget, unsplittable);
926
927 close_array(ctx_, array_);
928 }
929
930 TEST_CASE_METHOD(
931 SubarrayPartitionerSparseFx,
932 "SubarrayPartitioner (Sparse): 1D, multi-range, split once",
933 "[SubarrayPartitioner][sparse][1D][MR][split_once]") {
934 Layout subarray_layout;
935 SubarrayRanges<uint64_t> ranges = {{5, 10, 25, 27, 33, 50}};
936 std::vector<SubarrayRanges<uint64_t>> partitions = {{{5, 10, 25, 27}},
937 {{33, 50}}};
938 uint64_t budget = 4 * sizeof(int);
939 std::string attr = "a";
940 bool unsplittable = false;
941
942 create_default_1d_array(TILEDB_ROW_MAJOR, TILEDB_ROW_MAJOR);
943 write_default_1d_array_2();
944 open_array(ctx_, array_, TILEDB_READ);
945
946 // subarray: row
947 subarray_layout = Layout::ROW_MAJOR;
948 test_subarray_partitioner(
949 subarray_layout, ranges, partitions, attr, budget, unsplittable);
950
951 // subarray: col
952 subarray_layout = Layout::COL_MAJOR;
953 test_subarray_partitioner(
954 subarray_layout, ranges, partitions, attr, budget, unsplittable);
955
956 // subarray: unordered
957 subarray_layout = Layout::UNORDERED;
958 test_subarray_partitioner(
959 subarray_layout, ranges, partitions, attr, budget, unsplittable);
960
961 close_array(ctx_, array_);
962 }
963
964 TEST_CASE_METHOD(
965 SubarrayPartitionerSparseFx,
966 "SubarrayPartitioner (Sparse): 1D, multi-range, split multiple",
967 "[SubarrayPartitioner][sparse][1D][MR][split_multiple]") {
968 Layout subarray_layout;
969 SubarrayRanges<uint64_t> ranges = {{5, 10, 25, 27, 33, 50}};
970 std::vector<SubarrayRanges<uint64_t>> partitions = {
971 {{5, 10}}, {{25, 27}}, {{33, 50}}};
972 uint64_t budget = 2 * sizeof(int);
973 std::string attr = "a";
974 bool unsplittable = false;
975
976 create_default_1d_array(TILEDB_ROW_MAJOR, TILEDB_ROW_MAJOR);
977 write_default_1d_array_2();
978 open_array(ctx_, array_, TILEDB_READ);
979
980 // subarray: row
981 subarray_layout = Layout::ROW_MAJOR;
982 test_subarray_partitioner(
983 subarray_layout, ranges, partitions, attr, budget, unsplittable);
984
985 // subarray: col
986 subarray_layout = Layout::COL_MAJOR;
987 test_subarray_partitioner(
988 subarray_layout, ranges, partitions, attr, budget, unsplittable);
989
990 // subarray: unordered
991 subarray_layout = Layout::UNORDERED;
992 test_subarray_partitioner(
993 subarray_layout, ranges, partitions, attr, budget, unsplittable);
994
995 close_array(ctx_, array_);
996 }
997
998 TEST_CASE_METHOD(
999 SubarrayPartitionerSparseFx,
1000 "SubarrayPartitioner (Sparse): 1D, multi-range, split multiple finer",
1001 "[SubarrayPartitioner][sparse][1D][MR][split_multiple_finer]") {
1002 Layout subarray_layout;
1003 SubarrayRanges<uint64_t> ranges = {{5, 10, 25, 27, 33, 40}};
1004 std::vector<SubarrayRanges<uint64_t>> partitions = {
1005 {{5, 7}},
1006 {{8, 10}},
1007 {{25, 26}},
1008 {{27, 27}},
1009 {{33, 36}},
1010 {{37, 40}},
1011 };
1012 uint64_t budget = 2 * sizeof(int) - 1;
1013 std::string attr = "a";
1014 bool unsplittable = false;
1015
1016 create_default_1d_array(TILEDB_ROW_MAJOR, TILEDB_ROW_MAJOR);
1017 write_default_1d_array_2();
1018 open_array(ctx_, array_, TILEDB_READ);
1019
1020 // subarray: row
1021 subarray_layout = Layout::ROW_MAJOR;
1022 test_subarray_partitioner(
1023 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1024
1025 // subarray: col
1026 subarray_layout = Layout::COL_MAJOR;
1027 test_subarray_partitioner(
1028 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1029
1030 // subarray: unordered
1031 subarray_layout = Layout::UNORDERED;
1032 test_subarray_partitioner(
1033 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1034
1035 close_array(ctx_, array_);
1036 }
1037
1038 TEST_CASE_METHOD(
1039 SubarrayPartitionerSparseFx,
1040 "SubarrayPartitioner (Sparse): 1D, multi-range, unsplittable",
1041 "[SubarrayPartitioner][sparse][1D][MR][unsplittable]") {
1042 Layout subarray_layout;
1043 SubarrayRanges<uint64_t> ranges = {{5, 10, 25, 27, 33, 40}};
1044 std::vector<SubarrayRanges<uint64_t>> partitions = {{{5, 5}}};
1045 uint64_t budget = 1;
1046 std::string attr = "a";
1047 bool unsplittable = true;
1048
1049 create_default_1d_array(TILEDB_ROW_MAJOR, TILEDB_ROW_MAJOR);
1050 write_default_1d_array_2();
1051 open_array(ctx_, array_, TILEDB_READ);
1052
1053 // subarray: row
1054 subarray_layout = Layout::ROW_MAJOR;
1055 test_subarray_partitioner(
1056 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1057
1058 // subarray: col
1059 subarray_layout = Layout::COL_MAJOR;
1060 test_subarray_partitioner(
1061 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1062
1063 // subarray: unordered
1064 subarray_layout = Layout::UNORDERED;
1065 test_subarray_partitioner(
1066 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1067
1068 close_array(ctx_, array_);
1069 }
1070
1071 TEST_CASE_METHOD(
1072 SubarrayPartitionerSparseFx,
1073 "SubarrayPartitioner (Sparse): 2D, single-range, whole subarray fits",
1074 "[SubarrayPartitioner][sparse][2D][1R][whole_subarray_fits]") {
1075 Layout subarray_layout;
1076 SubarrayRanges<uint64_t> ranges = {{2, 10}, {2, 10}};
1077 std::vector<SubarrayRanges<uint64_t>> partitions = {{{2, 10}, {2, 10}}};
1078 uint64_t budget = 1000 * sizeof(uint64_t);
1079 std::string attr = TILEDB_COORDS;
1080 bool unsplittable = false;
1081
1082 SECTION("# tile: row, cell: row") {
1083 create_default_2d_array(TILEDB_ROW_MAJOR, TILEDB_ROW_MAJOR);
1084 write_default_2d_array();
1085 open_array(ctx_, array_, TILEDB_READ);
1086
1087 // subarray: global
1088 subarray_layout = Layout::GLOBAL_ORDER;
1089 test_subarray_partitioner(
1090 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1091
1092 // subarray: row
1093 subarray_layout = Layout::ROW_MAJOR;
1094 test_subarray_partitioner(
1095 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1096
1097 // subarray: col
1098 subarray_layout = Layout::COL_MAJOR;
1099 test_subarray_partitioner(
1100 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1101
1102 // subarray: unordered
1103 subarray_layout = Layout::UNORDERED;
1104 test_subarray_partitioner(
1105 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1106 }
1107
1108 SECTION("# tile: row, cell: col") {
1109 create_default_2d_array(TILEDB_ROW_MAJOR, TILEDB_COL_MAJOR);
1110 write_default_2d_array();
1111 open_array(ctx_, array_, TILEDB_READ);
1112
1113 // subarray: global
1114 subarray_layout = Layout::GLOBAL_ORDER;
1115 test_subarray_partitioner(
1116 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1117
1118 // subarray: row
1119 subarray_layout = Layout::ROW_MAJOR;
1120 test_subarray_partitioner(
1121 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1122
1123 // subarray: col
1124 subarray_layout = Layout::COL_MAJOR;
1125 test_subarray_partitioner(
1126 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1127
1128 // subarray: unordered
1129 subarray_layout = Layout::UNORDERED;
1130 test_subarray_partitioner(
1131 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1132 }
1133
1134 SECTION("# tile: col, cell: row") {
1135 create_default_2d_array(TILEDB_COL_MAJOR, TILEDB_ROW_MAJOR);
1136 write_default_2d_array();
1137 open_array(ctx_, array_, TILEDB_READ);
1138
1139 // subarray: global
1140 subarray_layout = Layout::GLOBAL_ORDER;
1141 test_subarray_partitioner(
1142 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1143
1144 // subarray: row
1145 subarray_layout = Layout::ROW_MAJOR;
1146 test_subarray_partitioner(
1147 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1148
1149 // subarray: col
1150 subarray_layout = Layout::COL_MAJOR;
1151 test_subarray_partitioner(
1152 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1153
1154 // subarray: unordered
1155 subarray_layout = Layout::UNORDERED;
1156 test_subarray_partitioner(
1157 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1158 }
1159
1160 SECTION("# tile: col, cell: col") {
1161 create_default_2d_array(TILEDB_COL_MAJOR, TILEDB_COL_MAJOR);
1162 write_default_2d_array();
1163 open_array(ctx_, array_, TILEDB_READ);
1164
1165 // subarray: global
1166 subarray_layout = Layout::GLOBAL_ORDER;
1167 test_subarray_partitioner(
1168 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1169
1170 // subarray: row
1171 subarray_layout = Layout::ROW_MAJOR;
1172 test_subarray_partitioner(
1173 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1174
1175 // subarray: col
1176 subarray_layout = Layout::COL_MAJOR;
1177 test_subarray_partitioner(
1178 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1179
1180 // subarray: unordered
1181 subarray_layout = Layout::UNORDERED;
1182 test_subarray_partitioner(
1183 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1184 }
1185
1186 close_array(ctx_, array_);
1187 }
1188
1189 TEST_CASE_METHOD(
1190 SubarrayPartitionerSparseFx,
1191 "SubarrayPartitioner (Sparse): 2D, single-range, split multiple",
1192 "[SubarrayPartitioner][sparse][2D][1R][split_multiple]") {
1193 Layout subarray_layout;
1194 SubarrayRanges<uint64_t> ranges = {{3, 4}, {1, 10}};
1195 std::vector<SubarrayRanges<uint64_t>> partitions = {};
1196 std::string attr = TILEDB_COORDS;
1197 uint64_t budget = 2 * sizeof(uint64_t);
1198
1199 SECTION("# tile: row, cell: row") {
1200 create_default_2d_array(TILEDB_ROW_MAJOR, TILEDB_ROW_MAJOR);
1201 write_default_2d_array();
1202 open_array(ctx_, array_, TILEDB_READ);
1203
1204 // subarray: global
1205 subarray_layout = Layout::GLOBAL_ORDER;
1206 partitions = {
1207 {{3, 3}, {1, 2}},
1208 {{4, 4}, {1, 2}},
1209 {{3, 4}, {3, 4}},
1210 {{3, 4}, {5, 6}},
1211 {{3, 3}, {7, 8}},
1212 {{4, 4}, {7, 8}},
1213 {{3, 4}, {9, 10}},
1214 };
1215 test_subarray_partitioner(
1216 subarray_layout, ranges, partitions, attr, budget);
1217
1218 // subarray: row
1219 subarray_layout = Layout::ROW_MAJOR;
1220 partitions = {
1221 {{3, 3}, {1, 5}},
1222 {{3, 3}, {6, 10}},
1223 {{4, 4}, {1, 5}},
1224 {{4, 4}, {6, 10}},
1225 };
1226 test_subarray_partitioner(
1227 subarray_layout, ranges, partitions, attr, budget);
1228
1229 // subarray: col
1230 subarray_layout = Layout::COL_MAJOR;
1231 partitions = {
1232 {{3, 4}, {1, 1}},
1233 {{3, 4}, {2, 2}},
1234 {{3, 4}, {3, 3}},
1235 {{3, 4}, {4, 5}},
1236 {{3, 4}, {6, 7}},
1237 {{3, 4}, {8, 8}},
1238 {{3, 4}, {9, 10}},
1239 };
1240 test_subarray_partitioner(
1241 subarray_layout, ranges, partitions, attr, budget);
1242
1243 // subarray: unordered
1244 subarray_layout = Layout::UNORDERED;
1245 partitions = {
1246 {{3, 3}, {1, 5}},
1247 {{3, 3}, {6, 10}},
1248 {{4, 4}, {1, 5}},
1249 {{4, 4}, {6, 10}},
1250 };
1251 test_subarray_partitioner(
1252 subarray_layout, ranges, partitions, attr, budget);
1253 }
1254
1255 SECTION("# tile: row, cell: col") {
1256 create_default_2d_array(TILEDB_ROW_MAJOR, TILEDB_COL_MAJOR);
1257 write_default_2d_array();
1258 open_array(ctx_, array_, TILEDB_READ);
1259
1260 // subarray: global
1261 subarray_layout = Layout::GLOBAL_ORDER;
1262 partitions = {
1263 {{3, 4}, {1, 1}},
1264 {{3, 4}, {2, 2}},
1265 {{3, 4}, {3, 4}},
1266 {{3, 4}, {5, 6}},
1267 {{3, 4}, {7, 7}},
1268 {{3, 4}, {8, 8}},
1269 {{3, 4}, {9, 10}},
1270 };
1271 test_subarray_partitioner(
1272 subarray_layout, ranges, partitions, attr, budget);
1273
1274 // subarray: row
1275 subarray_layout = Layout::ROW_MAJOR;
1276 partitions = {
1277 {{3, 3}, {1, 5}},
1278 {{3, 3}, {6, 10}},
1279 {{4, 4}, {1, 5}},
1280 {{4, 4}, {6, 10}},
1281 };
1282 test_subarray_partitioner(
1283 subarray_layout, ranges, partitions, attr, budget);
1284
1285 // subarray: col
1286 subarray_layout = Layout::COL_MAJOR;
1287 partitions = {
1288 {{3, 4}, {1, 1}},
1289 {{3, 4}, {2, 2}},
1290 {{3, 4}, {3, 3}},
1291 {{3, 4}, {4, 5}},
1292 {{3, 4}, {6, 7}},
1293 {{3, 4}, {8, 8}},
1294 {{3, 4}, {9, 10}},
1295 };
1296 test_subarray_partitioner(
1297 subarray_layout, ranges, partitions, attr, budget);
1298
1299 // subarray: unordered
1300 subarray_layout = Layout::UNORDERED;
1301 partitions = {
1302 {{3, 4}, {1, 1}},
1303 {{3, 4}, {2, 2}},
1304 {{3, 4}, {3, 3}},
1305 {{3, 4}, {4, 5}},
1306 {{3, 4}, {6, 7}},
1307 {{3, 4}, {8, 8}},
1308 {{3, 4}, {9, 10}},
1309 };
1310 test_subarray_partitioner(
1311 subarray_layout, ranges, partitions, attr, budget);
1312 }
1313
1314 SECTION("# tile: col, cell: row") {
1315 create_default_2d_array(TILEDB_COL_MAJOR, TILEDB_ROW_MAJOR);
1316 write_default_2d_array();
1317 open_array(ctx_, array_, TILEDB_READ);
1318
1319 // subarray: global
1320 subarray_layout = Layout::GLOBAL_ORDER;
1321 partitions = {
1322 {{3, 4}, {1, 2}},
1323 {{3, 4}, {3, 4}},
1324 {{3, 4}, {5, 6}},
1325 {{3, 3}, {7, 8}},
1326 {{4, 4}, {7, 8}},
1327 {{3, 4}, {9, 10}},
1328 };
1329 test_subarray_partitioner(
1330 subarray_layout, ranges, partitions, attr, budget);
1331
1332 // subarray: row
1333 subarray_layout = Layout::ROW_MAJOR;
1334 partitions = {
1335 {{3, 3}, {1, 3}},
1336 {{3, 3}, {4, 5}},
1337 {{3, 3}, {6, 10}},
1338 {{4, 4}, {1, 5}},
1339 {{4, 4}, {6, 10}},
1340 };
1341 test_subarray_partitioner(
1342 subarray_layout, ranges, partitions, attr, budget);
1343
1344 // subarray: col
1345 subarray_layout = Layout::COL_MAJOR;
1346 partitions = {
1347 {{3, 4}, {1, 2}},
1348 {{3, 4}, {3, 3}},
1349 {{3, 4}, {4, 5}},
1350 {{3, 4}, {6, 7}},
1351 {{3, 4}, {8, 8}},
1352 {{3, 4}, {9, 10}},
1353 };
1354 test_subarray_partitioner(
1355 subarray_layout, ranges, partitions, attr, budget);
1356
1357 // subarray: unordered
1358 subarray_layout = Layout::UNORDERED;
1359 partitions = {
1360 {{3, 3}, {1, 3}},
1361 {{3, 3}, {4, 5}},
1362 {{3, 3}, {6, 10}},
1363 {{4, 4}, {1, 5}},
1364 {{4, 4}, {6, 10}},
1365 };
1366 test_subarray_partitioner(
1367 subarray_layout, ranges, partitions, attr, budget);
1368 }
1369
1370 SECTION("# tile: col, cell: col") {
1371 create_default_2d_array(TILEDB_COL_MAJOR, TILEDB_COL_MAJOR);
1372 write_default_2d_array();
1373 open_array(ctx_, array_, TILEDB_READ);
1374
1375 // subarray: global
1376 subarray_layout = Layout::GLOBAL_ORDER;
1377 partitions = {
1378 {{3, 4}, {1, 2}},
1379 {{3, 4}, {3, 4}},
1380 {{3, 4}, {5, 6}},
1381 {{3, 4}, {7, 7}},
1382 {{3, 4}, {8, 8}},
1383 {{3, 4}, {9, 10}},
1384 };
1385 test_subarray_partitioner(
1386 subarray_layout, ranges, partitions, attr, budget);
1387
1388 // subarray: row
1389 subarray_layout = Layout::ROW_MAJOR;
1390 partitions = {
1391 {{3, 3}, {1, 3}},
1392 {{3, 3}, {4, 5}},
1393 {{3, 3}, {6, 10}},
1394 {{4, 4}, {1, 5}},
1395 {{4, 4}, {6, 10}},
1396 };
1397 test_subarray_partitioner(
1398 subarray_layout, ranges, partitions, attr, budget);
1399
1400 // subarray: col
1401 subarray_layout = Layout::COL_MAJOR;
1402 partitions = {
1403 {{3, 4}, {1, 2}},
1404 {{3, 4}, {3, 3}},
1405 {{3, 4}, {4, 5}},
1406 {{3, 4}, {6, 7}},
1407 {{3, 4}, {8, 8}},
1408 {{3, 4}, {9, 10}},
1409 };
1410 test_subarray_partitioner(
1411 subarray_layout, ranges, partitions, attr, budget);
1412
1413 // subarray: unordered
1414 subarray_layout = Layout::UNORDERED;
1415 partitions = {
1416 {{3, 4}, {1, 2}},
1417 {{3, 4}, {3, 3}},
1418 {{3, 4}, {4, 5}},
1419 {{3, 4}, {6, 7}},
1420 {{3, 4}, {8, 8}},
1421 {{3, 4}, {9, 10}},
1422 };
1423 test_subarray_partitioner(
1424 subarray_layout, ranges, partitions, attr, budget);
1425 }
1426
1427 close_array(ctx_, array_);
1428 }
1429
1430 TEST_CASE_METHOD(
1431 SubarrayPartitionerSparseFx,
1432 "SubarrayPartitioner (Sparse): 2D, single-range, unsplittable",
1433 "[SubarrayPartitioner][sparse][2D][1R][unsplittable]") {
1434 Layout subarray_layout;
1435 SubarrayRanges<uint64_t> ranges = {{2, 10}, {2, 10}};
1436 std::vector<SubarrayRanges<uint64_t>> partitions = {{{2, 2}, {2, 2}}};
1437 uint64_t budget = 0;
1438 std::string attr = TILEDB_COORDS;
1439 bool unsplittable = true;
1440
1441 SECTION("# tile: row, cell: row") {
1442 create_default_2d_array(TILEDB_ROW_MAJOR, TILEDB_ROW_MAJOR);
1443 write_default_2d_array();
1444 open_array(ctx_, array_, TILEDB_READ);
1445
1446 // subarray: global
1447 subarray_layout = Layout::GLOBAL_ORDER;
1448 test_subarray_partitioner(
1449 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1450
1451 // subarray: row
1452 subarray_layout = Layout::ROW_MAJOR;
1453 test_subarray_partitioner(
1454 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1455
1456 // subarray: col
1457 subarray_layout = Layout::COL_MAJOR;
1458 test_subarray_partitioner(
1459 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1460
1461 // subarray: unordered
1462 subarray_layout = Layout::UNORDERED;
1463 test_subarray_partitioner(
1464 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1465 }
1466
1467 SECTION("# tile: row, cell: col") {
1468 create_default_2d_array(TILEDB_ROW_MAJOR, TILEDB_COL_MAJOR);
1469 write_default_2d_array();
1470 open_array(ctx_, array_, TILEDB_READ);
1471
1472 // subarray: global
1473 subarray_layout = Layout::GLOBAL_ORDER;
1474 test_subarray_partitioner(
1475 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1476
1477 // subarray: row
1478 subarray_layout = Layout::ROW_MAJOR;
1479 test_subarray_partitioner(
1480 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1481
1482 // subarray: col
1483 subarray_layout = Layout::COL_MAJOR;
1484 test_subarray_partitioner(
1485 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1486
1487 // subarray: unordered
1488 subarray_layout = Layout::UNORDERED;
1489 test_subarray_partitioner(
1490 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1491 }
1492
1493 SECTION("# tile: col, cell: row") {
1494 create_default_2d_array(TILEDB_COL_MAJOR, TILEDB_ROW_MAJOR);
1495 write_default_2d_array();
1496 open_array(ctx_, array_, TILEDB_READ);
1497
1498 // subarray: global
1499 subarray_layout = Layout::GLOBAL_ORDER;
1500 test_subarray_partitioner(
1501 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1502
1503 // subarray: row
1504 subarray_layout = Layout::ROW_MAJOR;
1505 test_subarray_partitioner(
1506 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1507
1508 // subarray: col
1509 subarray_layout = Layout::COL_MAJOR;
1510 test_subarray_partitioner(
1511 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1512
1513 // subarray: unordered
1514 subarray_layout = Layout::UNORDERED;
1515 test_subarray_partitioner(
1516 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1517 }
1518
1519 SECTION("# tile: col, cell: col") {
1520 create_default_2d_array(TILEDB_COL_MAJOR, TILEDB_COL_MAJOR);
1521 write_default_2d_array();
1522 open_array(ctx_, array_, TILEDB_READ);
1523
1524 // subarray: global
1525 subarray_layout = Layout::GLOBAL_ORDER;
1526 test_subarray_partitioner(
1527 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1528
1529 // subarray: row
1530 subarray_layout = Layout::ROW_MAJOR;
1531 test_subarray_partitioner(
1532 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1533
1534 // subarray: col
1535 subarray_layout = Layout::COL_MAJOR;
1536 test_subarray_partitioner(
1537 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1538
1539 // subarray: unordered
1540 subarray_layout = Layout::UNORDERED;
1541 test_subarray_partitioner(
1542 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1543 }
1544
1545 close_array(ctx_, array_);
1546 }
1547
1548 TEST_CASE_METHOD(
1549 SubarrayPartitionerSparseFx,
1550 "SubarrayPartitioner (Sparse): 2D, multi-range, whole subarray fits",
1551 "[SubarrayPartitioner][sparse][2D][MR][whole_subarray_fits]") {
1552 Layout subarray_layout;
1553 SubarrayRanges<uint64_t> ranges = {{1, 2, 3, 3, 4, 4}, {2, 3, 4, 5}};
1554 std::vector<SubarrayRanges<uint64_t>> partitions = {
1555 {{1, 2, 3, 3, 4, 4}, {2, 3, 4, 5}}};
1556 uint64_t budget = 10000;
1557 std::string attr = "a";
1558
1559 SECTION("# tile: row, cell: row") {
1560 create_default_2d_array(TILEDB_ROW_MAJOR, TILEDB_ROW_MAJOR);
1561 write_default_2d_array();
1562 open_array(ctx_, array_, TILEDB_READ);
1563
1564 // subarray: row
1565 subarray_layout = Layout::ROW_MAJOR;
1566 test_subarray_partitioner(
1567 subarray_layout, ranges, partitions, attr, budget);
1568
1569 // subarray: col
1570 subarray_layout = Layout::COL_MAJOR;
1571 test_subarray_partitioner(
1572 subarray_layout, ranges, partitions, attr, budget);
1573
1574 // subarray: unordered
1575 subarray_layout = Layout::UNORDERED;
1576 test_subarray_partitioner(
1577 subarray_layout, ranges, partitions, attr, budget);
1578 }
1579
1580 SECTION("# tile: row, cell: col") {
1581 create_default_2d_array(TILEDB_ROW_MAJOR, TILEDB_COL_MAJOR);
1582 write_default_2d_array();
1583 open_array(ctx_, array_, TILEDB_READ);
1584
1585 // subarray: row
1586 subarray_layout = Layout::ROW_MAJOR;
1587 test_subarray_partitioner(
1588 subarray_layout, ranges, partitions, attr, budget);
1589
1590 // subarray: col
1591 subarray_layout = Layout::COL_MAJOR;
1592 test_subarray_partitioner(
1593 subarray_layout, ranges, partitions, attr, budget);
1594
1595 // subarray: unordered
1596 subarray_layout = Layout::UNORDERED;
1597 test_subarray_partitioner(
1598 subarray_layout, ranges, partitions, attr, budget);
1599 }
1600
1601 SECTION("# tile: col, cell: row") {
1602 create_default_2d_array(TILEDB_COL_MAJOR, TILEDB_ROW_MAJOR);
1603 write_default_2d_array();
1604 open_array(ctx_, array_, TILEDB_READ);
1605
1606 // subarray: row
1607 subarray_layout = Layout::ROW_MAJOR;
1608 test_subarray_partitioner(
1609 subarray_layout, ranges, partitions, attr, budget);
1610
1611 // subarray: col
1612 subarray_layout = Layout::COL_MAJOR;
1613 test_subarray_partitioner(
1614 subarray_layout, ranges, partitions, attr, budget);
1615
1616 // subarray: unordered
1617 subarray_layout = Layout::UNORDERED;
1618 test_subarray_partitioner(
1619 subarray_layout, ranges, partitions, attr, budget);
1620 }
1621
1622 SECTION("# tile: col, cell: col") {
1623 create_default_2d_array(TILEDB_COL_MAJOR, TILEDB_COL_MAJOR);
1624 write_default_2d_array();
1625 open_array(ctx_, array_, TILEDB_READ);
1626
1627 // subarray: row
1628 subarray_layout = Layout::ROW_MAJOR;
1629 test_subarray_partitioner(
1630 subarray_layout, ranges, partitions, attr, budget);
1631
1632 // subarray: col
1633 subarray_layout = Layout::COL_MAJOR;
1634 test_subarray_partitioner(
1635 subarray_layout, ranges, partitions, attr, budget);
1636
1637 // subarray: unordered
1638 subarray_layout = Layout::UNORDERED;
1639 test_subarray_partitioner(
1640 subarray_layout, ranges, partitions, attr, budget);
1641 }
1642
1643 close_array(ctx_, array_);
1644 }
1645
1646 TEST_CASE_METHOD(
1647 SubarrayPartitionerSparseFx,
1648 "SubarrayPartitioner (Sparse): 2D, multi-range, split once",
1649 "[SubarrayPartitioner][sparse][2D][MR][split_once]") {
1650 Layout subarray_layout;
1651 std::vector<SubarrayRanges<uint64_t>> partitions = {};
1652 SubarrayRanges<uint64_t> ranges;
1653 std::string attr = "a";
1654 uint64_t budget = 4 * sizeof(int);
1655
1656 SECTION("# tile: row, cell: row") {
1657 create_default_2d_array(TILEDB_ROW_MAJOR, TILEDB_ROW_MAJOR);
1658 write_default_2d_array();
1659 open_array(ctx_, array_, TILEDB_READ);
1660
1661 // subarray: row
1662 subarray_layout = Layout::ROW_MAJOR;
1663 ranges = {{1, 2, 3, 3, 4, 4}, {2, 5, 6, 9}};
1664 partitions = {{{1, 2, 3, 3}, {2, 5, 6, 9}}, {{4, 4}, {2, 5, 6, 9}}};
1665 test_subarray_partitioner(
1666 subarray_layout, ranges, partitions, attr, budget);
1667
1668 // subarray: col
1669 subarray_layout = Layout::COL_MAJOR;
1670 ranges = {{1, 2, 3, 4}, {1, 2, 3, 5, 7, 9}};
1671 partitions = {{{1, 2, 3, 4}, {1, 2, 3, 5}}, {{1, 2, 3, 4}, {7, 9}}};
1672 test_subarray_partitioner(
1673 subarray_layout, ranges, partitions, attr, budget);
1674
1675 // subarray: unordered
1676 subarray_layout = Layout::UNORDERED;
1677 ranges = {{1, 2, 3, 3, 4, 4}, {2, 5, 6, 9}};
1678 partitions = {{{1, 2, 3, 3}, {2, 5, 6, 9}}, {{4, 4}, {2, 5, 6, 9}}};
1679 test_subarray_partitioner(
1680 subarray_layout, ranges, partitions, attr, budget);
1681 }
1682
1683 SECTION("# tile: row, cell: col") {
1684 create_default_2d_array(TILEDB_ROW_MAJOR, TILEDB_COL_MAJOR);
1685 write_default_2d_array();
1686 open_array(ctx_, array_, TILEDB_READ);
1687
1688 // subarray: row
1689 subarray_layout = Layout::ROW_MAJOR;
1690 ranges = {{1, 2, 3, 3, 4, 4}, {2, 5, 6, 9}};
1691 partitions = {{{1, 2, 3, 3}, {2, 5, 6, 9}}, {{4, 4}, {2, 5, 6, 9}}};
1692 test_subarray_partitioner(
1693 subarray_layout, ranges, partitions, attr, budget);
1694
1695 // subarray: col
1696 subarray_layout = Layout::COL_MAJOR;
1697 ranges = {{1, 2, 3, 4}, {1, 2, 3, 5, 7, 9}};
1698 partitions = {{{1, 2, 3, 4}, {1, 2, 3, 5}}, {{1, 2, 3, 4}, {7, 9}}};
1699 test_subarray_partitioner(
1700 subarray_layout, ranges, partitions, attr, budget);
1701
1702 // subarray: unordered
1703 subarray_layout = Layout::UNORDERED;
1704 ranges = {{1, 2, 3, 4}, {1, 2, 3, 5, 7, 9}};
1705 partitions = {{{1, 2, 3, 4}, {1, 2, 3, 5}}, {{1, 2, 3, 4}, {7, 9}}};
1706 test_subarray_partitioner(
1707 subarray_layout, ranges, partitions, attr, budget);
1708 }
1709
1710 SECTION("# tile: col, cell: row") {
1711 create_default_2d_array(TILEDB_COL_MAJOR, TILEDB_ROW_MAJOR);
1712 write_default_2d_array();
1713 open_array(ctx_, array_, TILEDB_READ);
1714
1715 // subarray: row
1716 subarray_layout = Layout::ROW_MAJOR;
1717 ranges = {{1, 2, 3, 3, 4, 4}, {2, 5, 6, 9}};
1718 partitions = {{{1, 2, 3, 3}, {2, 5, 6, 9}}, {{4, 4}, {2, 5, 6, 9}}};
1719 test_subarray_partitioner(
1720 subarray_layout, ranges, partitions, attr, budget);
1721
1722 // subarray: col
1723 subarray_layout = Layout::COL_MAJOR;
1724 ranges = {{1, 2, 3, 4}, {1, 2, 3, 5, 7, 9}};
1725 partitions = {{{1, 2, 3, 4}, {1, 2, 3, 5}}, {{1, 2, 3, 4}, {7, 9}}};
1726 test_subarray_partitioner(
1727 subarray_layout, ranges, partitions, attr, budget);
1728
1729 // subarray: unordered
1730 subarray_layout = Layout::UNORDERED;
1731 ranges = {{1, 2, 3, 3, 4, 4}, {2, 5, 6, 9}};
1732 partitions = {{{1, 2, 3, 3}, {2, 5, 6, 9}}, {{4, 4}, {2, 5, 6, 9}}};
1733 test_subarray_partitioner(
1734 subarray_layout, ranges, partitions, attr, budget);
1735 }
1736
1737 SECTION("# tile: col, cell: col") {
1738 create_default_2d_array(TILEDB_COL_MAJOR, TILEDB_COL_MAJOR);
1739 write_default_2d_array();
1740 open_array(ctx_, array_, TILEDB_READ);
1741
1742 // subarray: row
1743 subarray_layout = Layout::ROW_MAJOR;
1744 ranges = {{1, 2, 3, 3, 4, 4}, {2, 5, 6, 9}};
1745 partitions = {{{1, 2, 3, 3}, {2, 5, 6, 9}}, {{4, 4}, {2, 5, 6, 9}}};
1746 test_subarray_partitioner(
1747 subarray_layout, ranges, partitions, attr, budget);
1748
1749 // subarray: col
1750 subarray_layout = Layout::COL_MAJOR;
1751 ranges = {{1, 2, 3, 4}, {1, 2, 3, 5, 7, 9}};
1752 partitions = {{{1, 2, 3, 4}, {1, 2, 3, 5}}, {{1, 2, 3, 4}, {7, 9}}};
1753 test_subarray_partitioner(
1754 subarray_layout, ranges, partitions, attr, budget);
1755
1756 // subarray: unordered
1757 subarray_layout = Layout::UNORDERED;
1758 ranges = {{1, 2, 3, 4}, {1, 2, 3, 5, 7, 9}};
1759 partitions = {{{1, 2, 3, 4}, {1, 2, 3, 5}}, {{1, 2, 3, 4}, {7, 9}}};
1760 test_subarray_partitioner(
1761 subarray_layout, ranges, partitions, attr, budget);
1762 }
1763
1764 close_array(ctx_, array_);
1765 }
1766
1767 /**
1768 * Tests subarray range calibration, such that the ranges involved
1769 * in the next partition fall in the same slab (or fall in a single
1770 * slab in case the subarray layout is UNORDERED).
1771 */
1772 TEST_CASE_METHOD(
1773 SubarrayPartitionerSparseFx,
1774 "SubarrayPartitioner (Sparse): 2D, multi-range, calibrate",
1775 "[SubarrayPartitioner][sparse][2D][MR][calibrate]") {
1776 Layout subarray_layout;
1777 std::vector<SubarrayRanges<uint64_t>> partitions = {};
1778 SubarrayRanges<uint64_t> ranges;
1779 std::string attr = "a";
1780 uint64_t budget = 5 * sizeof(int);
1781
1782 SECTION("# tile: row, cell: row") {
1783 create_default_2d_array(TILEDB_ROW_MAJOR, TILEDB_ROW_MAJOR);
1784 write_default_2d_array();
1785 open_array(ctx_, array_, TILEDB_READ);
1786
1787 // subarray: row
1788 subarray_layout = Layout::ROW_MAJOR;
1789 ranges = {{1, 2, 3, 3, 4, 4}, {2, 5, 6, 9}};
1790 partitions = {{{1, 2, 3, 3}, {2, 5, 6, 9}}, {{4, 4}, {2, 5, 6, 9}}};
1791 test_subarray_partitioner(
1792 subarray_layout, ranges, partitions, attr, budget);
1793
1794 // subarray: col
1795 subarray_layout = Layout::COL_MAJOR;
1796 ranges = {{1, 2, 3, 4}, {1, 2, 3, 5, 7, 9}};
1797 partitions = {{{1, 2, 3, 4}, {1, 2, 3, 5}}, {{1, 2, 3, 4}, {7, 9}}};
1798 test_subarray_partitioner(
1799 subarray_layout, ranges, partitions, attr, budget);
1800
1801 // subarray: unordered
1802 subarray_layout = Layout::UNORDERED;
1803 ranges = {{1, 2, 3, 3, 4, 4}, {2, 5, 6, 9}};
1804 partitions = {{{1, 2, 3, 3}, {2, 5, 6, 9}}, {{4, 4}, {2, 5, 6, 9}}};
1805 test_subarray_partitioner(
1806 subarray_layout, ranges, partitions, attr, budget);
1807 }
1808
1809 SECTION("# tile: row, cell: col") {
1810 create_default_2d_array(TILEDB_ROW_MAJOR, TILEDB_COL_MAJOR);
1811 write_default_2d_array();
1812 open_array(ctx_, array_, TILEDB_READ);
1813
1814 // subarray: row
1815 subarray_layout = Layout::ROW_MAJOR;
1816 ranges = {{1, 2, 3, 3, 4, 4}, {2, 5, 6, 9}};
1817 partitions = {{{1, 2, 3, 3}, {2, 5, 6, 9}}, {{4, 4}, {2, 5, 6, 9}}};
1818 test_subarray_partitioner(
1819 subarray_layout, ranges, partitions, attr, budget);
1820
1821 // subarray: col
1822 subarray_layout = Layout::COL_MAJOR;
1823 ranges = {{1, 2, 3, 4}, {1, 2, 3, 5, 7, 9}};
1824 partitions = {{{1, 2, 3, 4}, {1, 2, 3, 5}}, {{1, 2, 3, 4}, {7, 9}}};
1825 test_subarray_partitioner(
1826 subarray_layout, ranges, partitions, attr, budget);
1827
1828 // subarray: unordered
1829 subarray_layout = Layout::UNORDERED;
1830 ranges = {{1, 2, 3, 4}, {1, 2, 3, 5, 7, 9}};
1831 partitions = {{{1, 2, 3, 4}, {1, 2, 3, 5}}, {{1, 2, 3, 4}, {7, 9}}};
1832 test_subarray_partitioner(
1833 subarray_layout, ranges, partitions, attr, budget);
1834 }
1835
1836 SECTION("# tile: col, cell: row") {
1837 create_default_2d_array(TILEDB_COL_MAJOR, TILEDB_ROW_MAJOR);
1838 write_default_2d_array();
1839 open_array(ctx_, array_, TILEDB_READ);
1840
1841 // subarray: row
1842 subarray_layout = Layout::ROW_MAJOR;
1843 ranges = {{1, 2, 3, 3, 4, 4}, {2, 5, 6, 9}};
1844 partitions = {{{1, 2, 3, 3, 4, 4}, {2, 5, 6, 9}}};
1845 test_subarray_partitioner(
1846 subarray_layout, ranges, partitions, attr, budget);
1847
1848 // subarray: col
1849 subarray_layout = Layout::COL_MAJOR;
1850 ranges = {{1, 2, 3, 4}, {2, 5, 7, 9}};
1851 partitions = {{{1, 2, 3, 4}, {2, 5, 7, 9}}};
1852 test_subarray_partitioner(
1853 subarray_layout, ranges, partitions, attr, budget);
1854
1855 // subarray: unordered
1856 subarray_layout = Layout::UNORDERED;
1857 ranges = {{1, 2, 3, 3, 4, 4}, {2, 5, 6, 9}};
1858 partitions = {{{1, 2, 3, 3, 4, 4}, {2, 5, 6, 9}}};
1859 test_subarray_partitioner(
1860 subarray_layout, ranges, partitions, attr, budget);
1861 }
1862
1863 SECTION("# tile: col, cell: col") {
1864 create_default_2d_array(TILEDB_COL_MAJOR, TILEDB_COL_MAJOR);
1865 write_default_2d_array();
1866 open_array(ctx_, array_, TILEDB_READ);
1867
1868 // subarray: row
1869 subarray_layout = Layout::ROW_MAJOR;
1870 ranges = {{1, 2, 3, 3, 4, 4}, {2, 5, 6, 9}};
1871 partitions = {{{1, 2, 3, 3, 4, 4}, {2, 5, 6, 9}}};
1872 test_subarray_partitioner(
1873 subarray_layout, ranges, partitions, attr, budget);
1874
1875 // subarray: col
1876 subarray_layout = Layout::COL_MAJOR;
1877 ranges = {{1, 2, 3, 4}, {2, 5, 7, 9}};
1878 partitions = {{{1, 2, 3, 4}, {2, 5, 7, 9}}};
1879 test_subarray_partitioner(
1880 subarray_layout, ranges, partitions, attr, budget);
1881
1882 // subarray: unordered
1883 subarray_layout = Layout::UNORDERED;
1884 ranges = {{1, 2, 3, 4}, {2, 5, 7, 9}};
1885 partitions = {{{1, 2, 3, 4}, {2, 5, 7, 9}}};
1886 test_subarray_partitioner(
1887 subarray_layout, ranges, partitions, attr, budget);
1888 }
1889
1890 close_array(ctx_, array_);
1891 }
1892
1893 TEST_CASE_METHOD(
1894 SubarrayPartitionerSparseFx,
1895 "SubarrayPartitioner (Sparse): 2D, multi-range, unsplittable",
1896 "[SubarrayPartitioner][sparse][2D][MR][unsplittable]") {
1897 Layout subarray_layout;
1898 std::vector<SubarrayRanges<uint64_t>> partitions = {{{1, 1}, {2, 2}}};
1899 SubarrayRanges<uint64_t> ranges = {{1, 2, 3, 3, 4, 4}, {2, 5, 6, 9}};
1900 std::string attr = "a";
1901 uint64_t budget = 0;
1902 bool unsplittable = true;
1903
1904 SECTION("# tile: row, cell: row") {
1905 create_default_2d_array(TILEDB_ROW_MAJOR, TILEDB_ROW_MAJOR);
1906 write_default_2d_array();
1907 open_array(ctx_, array_, TILEDB_READ);
1908
1909 // subarray: row
1910 subarray_layout = Layout::ROW_MAJOR;
1911 test_subarray_partitioner(
1912 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1913
1914 // subarray: col
1915 subarray_layout = Layout::COL_MAJOR;
1916 test_subarray_partitioner(
1917 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1918
1919 // subarray: unordered
1920 subarray_layout = Layout::UNORDERED;
1921 test_subarray_partitioner(
1922 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1923 }
1924
1925 SECTION("# tile: row, cell: col") {
1926 create_default_2d_array(TILEDB_ROW_MAJOR, TILEDB_COL_MAJOR);
1927 write_default_2d_array();
1928 open_array(ctx_, array_, TILEDB_READ);
1929
1930 // subarray: row
1931 subarray_layout = Layout::ROW_MAJOR;
1932 test_subarray_partitioner(
1933 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1934
1935 // subarray: col
1936 subarray_layout = Layout::COL_MAJOR;
1937 test_subarray_partitioner(
1938 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1939
1940 // subarray: unordered
1941 subarray_layout = Layout::UNORDERED;
1942 test_subarray_partitioner(
1943 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1944 }
1945
1946 SECTION("# tile: col, cell: row") {
1947 create_default_2d_array(TILEDB_COL_MAJOR, TILEDB_ROW_MAJOR);
1948 write_default_2d_array();
1949 open_array(ctx_, array_, TILEDB_READ);
1950
1951 // subarray: row
1952 subarray_layout = Layout::ROW_MAJOR;
1953 test_subarray_partitioner(
1954 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1955
1956 // subarray: col
1957 subarray_layout = Layout::COL_MAJOR;
1958 test_subarray_partitioner(
1959 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1960
1961 // subarray: unordered
1962 subarray_layout = Layout::UNORDERED;
1963 test_subarray_partitioner(
1964 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1965 }
1966
1967 SECTION("# tile: col, cell: col") {
1968 create_default_2d_array(TILEDB_COL_MAJOR, TILEDB_COL_MAJOR);
1969 write_default_2d_array();
1970 open_array(ctx_, array_, TILEDB_READ);
1971
1972 // subarray: row
1973 subarray_layout = Layout::ROW_MAJOR;
1974 test_subarray_partitioner(
1975 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1976
1977 // subarray: col
1978 subarray_layout = Layout::COL_MAJOR;
1979 test_subarray_partitioner(
1980 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1981
1982 // subarray: unordered
1983 subarray_layout = Layout::UNORDERED;
1984 test_subarray_partitioner(
1985 subarray_layout, ranges, partitions, attr, budget, unsplittable);
1986 }
1987
1988 close_array(ctx_, array_);
1989 }
1990
1991 TEST_CASE_METHOD(
1992 SubarrayPartitionerSparseFx,
1993 "SubarrayPartitioner (Sparse): 2D, multi-range, split multiple finer",
1994 "[SubarrayPartitioner][sparse][2D][MR][split_multiple_finer]") {
1995 Layout subarray_layout;
1996 std::vector<SubarrayRanges<uint64_t>> partitions = {};
1997 SubarrayRanges<uint64_t> ranges = {{1, 2, 3, 3, 4, 4}, {2, 5, 6, 9}};
1998 std::string attr = "a";
1999 uint64_t budget = sizeof(int);
2000
2001 SECTION("# tile: row, cell: row") {
2002 create_default_2d_array(TILEDB_ROW_MAJOR, TILEDB_ROW_MAJOR);
2003 write_default_2d_array();
2004 open_array(ctx_, array_, TILEDB_READ);
2005
2006 // subarray: row
2007 subarray_layout = Layout::ROW_MAJOR;
2008 partitions = {
2009 {{1, 1}, {2, 5, 6, 9}},
2010 {{2, 2}, {2, 5, 6, 9}},
2011 {{3, 3}, {2, 5}},
2012 {{3, 3}, {6, 9}},
2013 {{4, 4}, {2, 5}},
2014 {{4, 4}, {6, 9}},
2015 };
2016 test_subarray_partitioner(
2017 subarray_layout, ranges, partitions, attr, budget);
2018
2019 // subarray: col
2020 subarray_layout = Layout::COL_MAJOR;
2021 partitions = {
2022 {{1, 2, 3, 3}, {2, 2}},
2023 {{4, 4}, {2, 2}},
2024 {{1, 2, 3, 3}, {3, 3}},
2025 {{4, 4}, {3, 3}},
2026 {{1, 2, 3, 3, 4, 4}, {4, 5}},
2027 {{1, 2, 3, 3, 4, 4}, {6, 7}},
2028 {{1, 2, 3, 3, 4, 4}, {8, 8}},
2029 {{1, 2, 3, 3, 4, 4}, {9, 9}},
2030 };
2031 test_subarray_partitioner(
2032 subarray_layout, ranges, partitions, attr, budget);
2033
2034 // subarray: unordered
2035 subarray_layout = Layout::UNORDERED;
2036 partitions = {
2037 {{1, 1}, {2, 5}},
2038 {{2, 2}, {2, 5}},
2039 {{1, 2}, {6, 9}},
2040 {{3, 3}, {2, 5}},
2041 {{3, 3}, {6, 9}},
2042 {{4, 4}, {2, 5}},
2043 {{4, 4}, {6, 9}},
2044 };
2045 test_subarray_partitioner(
2046 subarray_layout, ranges, partitions, attr, budget);
2047 }
2048
2049 SECTION("# tile: row, cell: col") {
2050 create_default_2d_array(TILEDB_ROW_MAJOR, TILEDB_COL_MAJOR);
2051 write_default_2d_array();
2052 open_array(ctx_, array_, TILEDB_READ);
2053
2054 // subarray: row
2055 subarray_layout = Layout::ROW_MAJOR;
2056 partitions = {
2057 {{1, 1}, {2, 5, 6, 9}},
2058 {{2, 2}, {2, 5, 6, 9}},
2059 {{3, 3}, {2, 5}},
2060 {{3, 3}, {6, 9}},
2061 {{4, 4}, {2, 5}},
2062 {{4, 4}, {6, 9}},
2063 };
2064 test_subarray_partitioner(
2065 subarray_layout, ranges, partitions, attr, budget);
2066
2067 // subarray: col
2068 subarray_layout = Layout::COL_MAJOR;
2069 partitions = {
2070 {{1, 2, 3, 3}, {2, 2}},
2071 {{4, 4}, {2, 2}},
2072 {{1, 2, 3, 3}, {3, 3}},
2073 {{4, 4}, {3, 3}},
2074 {{1, 2, 3, 3, 4, 4}, {4, 5}},
2075 {{1, 2, 3, 3, 4, 4}, {6, 7}},
2076 {{1, 2, 3, 3, 4, 4}, {8, 8}},
2077 {{1, 2, 3, 3, 4, 4}, {9, 9}},
2078 };
2079 test_subarray_partitioner(
2080 subarray_layout, ranges, partitions, attr, budget);
2081
2082 // subarray: unordered
2083 subarray_layout = Layout::UNORDERED;
2084 partitions = {
2085 {{1, 2}, {2, 3}},
2086 {{1, 2}, {4, 5}},
2087 {{3, 3}, {2, 5}},
2088 {{4, 4}, {2, 5}},
2089 {{1, 2, 3, 3}, {6, 9}},
2090 {{4, 4}, {6, 9}},
2091 };
2092 test_subarray_partitioner(
2093 subarray_layout, ranges, partitions, attr, budget);
2094 }
2095
2096 SECTION("# tile: col, cell: row") {
2097 create_default_2d_array(TILEDB_COL_MAJOR, TILEDB_ROW_MAJOR);
2098 write_default_2d_array();
2099 open_array(ctx_, array_, TILEDB_READ);
2100
2101 // subarray: row
2102 subarray_layout = Layout::ROW_MAJOR;
2103 partitions = {
2104 {{1, 1}, {2, 5, 6, 9}},
2105 {{2, 2}, {2, 3}},
2106 {{2, 2}, {4, 5}},
2107 {{2, 2}, {6, 9}},
2108 {{3, 3}, {2, 3}},
2109 {{3, 3}, {4, 5}},
2110 {{3, 3}, {6, 9}},
2111 {{4, 4}, {2, 5}},
2112 {{4, 4}, {6, 9}},
2113 };
2114 test_subarray_partitioner(
2115 subarray_layout, ranges, partitions, attr, budget);
2116
2117 // subarray: col
2118 subarray_layout = Layout::COL_MAJOR;
2119 partitions = {
2120 {{1, 2, 3, 3, 4, 4}, {2, 2}},
2121 {{1, 2, 3, 3, 4, 4}, {3, 3}},
2122 {{1, 2, 3, 3, 4, 4}, {4, 4}},
2123 {{1, 2, 3, 3, 4, 4}, {5, 5}},
2124 {{1, 2, 3, 3, 4, 4}, {6, 7}},
2125 {{1, 2, 3, 3, 4, 4}, {8, 8}},
2126 {{1, 2, 3, 3, 4, 4}, {9, 9}},
2127 };
2128 test_subarray_partitioner(
2129 subarray_layout, ranges, partitions, attr, budget);
2130
2131 // subarray: unordered
2132 subarray_layout = Layout::UNORDERED;
2133 partitions = {
2134 {{1, 1}, {2, 5}},
2135 {{2, 2}, {2, 3}},
2136 {{2, 2}, {4, 5}},
2137 {{1, 2}, {6, 9}},
2138 {{3, 3}, {2, 3}},
2139 {{3, 3}, {4, 5}},
2140 {{3, 3}, {6, 9}},
2141 {{4, 4}, {2, 5}},
2142 {{4, 4}, {6, 9}},
2143 };
2144 test_subarray_partitioner(
2145 subarray_layout, ranges, partitions, attr, budget);
2146 }
2147
2148 SECTION("# tile: col, cell: col") {
2149 create_default_2d_array(TILEDB_COL_MAJOR, TILEDB_COL_MAJOR);
2150 write_default_2d_array();
2151 open_array(ctx_, array_, TILEDB_READ);
2152
2153 // subarray: row
2154 subarray_layout = Layout::ROW_MAJOR;
2155 partitions = {
2156 {{1, 1}, {2, 5, 6, 9}},
2157 {{2, 2}, {2, 3}},
2158 {{2, 2}, {4, 5}},
2159 {{2, 2}, {6, 9}},
2160 {{3, 3}, {2, 3}},
2161 {{3, 3}, {4, 5}},
2162 {{3, 3}, {6, 9}},
2163 {{4, 4}, {2, 5}},
2164 {{4, 4}, {6, 9}},
2165 };
2166 test_subarray_partitioner(
2167 subarray_layout, ranges, partitions, attr, budget);
2168
2169 // subarray: col
2170 subarray_layout = Layout::COL_MAJOR;
2171 partitions = {
2172 {{1, 2, 3, 3, 4, 4}, {2, 2}},
2173 {{1, 2, 3, 3, 4, 4}, {3, 3}},
2174 {{1, 2, 3, 3, 4, 4}, {4, 4}},
2175 {{1, 2, 3, 3, 4, 4}, {5, 5}},
2176 {{1, 2, 3, 3, 4, 4}, {6, 7}},
2177 {{1, 2, 3, 3, 4, 4}, {8, 8}},
2178 {{1, 2, 3, 3, 4, 4}, {9, 9}},
2179 };
2180 test_subarray_partitioner(
2181 subarray_layout, ranges, partitions, attr, budget);
2182
2183 // subarray: unordered
2184 subarray_layout = Layout::UNORDERED;
2185 partitions = {
2186 {{1, 2}, {2, 3}},
2187 {{1, 2}, {4, 5}},
2188 {{3, 3}, {2, 3}},
2189 {{3, 3}, {4, 5}},
2190 {{4, 4}, {2, 5}},
2191 {{1, 2, 3, 3}, {6, 9}},
2192 {{4, 4}, {6, 9}},
2193 };
2194 test_subarray_partitioner(
2195 subarray_layout, ranges, partitions, attr, budget);
2196 }
2197
2198 close_array(ctx_, array_);
2199 }
2200
2201 TEST_CASE_METHOD(
2202 SubarrayPartitionerSparseFx,
2203 "SubarrayPartitioner (Sparse): 1D, single-range, string dimension",
2204 "[SubarrayPartitioner][sparse][1D][SR][string-dims][basic]") {
2205 // Create array
2206 create_array(
2207 ctx_,
2208 array_name_,
2209 TILEDB_SPARSE,
2210 {"d"},
2211 {TILEDB_STRING_ASCII},
2212 {nullptr},
2213 {nullptr},
2214 {"a"},
2215 {TILEDB_INT32},
2216 {1},
2217 {tiledb::test::Compressor(TILEDB_FILTER_NONE, -1)},
2218 TILEDB_ROW_MAJOR,
2219 TILEDB_ROW_MAJOR,
2220 2,
2221 false,
2222 false);
2223
2224 // ####### WRITE #######
2225
2226 // Open array
2227 tiledb_array_t* array;
2228 int rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array);
2229 CHECK(rc == TILEDB_OK);
2230 rc = tiledb_array_open(ctx_, array, TILEDB_WRITE);
2231 CHECK(rc == TILEDB_OK);
2232
2233 // Create and submit query
2234 tiledb_query_t* query;
2235 rc = tiledb_query_alloc(ctx_, array, TILEDB_WRITE, &query);
2236 REQUIRE(rc == TILEDB_OK);
2237
2238 char d_data[] = "ccbbccddaa";
2239 uint64_t d_data_size = sizeof(d_data) - 1; // Ignore '\0'
2240 uint64_t d_off[] = {0, 2, 4, 8};
2241 uint64_t d_off_size = sizeof(d_off);
2242 int32_t a_data[] = {3, 2, 4, 1};
2243 uint64_t a_size = sizeof(a_data);
2244 rc = tiledb_query_set_data_buffer(ctx_, query, "d", d_data, &d_data_size);
2245 REQUIRE(rc == TILEDB_OK);
2246 rc = tiledb_query_set_offsets_buffer(ctx_, query, "d", d_off, &d_off_size);
2247 REQUIRE(rc == TILEDB_OK);
2248 rc = tiledb_query_set_data_buffer(ctx_, query, "a", a_data, &a_size);
2249 REQUIRE(rc == TILEDB_OK);
2250 rc = tiledb_query_set_layout(ctx_, query, TILEDB_UNORDERED);
2251 REQUIRE(rc == TILEDB_OK);
2252 rc = tiledb_query_submit(ctx_, query);
2253 REQUIRE(rc == TILEDB_OK);
2254
2255 // Close array
2256 rc = tiledb_array_close(ctx_, array);
2257 CHECK(rc == TILEDB_OK);
2258 tiledb_array_free(&array);
2259
2260 // #### PARTITIONER ####
2261
2262 // Open array
2263 rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array);
2264 CHECK(rc == TILEDB_OK);
2265 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
2266 CHECK(rc == TILEDB_OK);
2267
2268 Layout layout = Layout::ROW_MAJOR;
2269
2270 SECTION("Global order") {
2271 layout = Layout::GLOBAL_ORDER;
2272 }
2273
2274 SECTION("Row-major") {
2275 layout = Layout::ROW_MAJOR;
2276 }
2277
2278 SECTION("Col-major") {
2279 layout = Layout::COL_MAJOR;
2280 }
2281
2282 SECTION("Unordered") {
2283 layout = Layout::UNORDERED;
2284 }
2285
2286 // Check unsplittable
2287 tiledb::sm::Subarray subarray(
2288 array->array_, layout, &g_helper_stats, g_helper_logger());
2289 tiledb::sm::Range r;
2290 r.set_str_range("bb", "bb");
2291 subarray.add_range(0, std::move(r), true);
2292 ThreadPool tp;
2293 CHECK(tp.init(4).ok());
2294 Config config;
2295 SubarrayPartitioner partitioner(
2296 &config,
2297 subarray,
2298 memory_budget_,
2299 memory_budget_var_,
2300 0,
2301 &tp,
2302 &g_helper_stats,
2303 g_helper_logger());
2304 auto st = partitioner.set_result_budget("d", 10);
2305 CHECK(!st.ok());
2306 uint64_t budget = 0;
2307 CHECK(!partitioner.get_result_budget("d", &budget).ok());
2308 st = partitioner.set_result_budget("d", 10, 1);
2309 CHECK(st.ok());
2310 uint64_t budget_off = 0, budget_val = 0;
2311 CHECK(partitioner.get_result_budget("d", &budget_off, &budget_val).ok());
2312 CHECK(budget_off == 10);
2313 CHECK(budget_val == 1);
2314 bool unsplittable = true;
2315 CHECK(partitioner.next(&unsplittable).ok());
2316 CHECK(unsplittable);
2317 auto partition = partitioner.current();
2318 CHECK(partition.range_num() == 1);
2319 const Range* range = nullptr;
2320 partition.get_range(0, 0, &range);
2321 CHECK(range != nullptr);
2322 CHECK(range->start_str() == std::string("bb", 2));
2323 CHECK(range->end_str() == std::string("bb", 2));
2324
2325 // Check full
2326 tiledb::sm::Subarray subarray_full(
2327 array->array_, layout, &g_helper_stats, g_helper_logger());
2328 r.set_str_range("a", "bb");
2329 subarray_full.add_range(0, std::move(r), true);
2330 SubarrayPartitioner partitioner_full(
2331 &config,
2332 subarray_full,
2333 memory_budget_,
2334 memory_budget_var_,
2335 0,
2336 &tp,
2337 &g_helper_stats,
2338 g_helper_logger());
2339 st = partitioner_full.set_result_budget("d", 16, 4);
2340 CHECK(st.ok());
2341 CHECK(partitioner_full.get_result_budget("d", &budget_off, &budget_val).ok());
2342 CHECK(budget_off == 16);
2343 CHECK(budget_val == 4);
2344 CHECK(partitioner_full.next(&unsplittable).ok());
2345 CHECK(!unsplittable);
2346 partition = partitioner_full.current();
2347 CHECK(partition.range_num() == 1);
2348 partition.get_range(0, 0, &range);
2349 CHECK(range != nullptr);
2350 CHECK(range->start_str() == std::string("a", 1));
2351 CHECK(range->end_str() == std::string("bb", 2));
2352
2353 // Check split
2354 tiledb::sm::Subarray subarray_split(
2355 array->array_, layout, &g_helper_stats, g_helper_logger());
2356 r.set_str_range("a", "bb");
2357 subarray_split.add_range(0, std::move(r), true);
2358 SubarrayPartitioner partitioner_split(
2359 &config,
2360 subarray_split,
2361 memory_budget_,
2362 memory_budget_var_,
2363 0,
2364 &tp,
2365 &g_helper_stats,
2366 g_helper_logger());
2367 st = partitioner_split.set_result_budget("d", 10, 4);
2368 CHECK(st.ok());
2369 CHECK(
2370 partitioner_split.get_result_budget("d", &budget_off, &budget_val).ok());
2371 CHECK(budget_off == 10);
2372 CHECK(budget_val == 4);
2373 CHECK(partitioner_split.next(&unsplittable).ok());
2374 CHECK(!unsplittable);
2375 partition = partitioner_split.current();
2376 CHECK(partition.range_num() == 1);
2377 partition.get_range(0, 0, &range);
2378 CHECK(range != nullptr);
2379 CHECK(range->start_str() == std::string("a", 1));
2380 CHECK(range->end_str() == std::string("a\x7F", 2));
2381 CHECK(partitioner_split.next(&unsplittable).ok());
2382 CHECK(!unsplittable);
2383 partition = partitioner_split.current();
2384 CHECK(partition.range_num() == 1);
2385 partition.get_range(0, 0, &range);
2386 CHECK(range != nullptr);
2387 CHECK(range->start_str() == std::string("b", 1));
2388 CHECK(range->end_str() == std::string("bb", 2));
2389 CHECK(partitioner_split.done());
2390
2391 // Check no split 2 MBRs
2392 tiledb::sm::Subarray subarray_no_split(
2393 array->array_, layout, &g_helper_stats, g_helper_logger());
2394 r.set_str_range("bb", "cc");
2395 subarray_no_split.add_range(0, std::move(r), true);
2396 SubarrayPartitioner partitioner_no_split(
2397 &config,
2398 subarray_no_split,
2399 memory_budget_,
2400 memory_budget_var_,
2401 0,
2402 &tp,
2403 &g_helper_stats,
2404 g_helper_logger());
2405 st = partitioner_no_split.set_result_budget("d", 16, 10);
2406 CHECK(st.ok());
2407 CHECK(partitioner_no_split.get_result_budget("d", &budget_off, &budget_val)
2408 .ok());
2409 CHECK(budget_off == 16);
2410 CHECK(budget_val == 10);
2411 CHECK(partitioner_no_split.next(&unsplittable).ok());
2412 CHECK(partitioner_no_split.done());
2413 CHECK(!unsplittable);
2414 partition = partitioner_no_split.current();
2415 CHECK(partition.range_num() == 1);
2416 partition.get_range(0, 0, &range);
2417 CHECK(range != nullptr);
2418 CHECK(range->start_str() == std::string("bb", 2));
2419 CHECK(range->end_str() == std::string("cc", 2));
2420
2421 // Check split 2 MBRs
2422 tiledb::sm::Subarray subarray_split_2(
2423 array->array_, layout, &g_helper_stats, g_helper_logger());
2424 r.set_str_range("bb", "cc");
2425 subarray_split_2.add_range(0, std::move(r), true);
2426 SubarrayPartitioner partitioner_split_2(
2427 &config,
2428 subarray_split_2,
2429 memory_budget_,
2430 memory_budget_var_,
2431 0,
2432 &tp,
2433 &g_helper_stats,
2434 g_helper_logger());
2435 st = partitioner_split_2.set_result_budget("d", 8, 10);
2436 CHECK(st.ok());
2437 CHECK(partitioner_split_2.get_result_budget("d", &budget_off, &budget_val)
2438 .ok());
2439 CHECK(budget_off == 8);
2440 CHECK(budget_val == 10);
2441 CHECK(partitioner_split_2.next(&unsplittable).ok());
2442 CHECK(!partitioner_split_2.done());
2443 CHECK(!unsplittable);
2444 partition = partitioner_split_2.current();
2445 CHECK(partition.range_num() == 1);
2446 partition.get_range(0, 0, &range);
2447 CHECK(range != nullptr);
2448 CHECK(range->start_str() == std::string("bb", 2));
2449 CHECK(range->end_str() == std::string("b\x7F", 2));
2450 CHECK(partitioner_split_2.next(&unsplittable).ok());
2451 CHECK(!unsplittable);
2452 partition = partitioner_split_2.current();
2453 CHECK(partition.range_num() == 1);
2454 partition.get_range(0, 0, &range);
2455 CHECK(range != nullptr);
2456 CHECK(range->start_str() == std::string("c", 1));
2457 CHECK(range->end_str() == std::string("cc", 2));
2458 CHECK(partitioner_split_2.done());
2459
2460 // Close array
2461 rc = tiledb_array_close(ctx_, array);
2462 CHECK(rc == TILEDB_OK);
2463
2464 // Clean up
2465 tiledb_array_free(&array);
2466 tiledb_query_free(&query);
2467 }
2468
2469 TEST_CASE_METHOD(
2470 SubarrayPartitionerSparseFx,
2471 "SubarrayPartitioner (Sparse): 1D, single-range, string dimension, edge "
2472 "split",
2473 "[SubarrayPartitioner][sparse][1D][SR][string-dims][edge-split]") {
2474 // Create array
2475 create_array(
2476 ctx_,
2477 array_name_,
2478 TILEDB_SPARSE,
2479 {"d"},
2480 {TILEDB_STRING_ASCII},
2481 {nullptr},
2482 {nullptr},
2483 {"a"},
2484 {TILEDB_INT32},
2485 {1},
2486 {tiledb::test::Compressor(TILEDB_FILTER_NONE, -1)},
2487 TILEDB_ROW_MAJOR,
2488 TILEDB_ROW_MAJOR,
2489 4,
2490 false,
2491 false);
2492
2493 // ####### WRITE #######
2494
2495 // Open array
2496 tiledb_array_t* array;
2497 int rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array);
2498 CHECK(rc == TILEDB_OK);
2499 rc = tiledb_array_open(ctx_, array, TILEDB_WRITE);
2500 CHECK(rc == TILEDB_OK);
2501
2502 // Create and submit query
2503 tiledb_query_t* query;
2504 rc = tiledb_query_alloc(ctx_, array, TILEDB_WRITE, &query);
2505 REQUIRE(rc == TILEDB_OK);
2506
2507 char d_data[] = "ccbbccddaa";
2508 uint64_t d_data_size = sizeof(d_data) - 1; // Ignore '\0'
2509 uint64_t d_off[] = {0, 2, 4, 8};
2510 uint64_t d_off_size = sizeof(d_off);
2511 int32_t a_data[] = {3, 2, 4, 1};
2512 uint64_t a_size = sizeof(a_data);
2513 rc = tiledb_query_set_data_buffer(ctx_, query, "d", d_data, &d_data_size);
2514 REQUIRE(rc == TILEDB_OK);
2515 rc = tiledb_query_set_offsets_buffer(ctx_, query, "d", d_off, &d_off_size);
2516 REQUIRE(rc == TILEDB_OK);
2517 rc = tiledb_query_set_data_buffer(ctx_, query, "a", a_data, &a_size);
2518 REQUIRE(rc == TILEDB_OK);
2519 rc = tiledb_query_set_layout(ctx_, query, TILEDB_UNORDERED);
2520 REQUIRE(rc == TILEDB_OK);
2521 rc = tiledb_query_submit(ctx_, query);
2522 REQUIRE(rc == TILEDB_OK);
2523
2524 // Close array
2525 rc = tiledb_array_close(ctx_, array);
2526 CHECK(rc == TILEDB_OK);
2527
2528 // Free array
2529 tiledb_array_free(&array);
2530
2531 // #### PARTITIONER ####
2532
2533 // Open array
2534 rc = tiledb_array_alloc(ctx_, array_name_.c_str(), &array);
2535 CHECK(rc == TILEDB_OK);
2536 rc = tiledb_array_open(ctx_, array, TILEDB_READ);
2537 CHECK(rc == TILEDB_OK);
2538
2539 // Unsplittable
2540 bool unsplittable = false;
2541 uint64_t budget_off = 0, budget_val = 0;
2542
2543 Layout layout = Layout::ROW_MAJOR;
2544
2545 SECTION("Global order") {
2546 layout = Layout::GLOBAL_ORDER;
2547 }
2548
2549 SECTION("Row-major") {
2550 layout = Layout::ROW_MAJOR;
2551 }
2552
2553 SECTION("Col-major") {
2554 layout = Layout::COL_MAJOR;
2555 }
2556
2557 SECTION("Unordered") {
2558 layout = Layout::UNORDERED;
2559 }
2560
2561 tiledb::sm::Subarray subarray(
2562 array->array_, layout, &g_helper_stats, g_helper_logger());
2563 tiledb::sm::Range r;
2564 r.set_str_range("cc", "ccd");
2565 subarray.add_range(0, std::move(r), true);
2566 ThreadPool tp;
2567 CHECK(tp.init(4).ok());
2568 Config config;
2569 SubarrayPartitioner partitioner(
2570 &config,
2571 subarray,
2572 memory_budget_,
2573 memory_budget_var_,
2574 0,
2575 &tp,
2576 &g_helper_stats,
2577 g_helper_logger());
2578 auto st = partitioner.set_result_budget("d", 10, 4);
2579 CHECK(st.ok());
2580 CHECK(partitioner.get_result_budget("d", &budget_off, &budget_val).ok());
2581 CHECK(budget_off == 10);
2582 CHECK(budget_val == 4);
2583 CHECK(partitioner.next(&unsplittable).ok());
2584 CHECK(unsplittable);
2585
2586 // Close array
2587 rc = tiledb_array_close(ctx_, array);
2588 CHECK(rc == TILEDB_OK);
2589
2590 // Clean up
2591 tiledb_array_free(&array);
2592 tiledb_query_free(&query);
2593 }
2594
2595 TEST_CASE_METHOD(
2596 SubarrayPartitionerSparseFx,
2597 "SubarrayPartitioner (Sparse): 2D, multi-range, test memory budget "
2598 "calibration",
2599 "[SubarrayPartitioner][sparse][2D][MR][calibrate-memory_budget]") {
2600 Layout subarray_layout = Layout::ROW_MAJOR;
2601 std::string attr = "a";
2602
2603 create_default_2d_array(TILEDB_ROW_MAJOR, TILEDB_ROW_MAJOR);
2604 write_default_2d_array();
2605 open_array(ctx_, array_, TILEDB_READ);
2606
2607 subarray_layout = Layout::ROW_MAJOR;
2608 SubarrayRanges<uint64_t> ranges = {{1, 1}, {2, 2, 2, 2, 2, 2}};
2609 std::vector<SubarrayRanges<uint64_t>> partitions = {
2610 {{1, 1}, {2, 2, 2, 2, 2, 2}},
2611 };
2612
2613 uint64_t result_budget = 3 * sizeof(int);
2614 uint64_t memory_budget = 2 * sizeof(int);
2615 uint64_t memory_budget_var = 20 * sizeof(int);
2616 test_subarray_partitioner(
2617 subarray_layout,
2618 ranges,
2619 partitions,
2620 attr,
2621 result_budget,
2622 memory_budget,
2623 memory_budget_var);
2624
2625 close_array(ctx_, array_);
2626 }