30#ifdef DEAL_II_WITH_TBB
31# include <tbb/blocked_range.h>
32# include <tbb/parallel_for.h>
34# ifndef DEAL_II_TBB_WITH_ONEAPI
35# include <tbb/task_scheduler_init.h>
65 namespace MatrixFreeFunctions
67#if defined(DEAL_II_WITH_TBB) && !defined(DEAL_II_TBB_WITH_ONEAPI)
77 ActualCellWork(MFWorkerInterface **worker_pointer,
78 const unsigned int partition,
79 const TaskInfo & task_info)
81 , worker_pointer(worker_pointer)
83 , task_info(task_info)
86 ActualCellWork(MFWorkerInterface &worker,
87 const unsigned int partition,
88 const TaskInfo & task_info)
90 , worker_pointer(nullptr)
92 , task_info(task_info)
98 MFWorkerInterface *used_worker =
99 worker !=
nullptr ? worker : *worker_pointer;
101 used_worker->cell(partition);
103 if (task_info.face_partition_data.empty() ==
false)
105 used_worker->face(partition);
106 used_worker->boundary(partition);
111 MFWorkerInterface * worker;
112 MFWorkerInterface **worker_pointer;
114 const TaskInfo & task_info;
117 class CellWork :
public tbb::task
120 CellWork(MFWorkerInterface &worker,
121 const unsigned int partition,
122 const TaskInfo & task_info,
123 const bool is_blocked)
126 , is_blocked(is_blocked)
134 if (is_blocked ==
true)
135 tbb::empty_task::spawn(*dummy);
139 tbb::empty_task *dummy;
143 const bool is_blocked;
148 class PartitionWork :
public tbb::task
151 PartitionWork(MFWorkerInterface &function_in,
152 const unsigned int partition_in,
153 const TaskInfo & task_info_in,
154 const bool is_blocked_in =
false)
156 , function(function_in)
158 , task_info(task_info_in)
159 , is_blocked(is_blocked_in)
165 tbb::empty_task *root =
166 new (tbb::task::allocate_root()) tbb::empty_task;
167 const unsigned int evens = task_info.partition_evens[
partition];
168 const unsigned int odds = task_info.partition_odds[
partition];
169 const unsigned int n_blocked_workers =
170 task_info.partition_n_blocked_workers[
partition];
171 const unsigned int n_workers =
172 task_info.partition_n_workers[
partition];
173 std::vector<CellWork *> worker(n_workers);
174 std::vector<CellWork *> blocked_worker(n_blocked_workers);
176 root->set_ref_count(evens + 1);
177 for (
unsigned int j = 0; j < evens; ++j)
179 worker[j] =
new (root->allocate_child())
181 task_info.partition_row_index[partition] + 2 * j,
186 worker[j]->set_ref_count(2);
187 blocked_worker[j - 1]->dummy =
188 new (worker[j]->allocate_child()) tbb::empty_task;
189 tbb::task::spawn(*blocked_worker[j - 1]);
192 worker[j]->set_ref_count(1);
195 blocked_worker[j] =
new (worker[j]->allocate_child())
197 task_info.partition_row_index[partition] + 2 * j +
206 worker[evens] =
new (worker[j]->allocate_child())
208 task_info.partition_row_index[partition] +
212 tbb::task::spawn(*worker[evens]);
216 tbb::empty_task *child =
217 new (worker[j]->allocate_child()) tbb::empty_task();
218 tbb::task::spawn(*child);
223 root->wait_for_all();
224 root->destroy(*root);
225 if (is_blocked ==
true)
226 tbb::empty_task::spawn(*dummy);
230 tbb::empty_task *dummy;
233 MFWorkerInterface &function;
235 const TaskInfo & task_info;
236 const bool is_blocked;
248 CellWork(MFWorkerInterface &worker_in,
249 const TaskInfo & task_info_in,
250 const unsigned int partition_in)
252 , task_info(task_info_in)
257 operator()(
const tbb::blocked_range<unsigned int> &r)
const
259 const unsigned int start_index =
260 task_info.cell_partition_data[
partition] +
261 task_info.block_size * r.begin();
262 const unsigned int end_index =
263 std::min(start_index + task_info.block_size * (r.end() - r.begin()),
264 task_info.cell_partition_data[partition + 1]);
265 worker.cell(std::make_pair(start_index, end_index));
267 if (task_info.face_partition_data.empty() ==
false)
274 MFWorkerInterface &worker;
275 const TaskInfo & task_info;
281 class PartitionWork :
public tbb::task
284 PartitionWork(MFWorkerInterface &worker_in,
285 const unsigned int partition_in,
286 const TaskInfo & task_info_in,
287 const bool is_blocked_in)
291 , task_info(task_info_in)
292 , is_blocked(is_blocked_in)
298 const unsigned int n_chunks =
299 (task_info.cell_partition_data[
partition + 1] -
300 task_info.cell_partition_data[
partition] + task_info.block_size -
302 task_info.block_size;
303 parallel_for(tbb::blocked_range<unsigned int>(0, n_chunks, 1),
304 CellWork(worker, task_info, partition));
305 if (is_blocked ==
true)
306 tbb::empty_task::spawn(*dummy);
310 tbb::empty_task *dummy;
313 MFWorkerInterface &worker;
315 const TaskInfo & task_info;
316 const bool is_blocked;
323 class MPICommunication :
public tbb::task
326 MPICommunication(MFWorkerInterface &worker_in,
const bool do_compress)
328 , do_compress(do_compress)
334 if (do_compress ==
false)
335 worker.vector_update_ghosts_finish();
337 worker.vector_compress_start();
342 MFWorkerInterface &worker;
343 const bool do_compress;
365#if defined(DEAL_II_WITH_TBB) && !defined(DEAL_II_TBB_WITH_ONEAPI)
372 tbb::empty_task *root =
373 new (tbb::task::allocate_root()) tbb::empty_task;
374 root->set_ref_count(
evens + 1);
375 std::vector<partition::PartitionWork *> worker(
n_workers);
376 std::vector<partition::PartitionWork *> blocked_worker(
378 MPICommunication *worker_compr =
379 new (root->allocate_child()) MPICommunication(funct,
true);
380 worker_compr->set_ref_count(1);
381 for (
unsigned int j = 0; j <
evens; ++j)
385 worker[j] =
new (root->allocate_child())
386 partition::PartitionWork(funct, 2 * j, *
this,
false);
387 worker[j]->set_ref_count(2);
388 blocked_worker[j - 1]->dummy =
389 new (worker[j]->allocate_child()) tbb::empty_task;
390 tbb::task::spawn(*blocked_worker[j - 1]);
394 worker[j] =
new (worker_compr->allocate_child())
395 partition::PartitionWork(funct, 2 * j, *
this,
false);
396 worker[j]->set_ref_count(2);
397 MPICommunication *worker_dist =
398 new (worker[j]->allocate_child())
399 MPICommunication(funct,
false);
400 tbb::task::spawn(*worker_dist);
404 blocked_worker[j] =
new (worker[j]->allocate_child())
405 partition::PartitionWork(funct, 2 * j + 1, *
this,
true);
411 worker[
evens] =
new (worker[j]->allocate_child())
412 partition::PartitionWork(funct,
416 tbb::task::spawn(*worker[
evens]);
420 tbb::empty_task *child =
421 new (worker[j]->allocate_child()) tbb::empty_task();
422 tbb::task::spawn(*child);
427 root->wait_for_all();
428 root->destroy(*root);
444 tbb::empty_task *root =
445 new (tbb::task::allocate_root()) tbb::empty_task;
446 root->set_ref_count(
evens + 1);
451 std::vector<color::PartitionWork *> worker(
n_workers);
452 std::vector<color::PartitionWork *> blocked_worker(
454 unsigned int worker_index = 0, slice_index = 0;
455 int spawn_index_child = -2;
456 MPICommunication *worker_compr =
457 new (root->allocate_child()) MPICommunication(funct,
true);
458 worker_compr->set_ref_count(1);
459 for (
unsigned int part = 0;
464 worker[worker_index] =
465 new (worker_compr->allocate_child())
466 color::PartitionWork(funct,
471 worker[worker_index] =
new (root->allocate_child())
472 color::PartitionWork(funct,
480 worker[worker_index]->set_ref_count(1);
482 worker[worker_index] =
483 new (worker[worker_index - 1]->allocate_child())
484 color::PartitionWork(funct,
489 worker[worker_index]->set_ref_count(2);
492 blocked_worker[(part - 1) / 2]->dummy =
493 new (worker[worker_index]->allocate_child())
496 if (spawn_index_child == -1)
497 tbb::task::spawn(*blocked_worker[(part - 1) / 2]);
500 Assert(spawn_index_child >= 0,
502 tbb::task::spawn(*worker[spawn_index_child]);
504 spawn_index_child = -2;
508 MPICommunication *worker_dist =
509 new (worker[worker_index]->allocate_child())
510 MPICommunication(funct,
false);
511 tbb::task::spawn(*worker_dist);
519 blocked_worker[part / 2] =
520 new (worker[worker_index - 1]->allocate_child())
521 color::PartitionWork(funct,
528 blocked_worker[part / 2]->set_ref_count(1);
529 worker[worker_index] =
new (
530 blocked_worker[part / 2]->allocate_child())
531 color::PartitionWork(funct,
539 spawn_index_child = -1;
548 worker[worker_index]->set_ref_count(1);
551 worker[worker_index] =
552 new (worker[worker_index - 1]->allocate_child())
553 color::PartitionWork(funct,
558 spawn_index_child = worker_index;
563 tbb::empty_task *
final =
564 new (worker[worker_index - 1]->allocate_child())
566 tbb::task::spawn(*
final);
567 spawn_index_child = worker_index - 1;
573 tbb::task::spawn(*worker[spawn_index_child]);
575 root->wait_for_all();
576 root->destroy(*root);
589 tbb::empty_task *root =
590 new (tbb::task::allocate_root()) tbb::empty_task;
591 root->set_ref_count(2);
592 color::PartitionWork *worker =
593 new (root->allocate_child())
594 color::PartitionWork(funct,
color, *
this,
false);
595 tbb::empty_task::spawn(*worker);
596 root->wait_for_all();
597 root->destroy(*root);
689 template <
typename StreamType>
692 const std::size_t data_length)
const
699 out << memory_c.
min <<
"/" << memory_c.
avg <<
"/" << memory_c.
max;
700 out <<
" MB" << std::endl;
724 std::vector<unsigned int> &boundary_cells)
728 unsigned int fillup_needed =
736 std::vector<unsigned int> new_boundary_cells;
737 new_boundary_cells.reserve(boundary_cells.size());
739 unsigned int next_free_slot = 0, bound_index = 0;
740 while (fillup_needed > 0 && bound_index < boundary_cells.size())
742 if (next_free_slot < boundary_cells[bound_index])
746 if (next_free_slot + fillup_needed <=
747 boundary_cells[bound_index])
749 for (
unsigned int j =
750 boundary_cells[bound_index] - fillup_needed;
751 j < boundary_cells[bound_index];
753 new_boundary_cells.push_back(j);
760 for (
unsigned int j = next_free_slot;
761 j < boundary_cells[bound_index];
763 new_boundary_cells.push_back(j);
765 boundary_cells[bound_index] - next_free_slot;
768 new_boundary_cells.push_back(boundary_cells[bound_index]);
769 next_free_slot = boundary_cells[bound_index] + 1;
772 while (fillup_needed > 0 &&
773 (new_boundary_cells.size() == 0 ||
775 new_boundary_cells.push_back(new_boundary_cells.back() + 1);
776 while (bound_index < boundary_cells.size())
777 new_boundary_cells.push_back(boundary_cells[bound_index++]);
779 boundary_cells.swap(new_boundary_cells);
783 std::sort(boundary_cells.begin(), boundary_cells.end());
796 const std::vector<unsigned int> &cells_with_comm,
797 const unsigned int dofs_per_cell,
798 const bool categories_are_hp,
799 const std::vector<unsigned int> &cell_vectorization_categories,
800 const bool cell_vectorization_categories_strict,
801 const std::vector<unsigned int> &parent_relation,
802 std::vector<unsigned int> & renumbering,
803 std::vector<unsigned char> & incompletely_filled_vectorization)
834 unsigned int n_categories = 1;
836 if (cell_vectorization_categories.empty() ==
false)
841 std::set<unsigned int> used_categories;
843 used_categories.insert(cell_vectorization_categories[i]);
844 std::vector<unsigned int> used_categories_vector(
845 used_categories.size());
847 for (
const auto &it : used_categories)
848 used_categories_vector[n_categories++] = it;
851 const unsigned int index =
852 std::lower_bound(used_categories_vector.begin(),
853 used_categories_vector.end(),
854 cell_vectorization_categories[i]) -
855 used_categories_vector.begin();
857 tight_category_map[i] =
index;
864 std::vector<std::vector<unsigned int>> renumbering_category(n_categories);
866 renumbering_category[tight_category_map[i]].push_back(i);
868 if (cell_vectorization_categories_strict ==
false && n_categories > 1)
869 for (
unsigned int j = n_categories - 1; j > 0; --j)
871 unsigned int lower_index = j - 1;
872 while ((renumbering_category[j].size() % n_lanes) != 0u)
874 while (((renumbering_category[j].size() % n_lanes) != 0u) &&
875 !renumbering_category[lower_index].empty())
877 renumbering_category[j].push_back(
878 renumbering_category[lower_index].back());
879 renumbering_category[lower_index].pop_back();
881 if (lower_index == 0)
892 std::vector<unsigned int> temporary_numbering;
894 (n_lanes - 1) * n_categories);
895 const unsigned int n_cells_per_parent =
896 std::count(parent_relation.begin(), parent_relation.end(), 0);
897 std::vector<unsigned int> category_size;
898 for (
unsigned int j = 0; j < n_categories; ++j)
900 std::vector<std::pair<unsigned int, unsigned int>> grouped_cells;
901 std::vector<unsigned int> other_cells;
902 for (
const unsigned int cell : renumbering_category[j])
903 if (parent_relation.empty() ||
905 other_cells.push_back(cell);
907 grouped_cells.emplace_back(parent_relation[cell], cell);
910 std::sort(grouped_cells.begin(), grouped_cells.end());
911 std::vector<unsigned int> n_cells_per_group;
912 unsigned int length = 0;
913 for (
unsigned int i = 0; i < grouped_cells.size(); ++i, ++length)
914 if (i > 0 && grouped_cells[i].
first != grouped_cells[i - 1].
first)
916 n_cells_per_group.push_back(length);
920 n_cells_per_group.push_back(length);
925 auto group_it = grouped_cells.begin();
926 for (
const unsigned int length : n_cells_per_group)
927 if (length < n_cells_per_parent)
928 for (
unsigned int j = 0; j < length; ++j)
929 other_cells.push_back((group_it++)->second);
935 for (
unsigned int j = 0; j < length; ++j)
936 temporary_numbering.push_back((group_it++)->second);
940 std::sort(other_cells.begin(), other_cells.end());
941 temporary_numbering.insert(temporary_numbering.end(),
945 while (temporary_numbering.size() % n_lanes != 0)
948 category_size.push_back(temporary_numbering.size());
952 std::vector<bool> batch_with_comm(temporary_numbering.size() / n_lanes,
954 std::vector<unsigned int> temporary_numbering_inverse(
n_active_cells);
955 for (
unsigned int i = 0; i < temporary_numbering.size(); ++i)
957 temporary_numbering_inverse[temporary_numbering[i]] = i;
958 for (
const unsigned int cell : cells_with_comm)
959 batch_with_comm[temporary_numbering_inverse[cell] / n_lanes] =
true;
965 std::vector<std::array<unsigned int, 3>> batch_order;
966 std::vector<std::array<unsigned int, 3>> batch_order_comm;
967 for (
unsigned int i = 0; i < temporary_numbering.size(); i += n_lanes)
969 unsigned int max_index = 0;
970 for (
unsigned int j = 0; j < n_lanes; ++j)
972 max_index =
std::max(temporary_numbering[i + j], max_index);
973 const unsigned int category_hp =
975 std::upper_bound(category_size.begin(), category_size.end(), i) -
976 category_size.begin() :
978 const std::array<unsigned int, 3> next{{category_hp, max_index, i}};
979 if (batch_with_comm[i / n_lanes])
980 batch_order_comm.emplace_back(next);
982 batch_order.emplace_back(next);
985 std::sort(batch_order.begin(), batch_order.end());
986 std::sort(batch_order_comm.begin(), batch_order_comm.end());
993 std::vector<unsigned int> blocks;
996 if (batch_order.empty())
997 std::swap(batch_order_comm, batch_order);
1000 blocks = {0,
static_cast<unsigned int>(batch_order.size())};
1005 const unsigned int comm_begin = batch_order.size() / 2;
1006 batch_order.insert(batch_order.begin() + comm_begin,
1007 batch_order_comm.begin(),
1008 batch_order_comm.end());
1009 const unsigned int comm_end = comm_begin + batch_order_comm.size();
1010 const unsigned int end = batch_order.size();
1011 blocks = {0, comm_begin, comm_end, end};
1015 std::vector<std::array<unsigned int, 2>> tight_category_map_ghost;
1017 if (cell_vectorization_categories.empty() ==
false)
1021 std::set<unsigned int> used_categories;
1023 used_categories.insert(
1026 std::vector<unsigned int> used_categories_vector(
1027 used_categories.size());
1029 for (
const auto &it : used_categories)
1030 used_categories_vector[n_categories++] = it;
1032 std::vector<unsigned int> counters(n_categories, 0);
1036 const unsigned int index =
1038 used_categories_vector.begin(),
1039 used_categories_vector.end(),
1041 used_categories_vector.begin();
1043 tight_category_map_ghost.emplace_back(
1044 std::array<unsigned int, 2>{{
index, i}});
1047 if (categories_are_hp || cell_vectorization_categories_strict)
1052 for (
unsigned int i = 0; i < counters.size(); ++i)
1053 if (counters[i] % n_lanes != 0)
1054 for (
unsigned int j = counters[i] % n_lanes; j < n_lanes; ++j)
1055 tight_category_map_ghost.emplace_back(
1056 std::array<unsigned int, 2>{
1057 {i, numbers::invalid_unsigned_int}});
1059 std::sort(tight_category_map_ghost.begin(),
1060 tight_category_map_ghost.end());
1064 const unsigned int n_cell_batches = batch_order.size();
1065 const unsigned int n_ghost_batches =
1066 ((tight_category_map_ghost.empty() ? n_ghost_cells :
1067 tight_category_map_ghost.size()) +
1070 incompletely_filled_vectorization.resize(n_cell_batches +
1073 cell_partition_data.clear();
1074 cell_partition_data.resize(1, 0);
1076 renumbering.clear();
1077 renumbering.resize(n_active_cells + n_ghost_cells,
1080 unsigned int counter = 0;
1081 for (
unsigned int block = 0; block < blocks.size() - 1; ++block)
1083 const unsigned int grain_size =
1084 std::max((2048U / dofs_per_cell) / 8 * 4, 2U);
1085 for (
unsigned int k = blocks[block]; k < blocks[block + 1];
1087 cell_partition_data.push_back(
1088 std::min(k + grain_size, blocks[block + 1]));
1089 partition_row_index[block + 1] = cell_partition_data.size() - 1;
1092 for (
unsigned int k = blocks[block]; k < blocks[block + 1]; ++k)
1094 const unsigned int pos = batch_order[k][2];
1096 for (; j < n_lanes && temporary_numbering[pos + j] !=
1099 renumbering[counter++] = temporary_numbering[pos + j];
1101 incompletely_filled_vectorization[k] = j;
1107 if (tight_category_map_ghost.empty())
1109 for (
unsigned int cell = 0; cell < n_ghost_cells; ++cell)
1110 renumbering[n_active_cells + cell] = n_active_cells + cell;
1112 if ((n_ghost_cells % n_lanes) != 0u)
1113 incompletely_filled_vectorization.back() = n_ghost_cells % n_lanes;
1117 for (
unsigned int k = 0, ptr = 0; k < n_ghost_batches;
1118 ++k, ptr += n_lanes)
1123 j < n_lanes && (ptr + j < tight_category_map_ghost.size()) &&
1124 (tight_category_map_ghost[ptr + j][1] !=
1127 renumbering[counter++] =
1128 n_active_cells + tight_category_map_ghost[ptr + j][1];
1131 incompletely_filled_vectorization[n_cell_batches + k] = j;
1137 cell_partition_data.push_back(n_cell_batches + n_ghost_batches);
1138 partition_row_index.back() = cell_partition_data.size() - 1;
1141 std::vector<unsigned int> renumber_cpy(renumbering);
1142 std::sort(renumber_cpy.begin(), renumber_cpy.end());
1143 for (
unsigned int i = 0; i < renumber_cpy.size(); ++i)
1151 TaskInfo::initial_setup_blocks_tasks(
1152 const std::vector<unsigned int> &boundary_cells,
1153 std::vector<unsigned int> & renumbering,
1154 std::vector<unsigned char> & incompletely_filled_vectorization)
1156 const unsigned int n_cell_batches =
1157 (n_active_cells + vectorization_length - 1) / vectorization_length;
1158 const unsigned int n_ghost_slots =
1159 (n_ghost_cells + vectorization_length - 1) / vectorization_length;
1160 incompletely_filled_vectorization.resize(n_cell_batches + n_ghost_slots);
1161 if (n_cell_batches * vectorization_length > n_active_cells)
1162 incompletely_filled_vectorization[n_cell_batches - 1] =
1163 vectorization_length -
1164 (n_cell_batches * vectorization_length - n_active_cells);
1165 if (n_ghost_slots * vectorization_length > n_ghost_cells)
1166 incompletely_filled_vectorization[n_cell_batches + n_ghost_slots - 1] =
1167 vectorization_length -
1168 (n_ghost_slots * vectorization_length - n_ghost_cells);
1170 std::vector<unsigned int> reverse_numbering(
1172 for (
unsigned int j = 0; j < boundary_cells.size(); ++j)
1173 reverse_numbering[boundary_cells[j]] = j;
1174 unsigned int counter = boundary_cells.size();
1175 for (
unsigned int j = 0; j < n_active_cells; ++j)
1177 reverse_numbering[j] = counter++;
1182 for (
unsigned int j = n_active_cells; j < n_active_cells + n_ghost_cells;
1184 renumbering.push_back(j);
1188 cell_partition_data.clear();
1189 cell_partition_data.push_back(0);
1192 const unsigned int n_macro_boundary_cells =
1193 (boundary_cells.size() + vectorization_length - 1) /
1194 vectorization_length;
1195 cell_partition_data.push_back(
1196 (n_cell_batches - n_macro_boundary_cells) / 2);
1197 cell_partition_data.push_back(cell_partition_data[1] +
1198 n_macro_boundary_cells);
1202 cell_partition_data.push_back(n_cell_batches);
1203 cell_partition_data.push_back(cell_partition_data.back() + n_ghost_slots);
1204 partition_row_index.resize(n_procs > 1 ? 4 : 2);
1205 partition_row_index[0] = 0;
1206 partition_row_index[1] = 1;
1209 partition_row_index[2] = 2;
1210 partition_row_index[3] = 3;
1217 TaskInfo::guess_block_size(
const unsigned int dofs_per_cell)
1220 if (block_size == 0)
1225 vectorization_length);
1229 const unsigned int minimum_parallel_grain_size = 200;
1230 if (dofs_per_cell * block_size < minimum_parallel_grain_size)
1231 block_size = (minimum_parallel_grain_size / dofs_per_cell + 1);
1232 if (dofs_per_cell * block_size > 10000)
1236 1 <<
static_cast<unsigned int>(std::log2(block_size + 1));
1238 if (block_size > n_active_cells)
1239 block_size =
std::max(1U, n_active_cells);
1245 TaskInfo::make_thread_graph_partition_color(
1247 std::vector<unsigned int> & renumbering,
1248 std::vector<unsigned char> &irregular_cells,
1251 const unsigned int n_cell_batches = *(cell_partition_data.end() - 2);
1252 if (n_cell_batches == 0)
1257 unsigned int partition = 0, counter = 0;
1262 make_connectivity_cells_to_blocks(irregular_cells,
1271 std::vector<unsigned int> cell_partition(n_blocks,
1276 std::vector<unsigned int> partition_list(n_blocks, 0);
1277 std::vector<unsigned int> partition_color_list(n_blocks, 0);
1280 std::vector<unsigned int> partition_size(2, 0);
1286 unsigned int cluster_size = 1;
1289 make_partitioning(connectivity,
1297 make_coloring_within_partitions_pre_blocked(connectivity,
1302 partition_color_list);
1304 partition_list = renumbering;
1309 std::vector<unsigned int> sorted_pc_list(partition_color_list);
1310 std::sort(sorted_pc_list.begin(), sorted_pc_list.end());
1311 for (
unsigned int i = 0; i < sorted_pc_list.size(); ++i)
1318 std::vector<unsigned int> block_start(n_cell_batches + 1);
1319 std::vector<unsigned char> irregular(n_cell_batches);
1321 unsigned int mcell_start = 0;
1323 for (
unsigned int block = 0; block < n_blocks; ++block)
1325 block_start[block + 1] = block_start[block];
1326 for (
unsigned int mcell = mcell_start;
1327 mcell <
std::min(mcell_start + block_size, n_cell_batches);
1330 unsigned int n_comp = (irregular_cells[mcell] > 0) ?
1331 irregular_cells[mcell] :
1332 vectorization_length;
1333 block_start[block + 1] += n_comp;
1336 mcell_start += block_size;
1339 unsigned int counter_macro = 0;
1340 unsigned int block_size_last =
1341 n_cell_batches - block_size * (n_blocks - 1);
1342 if (block_size_last == 0)
1343 block_size_last = block_size;
1345 unsigned int tick = 0;
1346 for (
unsigned int block = 0; block < n_blocks; ++block)
1348 unsigned int present_block = partition_color_list[block];
1349 for (
unsigned int cell = block_start[present_block];
1350 cell < block_start[present_block + 1];
1352 renumbering[counter++] = partition_list[cell];
1353 unsigned int this_block_size =
1354 (present_block == n_blocks - 1) ? block_size_last : block_size;
1358 if (cell_partition_data[tick] == block)
1359 cell_partition_data[tick++] = counter_macro;
1361 for (
unsigned int j = 0; j < this_block_size; ++j)
1362 irregular[counter_macro++] =
1363 irregular_cells[present_block * block_size + j];
1366 cell_partition_data.back() = counter_macro;
1368 irregular_cells.swap(irregular);
1375 std::vector<unsigned int> sorted_renumbering(renumbering);
1376 std::sort(sorted_renumbering.begin(), sorted_renumbering.end());
1377 for (
unsigned int i = 0; i < sorted_renumbering.size(); ++i)
1392 TaskInfo::make_thread_graph(
1393 const std::vector<unsigned int> &cell_active_fe_index,
1395 std::vector<unsigned int> & renumbering,
1396 std::vector<unsigned char> & irregular_cells,
1399 const unsigned int n_cell_batches = *(cell_partition_data.end() - 2);
1400 if (n_cell_batches == 0)
1408 make_connectivity_cells_to_blocks(irregular_cells,
1410 connectivity_blocks);
1412 unsigned int n_blocks = 0;
1413 if (scheme == partition_color ||
1415 n_blocks = this->n_blocks;
1417 n_blocks = n_active_cells;
1422 std::vector<unsigned int> cell_partition(n_blocks,
1428 std::vector<unsigned int> partition_list(n_blocks, 0);
1429 std::vector<unsigned int> partition_2layers_list(n_blocks, 0);
1432 std::vector<unsigned int> partition_size(2, 0);
1434 unsigned int partition = 0;
1440 unsigned int cluster_size = 1;
1441 if (scheme == partition_partition)
1442 cluster_size = block_size * vectorization_length;
1445 if (scheme == partition_color || scheme == color)
1446 make_partitioning(connectivity_blocks,
1453 make_partitioning(connectivity,
1461 if (scheme == partition_partition)
1465 make_partitioning_within_partitions_post_blocked(
1467 cell_active_fe_index,
1474 partition_2layers_list,
1477 else if (scheme == partition_color || scheme == color)
1479 make_coloring_within_partitions_pre_blocked(connectivity_blocks,
1484 partition_2layers_list);
1490 std::vector<unsigned int> sorted_pc_list(partition_2layers_list);
1491 std::sort(sorted_pc_list.begin(), sorted_pc_list.end());
1492 for (
unsigned int i = 0; i < sorted_pc_list.size(); ++i)
1498 std::vector<unsigned int> renumbering_in(n_active_cells, 0);
1499 renumbering_in.swap(renumbering);
1500 if (scheme == partition_partition)
1505 for (
unsigned int j = 0; j < renumbering.size(); ++j)
1506 renumbering[j] = renumbering_in[partition_2layers_list[j]];
1508 for (
unsigned int i = 0; i < n_ghost_cells; ++i)
1509 renumbering.push_back(i + n_active_cells);
1515 std::vector<unsigned int> block_start(n_cell_batches + 1);
1516 std::vector<unsigned char> irregular(n_cell_batches);
1518 unsigned int counter = 0;
1519 unsigned int mcell_start = 0;
1521 for (
unsigned int block = 0; block < n_blocks; ++block)
1523 block_start[block + 1] = block_start[block];
1524 for (
unsigned int mcell = mcell_start;
1525 mcell <
std::min(mcell_start + block_size, n_cell_batches);
1528 unsigned int n_comp = (irregular_cells[mcell] > 0) ?
1529 irregular_cells[mcell] :
1530 vectorization_length;
1531 block_start[block + 1] += n_comp;
1534 mcell_start += block_size;
1537 unsigned int counter_macro = 0;
1538 unsigned int block_size_last =
1539 n_cell_batches - block_size * (n_blocks - 1);
1540 if (block_size_last == 0)
1541 block_size_last = block_size;
1543 unsigned int tick = 0;
1544 for (
unsigned int block = 0; block < n_blocks; ++block)
1546 unsigned int present_block = partition_2layers_list[block];
1547 for (
unsigned int cell = block_start[present_block];
1548 cell < block_start[present_block + 1];
1550 renumbering[counter++] = renumbering_in[cell];
1551 unsigned int this_block_size =
1552 (present_block == n_blocks - 1) ? block_size_last : block_size;
1556 if (cell_partition_data[tick] == block)
1557 cell_partition_data[tick++] = counter_macro;
1559 for (
unsigned int j = 0; j < this_block_size; ++j)
1560 irregular[counter_macro++] =
1561 irregular_cells[present_block * block_size + j];
1564 cell_partition_data.back() = counter_macro;
1566 irregular_cells.swap(irregular);
1572 std::vector<unsigned int> sorted_renumbering(renumbering);
1573 std::sort(sorted_renumbering.begin(), sorted_renumbering.end());
1574 for (
unsigned int i = 0; i < sorted_renumbering.size(); ++i)
1581 update_task_info(partition);
1587 TaskInfo::make_thread_graph_partition_partition(
1588 const std::vector<unsigned int> &cell_active_fe_index,
1590 std::vector<unsigned int> & renumbering,
1591 std::vector<unsigned char> & irregular_cells,
1594 const unsigned int n_cell_batches = *(cell_partition_data.end() - 2);
1595 if (n_cell_batches == 0)
1598 const unsigned int cluster_size = block_size * vectorization_length;
1605 std::vector<unsigned int> cell_partition(n_active_cells,
1611 std::vector<unsigned int> partition_list(n_active_cells, 0);
1612 std::vector<unsigned int> partition_partition_list(n_active_cells, 0);
1615 std::vector<unsigned int> partition_size(2, 0);
1617 unsigned int partition = 0;
1622 make_partitioning(connectivity,
1630 make_partitioning_within_partitions_post_blocked(connectivity,
1631 cell_active_fe_index,
1638 partition_partition_list,
1641 partition_list.swap(renumbering);
1643 for (
unsigned int j = 0; j < renumbering.size(); ++j)
1644 renumbering[j] = partition_list[partition_partition_list[j]];
1646 for (
unsigned int i = 0; i < n_ghost_cells; ++i)
1647 renumbering.push_back(i + n_active_cells);
1649 update_task_info(partition);
1655 TaskInfo::make_connectivity_cells_to_blocks(
1656 const std::vector<unsigned char> &irregular_cells,
1660 std::vector<std::vector<unsigned int>> cell_blocks(n_blocks);
1661 std::vector<unsigned int> touched_cells(n_active_cells);
1662 unsigned int cell = 0;
1663 for (
unsigned int i = 0, mcell = 0; i < n_blocks; ++i)
1665 for (
unsigned int c = 0;
1666 c < block_size && mcell < *(cell_partition_data.end() - 2);
1669 unsigned int ncomp = (irregular_cells[mcell] > 0) ?
1670 irregular_cells[mcell] :
1671 vectorization_length;
1672 for (
unsigned int c = 0; c < ncomp; ++c, ++cell)
1674 cell_blocks[i].push_back(cell);
1675 touched_cells[cell] = i;
1680 for (
unsigned int i = 0; i < cell_blocks.size(); ++i)
1681 for (
unsigned int col = 0; col < cell_blocks[i].size(); ++col)
1684 connectivity_cells.
begin(cell_blocks[i][col]);
1685 it != connectivity_cells.
end(cell_blocks[i][col]);
1688 if (touched_cells[it->column()] != i)
1689 connectivity_blocks.
add(i, touched_cells[it->column()]);
1699 TaskInfo::make_partitioning_within_partitions_post_blocked(
1701 const std::vector<unsigned int> &cell_active_fe_index,
1702 const unsigned int partition,
1703 const unsigned int cluster_size,
1705 const std::vector<unsigned int> &cell_partition,
1706 const std::vector<unsigned int> &partition_list,
1707 const std::vector<unsigned int> &partition_size,
1708 std::vector<unsigned int> & partition_partition_list,
1709 std::vector<unsigned char> & irregular_cells)
1711 const unsigned int n_cell_batches = *(cell_partition_data.end() - 2);
1712 const unsigned int n_ghost_slots =
1713 *(cell_partition_data.end() - 1) - n_cell_batches;
1716 std::vector<unsigned int> neighbor_list;
1719 std::vector<unsigned int> neighbor_neighbor_list;
1721 std::vector<unsigned int> renumbering(n_active_cells);
1723 irregular_cells.back() = 0;
1724 irregular_cells.resize(n_active_cells + n_ghost_slots);
1726 unsigned int max_fe_index = 0;
1727 for (
const unsigned int fe_index : cell_active_fe_index)
1728 max_fe_index =
std::max(fe_index, max_fe_index);
1730 Assert(!hp_bool || cell_active_fe_index.size() == n_active_cells,
1734 unsigned int n_cell_batches_before = 0;
1740 std::vector<unsigned int> cell_partition_l2(
1742 partition_row_index.clear();
1743 partition_row_index.resize(partition + 1, 0);
1744 cell_partition_data.resize(1, 0);
1746 unsigned int counter = 0;
1747 unsigned int missing_macros;
1748 for (
unsigned int part = 0; part < partition; ++part)
1750 neighbor_neighbor_list.resize(0);
1751 neighbor_list.resize(0);
1753 unsigned int partition_l2 = 0;
1754 unsigned int start_up = partition_size[part];
1755 unsigned int partition_counter = 0;
1758 if (neighbor_list.size() == 0)
1761 partition_counter = 0;
1762 for (
unsigned int j = start_up;
1763 j < partition_size[part + 1];
1765 if (cell_partition[partition_list[j]] == part &&
1766 cell_partition_l2[partition_list[j]] ==
1771 partition_counter = 1;
1775 cell_partition_l2[partition_list[start_up]] =
1777 neighbor_neighbor_list.push_back(
1778 partition_list[start_up]);
1779 partition_partition_list[counter++] =
1780 partition_list[start_up];
1787 partition_counter = 0;
1788 for (
const unsigned int neighbor : neighbor_list)
1790 Assert(cell_partition[neighbor] == part,
1792 Assert(cell_partition_l2[neighbor] == partition_l2 - 1,
1794 auto neighbor_it = connectivity.
begin(neighbor);
1795 const auto end_it = connectivity.
end(neighbor);
1796 for (; neighbor_it != end_it; ++neighbor_it)
1798 if (cell_partition[neighbor_it->column()] == part &&
1799 cell_partition_l2[neighbor_it->column()] ==
1802 cell_partition_l2[neighbor_it->column()] =
1804 neighbor_neighbor_list.push_back(
1805 neighbor_it->column());
1806 partition_partition_list[counter++] =
1807 neighbor_it->column();
1808 partition_counter++;
1813 if (partition_counter > 0)
1815 int index_before = neighbor_neighbor_list.size(),
1816 index = index_before;
1821 std::vector<unsigned int> remaining_per_cell_batch(
1823 std::vector<std::vector<unsigned int>>
1824 renumbering_fe_index;
1827 if (hp_bool ==
true)
1829 renumbering_fe_index.resize(max_fe_index + 1);
1830 for (cell = counter - partition_counter;
1834 renumbering_fe_index
1835 [cell_active_fe_index.empty() ?
1837 cell_active_fe_index
1838 [partition_partition_list[cell]]]
1839 .push_back(partition_partition_list[cell]);
1842 for (
unsigned int j = 0; j < max_fe_index + 1; ++j)
1844 remaining_per_cell_batch[j] =
1845 renumbering_fe_index[j].size() %
1846 vectorization_length;
1847 if (remaining_per_cell_batch[j] != 0)
1850 ((renumbering_fe_index[j].size() +
1851 vectorization_length - 1) /
1852 vectorization_length);
1857 remaining_per_cell_batch.resize(1);
1858 remaining_per_cell_batch[0] =
1859 partition_counter % vectorization_length;
1861 partition_counter / vectorization_length;
1862 if (remaining_per_cell_batch[0] != 0)
1869 cluster_size - (missing_macros % cluster_size);
1872 while (missing_macros > 0 || filled ==
false)
1876 index = neighbor_neighbor_list.size();
1877 if (
index == index_before)
1879 if (missing_macros != 0)
1881 neighbor_neighbor_list.resize(0);
1886 index_before =
index;
1889 unsigned int additional =
1890 neighbor_neighbor_list[
index];
1901 for (; neighbor != end; ++neighbor)
1903 if (cell_partition[neighbor->
column()] == part &&
1904 cell_partition_l2[neighbor->
column()] ==
1907 unsigned int this_index = 0;
1908 if (hp_bool ==
true)
1910 cell_active_fe_index.empty() ?
1912 cell_active_fe_index[neighbor
1919 if (missing_macros > 0 ||
1920 remaining_per_cell_batch[this_index] > 0)
1922 cell_partition_l2[neighbor->
column()] =
1924 neighbor_neighbor_list.push_back(
1926 if (hp_bool ==
true)
1927 renumbering_fe_index[this_index]
1928 .push_back(neighbor->
column());
1929 partition_partition_list[counter] =
1932 partition_counter++;
1933 if (remaining_per_cell_batch
1934 [this_index] == 0 &&
1937 remaining_per_cell_batch[this_index]++;
1938 if (remaining_per_cell_batch
1940 vectorization_length)
1942 remaining_per_cell_batch[this_index] =
1945 if (missing_macros == 0)
1948 for (
unsigned int fe_ind = 0;
1949 fe_ind < max_fe_index + 1;
1951 if (remaining_per_cell_batch
1961 if (hp_bool ==
true)
1966 cell = counter - partition_counter;
1967 for (
unsigned int j = 0; j < max_fe_index + 1; ++j)
1969 for (
const unsigned int jj :
1970 renumbering_fe_index[j])
1971 renumbering[cell++] = jj;
1972 if (renumbering_fe_index[j].size() %
1973 vectorization_length !=
1975 irregular_cells[renumbering_fe_index[j].size() /
1976 vectorization_length +
1977 n_cell_batches_before] =
1978 renumbering_fe_index[j].size() %
1979 vectorization_length;
1980 n_cell_batches_before +=
1981 (renumbering_fe_index[j].size() +
1982 vectorization_length - 1) /
1983 vectorization_length;
1984 renumbering_fe_index[j].resize(0);
1989 n_cell_batches_before +=
1990 partition_counter / vectorization_length;
1991 if (partition_counter % vectorization_length != 0)
1993 irregular_cells[n_cell_batches_before] =
1994 partition_counter % vectorization_length;
1995 n_cell_batches_before++;
1999 cell_partition_data.push_back(n_cell_batches_before);
2002 neighbor_list = neighbor_neighbor_list;
2003 neighbor_neighbor_list.resize(0);
2005 partition_row_index[part + 1] =
2006 partition_row_index[part] + partition_l2;
2009 if (hp_bool ==
true)
2011 partition_partition_list.swap(renumbering);
2020 TaskInfo::make_coloring_within_partitions_pre_blocked(
2022 const unsigned int partition,
2023 const std::vector<unsigned int> &cell_partition,
2024 const std::vector<unsigned int> &partition_list,
2025 const std::vector<unsigned int> &partition_size,
2026 std::vector<unsigned int> & partition_color_list)
2028 const unsigned int n_cell_batches = *(cell_partition_data.end() - 2);
2029 std::vector<unsigned int> cell_color(n_blocks, n_cell_batches);
2030 std::vector<bool> color_finder;
2032 partition_row_index.resize(partition + 1);
2033 cell_partition_data.clear();
2034 unsigned int color_counter = 0, index_counter = 0;
2035 for (
unsigned int part = 0; part < partition; ++part)
2037 partition_row_index[part] = index_counter;
2038 unsigned int max_color = 0;
2039 for (
unsigned int k = partition_size[part];
2040 k < partition_size[part + 1];
2043 unsigned int cell = partition_list[k];
2044 unsigned int n_neighbors = connectivity.
row_length(cell);
2048 color_finder.resize(n_neighbors + 1);
2049 for (
unsigned int j = 0; j <= n_neighbors; ++j)
2050 color_finder[j] =
true;
2052 connectivity.
begin(cell),
2053 end = connectivity.
end(cell);
2054 for (; neighbor != end; ++neighbor)
2058 if (cell_partition[neighbor->
column()] == part &&
2059 cell_color[neighbor->
column()] <= n_neighbors)
2060 color_finder[cell_color[neighbor->
column()]] =
false;
2063 cell_color[cell] = 0;
2064 while (color_finder[cell_color[cell]] ==
false)
2066 if (cell_color[cell] > max_color)
2067 max_color = cell_color[cell];
2072 for (
unsigned int color = 0; color <= max_color; ++color)
2074 cell_partition_data.push_back(color_counter);
2076 for (
unsigned int k = partition_size[part];
2077 k < partition_size[part + 1];
2080 unsigned int cell = partition_list[k];
2081 if (cell_color[cell] == color)
2083 partition_color_list[color_counter++] = cell;
2088 cell_partition_data.push_back(n_blocks);
2089 partition_row_index[partition] = index_counter;
2097 const unsigned int cluster_size,
2098 std::vector<unsigned int> & cell_partition,
2099 std::vector<unsigned int> & partition_list,
2100 std::vector<unsigned int> & partition_size,
2101 unsigned int & partition)
const
2110 std::vector<unsigned int> neighbor_list;
2113 std::vector<unsigned int> neighbor_neighbor_list;
2123 unsigned int counter = 0;
2124 unsigned int start_nonboundary =
2125 cell_partition_data.size() == 5 ?
2126 vectorization_length *
2127 (cell_partition_data[2] - cell_partition_data[1]) :
2130 const unsigned int n_cell_batches = *(cell_partition_data.end() - 2);
2131 if (n_cell_batches == 0)
2133 if (scheme == color)
2134 start_nonboundary = n_cell_batches;
2135 if (scheme == partition_color ||
2137 start_nonboundary = ((start_nonboundary + block_size - 1) / block_size);
2138 unsigned int n_blocks;
2139 if (scheme == partition_color ||
2141 n_blocks = this->n_blocks;
2143 n_blocks = n_active_cells;
2145 if (start_nonboundary > n_blocks)
2146 start_nonboundary = n_blocks;
2149 unsigned int start_up = 0;
2151 unsigned int remainder = cluster_size;
2159 if (start_nonboundary > 0)
2161 for (
unsigned int cell = 0; cell < start_nonboundary; ++cell)
2163 const unsigned int cell_nn = cell;
2164 cell_partition[cell_nn] = partition;
2165 neighbor_list.push_back(cell_nn);
2166 partition_list[counter++] = cell_nn;
2167 partition_size.back()++;
2169 start_nonboundary = 0;
2170 remainder -= (start_nonboundary % cluster_size);
2171 if (remainder == cluster_size)
2178 cell_partition[start_up] = partition;
2179 neighbor_list.push_back(start_up);
2180 partition_list[counter++] = start_up;
2181 partition_size.back()++;
2184 if (remainder == cluster_size)
2187 int index_before = neighbor_list.size(),
index = index_before,
2189 while (remainder > 0)
2191 if (
index == index_stop)
2193 index = neighbor_list.size();
2194 if (
index == index_before)
2196 neighbor_list.resize(0);
2199 index_stop = index_before;
2200 index_before =
index;
2203 unsigned int additional = neighbor_list[
index];
2205 connectivity.
begin(additional),
2207 connectivity.
end(additional);
2208 for (; neighbor != end; ++neighbor)
2210 if (cell_partition[neighbor->
column()] ==
2213 partition_size.back()++;
2214 cell_partition[neighbor->
column()] = partition;
2215 neighbor_list.push_back(neighbor->
column());
2216 partition_list[counter++] = neighbor->
column();
2224 while (neighbor_list.size() > 0)
2229 unsigned int partition_counter = 0;
2232 partition_size.push_back(partition_size.back());
2236 for (
const unsigned int cell : neighbor_list)
2238 Assert(cell_partition[cell] == partition - 1,
2240 auto neighbor = connectivity.
begin(cell);
2241 const auto end = connectivity.
end(cell);
2242 for (; neighbor != end; ++neighbor)
2244 if (cell_partition[neighbor->column()] ==
2247 partition_size.back()++;
2248 cell_partition[neighbor->column()] = partition;
2252 neighbor_neighbor_list.push_back(neighbor->column());
2253 partition_list[counter++] = neighbor->column();
2254 partition_counter++;
2258 remainder = cluster_size - (partition_counter % cluster_size);
2259 if (remainder == cluster_size)
2262 int index_before = neighbor_neighbor_list.size(),
2263 index = index_before;
2264 while (remainder > 0)
2266 if (
index == index_stop)
2268 index = neighbor_neighbor_list.size();
2269 if (
index == index_before)
2271 neighbor_neighbor_list.resize(0);
2274 index_stop = index_before;
2275 index_before =
index;
2278 unsigned int additional = neighbor_neighbor_list[
index];
2282 end = connectivity.
end(
2284 for (; neighbor != end; ++neighbor)
2286 if (cell_partition[neighbor->
column()] ==
2289 partition_size.back()++;
2290 cell_partition[neighbor->
column()] = partition;
2291 neighbor_neighbor_list.push_back(neighbor->
column());
2292 partition_list[counter++] = neighbor->
column();
2300 neighbor_list = neighbor_neighbor_list;
2301 neighbor_neighbor_list.resize(0);
2307 for (
unsigned int j = start_up; j < n_blocks; ++j)
2313 remainder = cluster_size;
2325 TaskInfo::update_task_info(
const unsigned int partition)
2327 evens = (partition + 1) / 2;
2328 odds = partition / 2;
2329 n_blocked_workers = odds - (odds + evens + 1) % 2;
2330 n_workers = evens + odds - n_blocked_workers;
2332 partition_evens.resize(partition);
2333 partition_odds.resize(partition);
2334 partition_n_blocked_workers.resize(partition);
2335 partition_n_workers.resize(partition);
2336 for (
unsigned int part = 0; part < partition; ++part)
2338 partition_evens[part] =
2339 (partition_row_index[part + 1] - partition_row_index[part] + 1) / 2;
2340 partition_odds[part] =
2341 (partition_row_index[part + 1] - partition_row_index[part]) / 2;
2342 partition_n_blocked_workers[part] =
2343 partition_odds[part] -
2344 (partition_odds[part] + partition_evens[part] + 1) % 2;
2345 partition_n_workers[part] = partition_evens[part] +
2346 partition_odds[part] -
2347 partition_n_blocked_workers[part];
2357internal::MatrixFreeFunctions::TaskInfo::print_memory_statistics<std::ostream>(
2359 const std::size_t)
const;
size_type row_length(const size_type row) const
void add(const size_type i, const size_type j)
static unsigned int n_threads()
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_NAMESPACE_CLOSE
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
#define AssertDimension(dim1, dim2)
#define AssertIndexRange(index, range)
static ::ExceptionBase & ExcInternalError()
#define AssertThrow(cond, exc)
std::enable_if_t< std::is_fundamental< T >::value, std::size_t > memory_consumption(const T &t)
MinMaxAvg min_max_avg(const double my_value, const MPI_Comm mpi_communicator)
std::vector< Integer > invert_permutation(const std::vector< Integer > &permutation)
unsigned int indicate_power_of_two(const unsigned int vectorization_length)
static const unsigned int invalid_unsigned_int
void parallel_for(Iterator x_begin, Iterator x_end, const Functor &functor, const unsigned int grainsize)
::VectorizedArray< Number, width > min(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
virtual void face(const unsigned int range_index)=0
virtual void zero_dst_vector_range(const unsigned int range_index)=0
virtual void cell(const std::pair< unsigned int, unsigned int > &cell_range)=0
virtual void boundary(const unsigned int range_index)=0
virtual void vector_compress_start()=0
Starts the communication for the vector compress operation.
virtual void cell_loop_post_range(const unsigned int range_index)=0
virtual void vector_update_ghosts_start()=0
Starts the communication for the update ghost values operation.
virtual void cell_loop_pre_range(const unsigned int range_index)=0
virtual void vector_update_ghosts_finish()=0
Finishes the communication for the update ghost values operation.
virtual void vector_compress_finish()=0
Finishes the communication for the vector compress operation.
unsigned int n_ghost_cells
std::size_t memory_consumption() const
std::vector< unsigned int > boundary_partition_data
void loop(MFWorkerInterface &worker) const
std::vector< unsigned int > partition_n_workers
unsigned int vectorization_length
void create_blocks_serial(const std::vector< unsigned int > &cells_with_comm, const unsigned int dofs_per_cell, const bool categories_are_hp, const std::vector< unsigned int > &cell_vectorization_categories, const bool cell_vectorization_categories_strict, const std::vector< unsigned int > &parent_relation, std::vector< unsigned int > &renumbering, std::vector< unsigned char > &incompletely_filled_vectorization)
unsigned int n_active_cells
void print_memory_statistics(StreamType &out, std::size_t data_length) const
std::vector< unsigned int > partition_row_index
std::vector< unsigned int > partition_evens
unsigned int n_blocked_workers
std::vector< unsigned int > partition_n_blocked_workers
std::vector< unsigned int > cell_partition_data
void make_boundary_cells_divisible(std::vector< unsigned int > &boundary_cells)
TasksParallelScheme scheme
std::vector< unsigned int > partition_odds
std::vector< unsigned int > face_partition_data