16#ifndef dealii_work_stream_h
17# define dealii_work_stream_h
30# ifdef DEAL_II_WITH_TBB
31# ifdef DEAL_II_TBB_WITH_ONEAPI
32# include <tbb/parallel_pipeline.h>
34# include <tbb/pipeline.h>
168# ifdef DEAL_II_WITH_TBB
183 namespace tbb_no_coloring
188 template <
typename Iterator,
typename ScratchData,
typename CopyData>
324 const Iterator &
end,
325 const unsigned int buffer_size,
328 const CopyData & sample_copy_data)
343 item.copy_datas.resize(
chunk_size, sample_copy_data);
344 item.currently_in_use =
false;
370 for (
unsigned int i = 0; i <
item_buffer.size(); ++i)
377 Assert(current_item !=
nullptr,
378 ExcMessage(
"This can't be. There must be a free item!"));
466 template <
typename Worker,
469 typename ScratchData,
476 const ScratchData & sample_scratch_data,
477 const CopyData & sample_copy_data,
478 const unsigned int queue_length,
487 iterator_range_to_item_stream(
begin,
493 auto tbb_item_stream_filter = tbb::make_filter<void, ItemType *>(
495 tbb::filter_mode::serial_in_order,
499 [&](tbb::flow_control &fc) -> ItemType * {
500 if (
const auto item = iterator_range_to_item_stream.
get_item())
509 auto tbb_worker_filter = tbb::make_filter<ItemType *, ItemType *>(
511 tbb::filter_mode::parallel,
513 tbb::filter::parallel,
516 std::function<
void(
const Iterator &, ScratchData &, CopyData &)>(
519 static_cast<bool>(std::function<
void(
const CopyData &)>(copier))](
520 ItemType *current_item) {
532 ScratchData *scratch_data =
nullptr;
536 for (
auto &p : current_item->scratch_data->get())
537 if (p.currently_in_use ==
false)
539 scratch_data = p.scratch_data.get();
540 p.currently_in_use = true;
546 if (scratch_data ==
nullptr)
549 new ScratchData(*current_item->sample_scratch_data);
550 current_item->scratch_data->get().emplace_back(scratch_data,
559 for (
unsigned int i = 0; i < current_item->n_iterators; ++i)
564 worker(current_item->iterators[i],
566 current_item->copy_datas[i]);
568 catch (
const std::exception &exc)
581 for (
auto &p : current_item->scratch_data->get())
582 if (p.scratch_data.get() == scratch_data)
585 p.currently_in_use =
false;
591 if (copier_exist ==
false)
592 current_item->currently_in_use =
false;
600 auto tbb_copier_filter = tbb::make_filter<ItemType *, void>(
602 tbb::filter_mode::serial_in_order,
606 [copier = std::function<
void(
const CopyData &)>(copier)](
607 ItemType *current_item) {
613 for (
unsigned int i = 0; i < current_item->n_iterators; ++i)
617 copier(current_item->copy_datas[i]);
619 catch (
const std::exception &exc)
630 current_item->currently_in_use =
false;
634 tbb::parallel_pipeline(queue_length,
635 tbb_item_stream_filter & tbb_worker_filter &
654 template <
typename Worker,
657 typename ScratchData,
664 const ScratchData & sample_scratch_data,
665 const CopyData & sample_copy_data)
668 ScratchData scratch_data = sample_scratch_data;
669 CopyData copy_data = sample_copy_data;
673 const bool have_worker =
674 (
static_cast<const std::function<
675 void(
const Iterator &, ScratchData &, CopyData &)
> &>(worker)) !=
677 const bool have_copier =
678 (
static_cast<const std::function<
void(
const CopyData &)
> &>(
682 for (Iterator i =
begin; i !=
end; ++i)
685 worker(i, scratch_data, copy_data);
696 template <
typename Worker,
699 typename ScratchData,
702 run(
const std::vector<std::vector<Iterator>> &colored_iterators,
705 const ScratchData & sample_scratch_data,
706 const CopyData & sample_copy_data)
709 ScratchData scratch_data = sample_scratch_data;
710 CopyData copy_data = sample_copy_data;
714 const bool have_worker =
715 (
static_cast<const std::function<
716 void(
const Iterator &, ScratchData &, CopyData &)
> &>(worker)) !=
718 const bool have_copier =
719 (
static_cast<const std::function<
void(
const CopyData &)
> &>(
723 for (
unsigned int color = 0; color < colored_iterators.size(); ++color)
724 if (colored_iterators[color].size() > 0)
725 for (
auto &it : colored_iterators[color])
728 worker(it, scratch_data, copy_data);
738# ifdef DEAL_II_WITH_TBB
746 namespace tbb_colored
753 template <
typename Iterator,
typename ScratchData,
typename CopyData>
768 std::unique_ptr<CopyData> && q,
790 template <
typename Iterator,
typename ScratchData,
typename CopyData>
798 const std::function<
void(
const Iterator &, ScratchData &, CopyData &)>
800 const std::function<
void(
const CopyData &)> &
copier,
816 typename std::vector<Iterator>::const_iterator> &range)
828 ScratchData *scratch_data =
nullptr;
829 CopyData * copy_data =
nullptr;
835 for (
typename ScratchAndCopyDataList::iterator p =
836 scratch_and_copy_data_list.begin();
837 p != scratch_and_copy_data_list.end();
839 if (p->currently_in_use ==
false)
841 scratch_data = p->scratch_data.get();
842 copy_data = p->copy_data.get();
843 p->currently_in_use =
true;
849 if (scratch_data ==
nullptr)
853 scratch_and_copy_data_list.emplace_back(
858 scratch_and_copy_data_list.back().scratch_data.get();
859 copy_data = scratch_and_copy_data_list.back().copy_data.get();
865 for (
typename std::vector<Iterator>::const_iterator p = range.begin();
872 worker(*p, *scratch_data, *copy_data);
876 catch (
const std::exception &exc)
892 for (
typename ScratchAndCopyDataList::iterator p =
893 scratch_and_copy_data_list.begin();
894 p != scratch_and_copy_data_list.end();
896 if (p->scratch_data.get() == scratch_data)
899 p->currently_in_use =
false;
906 ScratchAndCopyDataObjects<Iterator, ScratchData, CopyData>;
920 const std::function<void(
const Iterator &, ScratchData &, CopyData &)>
927 const std::function<void(
const CopyData &)>
copier;
939 template <
typename Worker,
942 typename ScratchData,
945 run(
const std::vector<std::vector<Iterator>> &colored_iterators,
948 const ScratchData & sample_scratch_data,
949 const CopyData & sample_copy_data,
953 for (
unsigned int color = 0; color < colored_iterators.size(); ++color)
954 if (colored_iterators[color].size() > 0)
957 WorkerAndCopier<Iterator, ScratchData, CopyData>;
959 using RangeType =
typename std::vector<Iterator>::const_iterator;
967 colored_iterators[color].
begin(),
968 colored_iterators[color].
end(),
969 [&worker_and_copier](
970 const tbb::blocked_range<
971 typename std::vector<Iterator>::const_iterator> &range) {
972 worker_and_copier(range);
1033 template <
typename Worker,
1036 typename ScratchData,
1039 run(
const std::vector<std::vector<Iterator>> &colored_iterators,
1042 const ScratchData & sample_scratch_data,
1043 const CopyData & sample_copy_data,
1097 template <
typename Worker,
1100 typename ScratchData,
1107 const ScratchData & sample_scratch_data,
1108 const CopyData & sample_copy_data,
1113 ExcMessage(
"The queue length must be at least one, and preferably "
1114 "larger than the number of processors on this system."));
1126# ifdef DEAL_II_WITH_TBB
1127 if (
static_cast<const std::function<
void(
const CopyData &)
> &>(copier))
1134 sample_scratch_data,
1155 std::vector<std::vector<Iterator>> all_iterators(1);
1156 for (Iterator p =
begin; p !=
end; ++p)
1157 all_iterators[0].push_back(p);
1162 sample_scratch_data,
1175 begin,
end, worker, copier, sample_scratch_data, sample_copy_data);
1187 template <
typename Worker,
1189 typename IteratorRangeType,
1190 typename ScratchData,
1192 typename =
typename std::enable_if<
1195 run(IteratorRangeType iterator_range,
1198 const ScratchData &sample_scratch_data,
1199 const CopyData & sample_copy_data,
1204 run(iterator_range.begin(),
1205 iterator_range.end(),
1208 sample_scratch_data,
1219 template <
typename Worker,
1222 typename ScratchData,
1228 const ScratchData & sample_scratch_data,
1229 const CopyData & sample_copy_data,
1235 iterator_range.
end(),
1238 sample_scratch_data,
1246 template <
typename Worker,
1249 typename ScratchData,
1252 run(
const std::vector<std::vector<Iterator>> &colored_iterators,
1255 const ScratchData & sample_scratch_data,
1256 const CopyData & sample_copy_data,
1257 const unsigned int queue_length,
1261 ExcMessage(
"The queue length must be at least one, and preferably "
1262 "larger than the number of processors on this system."));
1270# ifdef DEAL_II_WITH_TBB
1274 sample_scratch_data,
1288 sample_scratch_data,
1336 template <
typename MainClass,
1338 typename ScratchData,
1343 MainClass & main_object,
1344 void (MainClass::*worker)(
const Iterator &, ScratchData &, CopyData &),
1345 void (MainClass::*copier)(
const CopyData &),
1346 const ScratchData &sample_scratch_data,
1347 const CopyData & sample_copy_data,
1354 [&main_object, worker](
const Iterator &iterator,
1355 ScratchData & scratch_data,
1356 CopyData & copy_data) {
1357 (main_object.*worker)(iterator, scratch_data, copy_data);
1359 [&main_object, copier](
const CopyData ©_data) {
1360 (main_object.*copier)(copy_data);
1362 sample_scratch_data,
1369 template <
typename MainClass,
1371 typename ScratchData,
1376 MainClass &main_object,
1377 void (MainClass::*worker)(
const Iterator &, ScratchData &, CopyData &),
1378 void (MainClass::*copier)(
const CopyData &),
1379 const ScratchData &sample_scratch_data,
1380 const CopyData & sample_copy_data,
1387 [&main_object, worker](
const Iterator &iterator,
1388 ScratchData & scratch_data,
1389 CopyData & copy_data) {
1390 (main_object.*worker)(iterator, scratch_data, copy_data);
1392 [&main_object, copier](
const CopyData ©_data) {
1393 (main_object.*copier)(copy_data);
1395 sample_scratch_data,
1410 template <
typename MainClass,
1411 typename IteratorRangeType,
1412 typename ScratchData,
1414 typename =
typename std::enable_if<
1417 run(IteratorRangeType iterator_range,
1418 MainClass & main_object,
1419 void (MainClass::*worker)(
1423 void (MainClass::*copier)(
const CopyData &),
1424 const ScratchData &sample_scratch_data,
1425 const CopyData & sample_copy_data,
1435 sample_scratch_data,
1446 template <
typename MainClass,
1448 typename ScratchData,
1452 MainClass & main_object,
1453 void (MainClass::*worker)(
const Iterator &, ScratchData &, CopyData &),
1454 void (MainClass::*copier)(
const CopyData &),
1455 const ScratchData &sample_scratch_data,
1456 const CopyData & sample_copy_data,
1466 sample_scratch_data,
IteratorOverIterators end() const
IteratorOverIterators begin()
static unsigned int n_threads()
std::list< ScratchAndCopyDataObjects > ScratchAndCopyDataList
WorkerAndCopier(const std::function< void(const Iterator &, ScratchData &, CopyData &)> &worker, const std::function< void(const CopyData &)> &copier, const ScratchData &sample_scratch_data, const CopyData &sample_copy_data)
Threads::ThreadLocalStorage< ScratchAndCopyDataList > data
void operator()(const tbb::blocked_range< typename std::vector< Iterator >::const_iterator > &range)
const std::function< void(const Iterator &, ScratchData &, CopyData &)> worker
typename tbb_colored::ScratchAndCopyDataObjects< Iterator, ScratchData, CopyData > ScratchAndCopyDataObjects
const CopyData & sample_copy_data
const ScratchData & sample_scratch_data
const std::function< void(const CopyData &)> copier
IteratorRangeToItemStream(const Iterator &begin, const Iterator &end, const unsigned int buffer_size, const unsigned int chunk_size, const ScratchData &sample_scratch_data, const CopyData &sample_copy_data)
Threads::ThreadLocalStorage< typename ItemType::ScratchDataList > thread_local_scratch
std::vector< ItemType > item_buffer
const unsigned int chunk_size
std::pair< Iterator, Iterator > remaining_iterator_range
const ScratchData & sample_scratch_data
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_TBB_WITH_ONEAPI
#define DEAL_II_NAMESPACE_CLOSE
#define Assert(cond, exc)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcMessage(std::string arg1)
void handle_unknown_exception()
void handle_std_exception(const std::exception &exc)
VectorType::value_type * end(VectorType &V)
VectorType::value_type * begin(VectorType &V)
void run(const Iterator &begin, const typename identity< Iterator >::type &end, Worker worker, Copier copier, const ScratchData &sample_scratch_data, const CopyData &sample_copy_data)
void run(const std::vector< std::vector< Iterator > > &colored_iterators, Worker worker, Copier copier, const ScratchData &sample_scratch_data, const CopyData &sample_copy_data, const unsigned int chunk_size)
void run(const Iterator &begin, const typename identity< Iterator >::type &end, Worker worker, Copier copier, const ScratchData &sample_scratch_data, const CopyData &sample_copy_data, const unsigned int queue_length, const unsigned int chunk_size)
void run(const std::vector< std::vector< Iterator > > &colored_iterators, Worker worker, Copier copier, const ScratchData &sample_scratch_data, const CopyData &sample_copy_data, const unsigned int queue_length=2 *MultithreadInfo::n_threads(), const unsigned int chunk_size=8)
void parallel_for(Iterator x_begin, Iterator x_end, const Functor &functor, const unsigned int grainsize)
ScratchAndCopyDataObjects(const ScratchAndCopyDataObjects &)
ScratchAndCopyDataObjects(std::unique_ptr< ScratchData > &&p, std::unique_ptr< CopyData > &&q, const bool in_use)
std::unique_ptr< ScratchData > scratch_data
ScratchAndCopyDataObjects()
std::unique_ptr< CopyData > copy_data
std::unique_ptr< ScratchData > scratch_data
ScratchDataObject(ScratchDataObject &&o) noexcept=default
ScratchDataObject(const ScratchDataObject &)
ScratchDataObject(ScratchData *p, const bool in_use)
const ScratchData * sample_scratch_data
std::list< ScratchDataObject > ScratchDataList
std::vector< Iterator > iterators
std::vector< CopyData > copy_datas
Threads::ThreadLocalStorage< ScratchDataList > * scratch_data