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,
472 run(
const Iterator & begin,
476 const ScratchData & sample_scratch_data,
477 const CopyData & sample_copy_data,
478 const unsigned int queue_length,
479 const unsigned int chunk_size)
493 iterator_range_to_item_stream(begin,
499 auto tbb_item_stream_filter = tbb::make_filter<void, ItemType *>(
501 tbb::filter_mode::serial_in_order,
505 [&](tbb::flow_control &fc) -> ItemType * {
506 if (
const auto item = iterator_range_to_item_stream.
get_item())
520 auto tbb_worker_filter = tbb::make_filter<ItemType *, ItemType *>(
522 tbb::filter_mode::parallel,
524 tbb::filter::parallel,
527 std::function<
void(
const Iterator &, ScratchData &, CopyData &)>(
530 static_cast<bool>(std::function<
void(
const CopyData &)>(copier))](
531 ItemType *current_item) {
543 ScratchData *scratch_data =
nullptr;
547 for (
auto &p : current_item->scratch_data->get())
548 if (p.currently_in_use ==
false)
550 scratch_data = p.scratch_data.get();
551 p.currently_in_use =
true;
557 if (scratch_data ==
nullptr)
560 new ScratchData(*current_item->sample_scratch_data);
561 current_item->scratch_data->get().emplace_back(scratch_data,
570 for (
unsigned int i = 0; i < current_item->n_iterators; ++i)
575 worker(current_item->iterators[i],
577 current_item->copy_datas[i]);
579 catch (
const std::exception &exc)
592 for (
auto &p : current_item->scratch_data->get())
593 if (p.scratch_data.get() == scratch_data)
596 p.currently_in_use =
false;
602 if (copier_exists ==
false)
603 current_item->currently_in_use =
false;
617 auto tbb_copier_filter = tbb::make_filter<ItemType *, void>(
619 tbb::filter_mode::serial_in_order,
623 [copier = std::function<
void(
const CopyData &)>(copier)](
624 ItemType *current_item) {
630 for (
unsigned int i = 0; i < current_item->n_iterators; ++i)
634 copier(current_item->copy_datas[i]);
636 catch (
const std::exception &exc)
647 current_item->currently_in_use =
false;
655 tbb::parallel_pipeline(queue_length,
656 tbb_item_stream_filter & tbb_worker_filter &
675 template <
typename Worker,
678 typename ScratchData,
681 run(
const Iterator & begin,
685 const ScratchData & sample_scratch_data,
686 const CopyData & sample_copy_data)
689 ScratchData scratch_data = sample_scratch_data;
690 CopyData copy_data = sample_copy_data;
694 const bool have_worker =
695 (
static_cast<const std::function<
696 void(
const Iterator &, ScratchData &, CopyData &)
> &>(worker)) !=
698 const bool have_copier =
699 (
static_cast<const std::function<
void(
const CopyData &)
> &>(
703 for (Iterator i = begin; i != end; ++i)
706 worker(i, scratch_data, copy_data);
717 template <
typename Worker,
720 typename ScratchData,
723 run(
const std::vector<std::vector<Iterator>> &colored_iterators,
726 const ScratchData & sample_scratch_data,
727 const CopyData & sample_copy_data)
730 ScratchData scratch_data = sample_scratch_data;
731 CopyData copy_data = sample_copy_data;
735 const bool have_worker =
736 (
static_cast<const std::function<
737 void(
const Iterator &, ScratchData &, CopyData &)
> &>(worker)) !=
739 const bool have_copier =
740 (
static_cast<const std::function<
void(
const CopyData &)
> &>(
744 for (
unsigned int color = 0; color < colored_iterators.size(); ++color)
745 if (colored_iterators[color].size() > 0)
746 for (
auto &it : colored_iterators[color])
749 worker(it, scratch_data, copy_data);
759# ifdef DEAL_II_WITH_TBB
767 namespace tbb_colored
774 template <
typename Iterator,
typename ScratchData,
typename CopyData>
789 std::unique_ptr<CopyData> && q,
811 template <
typename Iterator,
typename ScratchData,
typename CopyData>
819 const std::function<
void(
const Iterator &, ScratchData &, CopyData &)>
821 const std::function<
void(
const CopyData &)> &
copier,
837 typename std::vector<Iterator>::const_iterator> &range)
849 ScratchData *scratch_data =
nullptr;
850 CopyData * copy_data =
nullptr;
856 for (
typename ScratchAndCopyDataList::iterator p =
857 scratch_and_copy_data_list.begin();
858 p != scratch_and_copy_data_list.end();
860 if (p->currently_in_use ==
false)
862 scratch_data = p->scratch_data.get();
863 copy_data = p->copy_data.get();
864 p->currently_in_use =
true;
870 if (scratch_data ==
nullptr)
874 scratch_and_copy_data_list.emplace_back(
879 scratch_and_copy_data_list.back().scratch_data.get();
880 copy_data = scratch_and_copy_data_list.back().copy_data.get();
886 for (
typename std::vector<Iterator>::const_iterator p = range.begin();
893 worker(*p, *scratch_data, *copy_data);
897 catch (
const std::exception &exc)
913 for (
typename ScratchAndCopyDataList::iterator p =
914 scratch_and_copy_data_list.begin();
915 p != scratch_and_copy_data_list.end();
917 if (p->scratch_data.get() == scratch_data)
920 p->currently_in_use =
false;
927 ScratchAndCopyDataObjects<Iterator, ScratchData, CopyData>;
941 const std::function<void(
const Iterator &, ScratchData &, CopyData &)>
948 const std::function<void(
const CopyData &)>
copier;
960 template <
typename Worker,
963 typename ScratchData,
966 run(
const std::vector<std::vector<Iterator>> &colored_iterators,
969 const ScratchData & sample_scratch_data,
970 const CopyData & sample_copy_data,
971 const unsigned int chunk_size)
974 for (
unsigned int color = 0; color < colored_iterators.size(); ++color)
975 if (colored_iterators[color].size() > 0)
978 WorkerAndCopier<Iterator, ScratchData, CopyData>;
986 colored_iterators[color].begin(),
987 colored_iterators[color].end(),
988 [&worker_and_copier](
989 const tbb::blocked_range<
990 typename std::vector<Iterator>::const_iterator> &range) {
991 worker_and_copier(range);
1052 template <
typename Worker,
1055 typename ScratchData,
1058 run(
const std::vector<std::vector<Iterator>> &colored_iterators,
1061 const ScratchData & sample_scratch_data,
1062 const CopyData & sample_copy_data,
1064 const unsigned int chunk_size = 8);
1116 template <
typename Worker,
1119 typename ScratchData,
1126 const ScratchData & sample_scratch_data,
1127 const CopyData & sample_copy_data,
1129 const unsigned int chunk_size = 8)
1132 ExcMessage(
"The queue length must be at least one, and preferably "
1133 "larger than the number of processors on this system."));
1135 Assert(chunk_size > 0,
ExcMessage(
"The chunk_size must be at least one."));
1140 if (!(begin != end))
1145# ifdef DEAL_II_WITH_TBB
1146 if (
static_cast<const std::function<
void(
const CopyData &)
> &>(copier))
1153 sample_scratch_data,
1174 std::vector<std::vector<Iterator>> all_iterators(1);
1175 for (Iterator p = begin; p != end; ++p)
1176 all_iterators[0].push_back(p);
1181 sample_scratch_data,
1194 begin, end, worker, copier, sample_scratch_data, sample_copy_data);
1206 template <
typename Worker,
1208 typename IteratorRangeType,
1209 typename ScratchData,
1211 typename = std::enable_if_t<has_begin_and_end<IteratorRangeType>>>
1213 run(IteratorRangeType iterator_range,
1216 const ScratchData &sample_scratch_data,
1217 const CopyData & sample_copy_data,
1219 const unsigned int chunk_size = 8)
1222 run(iterator_range.begin(),
1223 iterator_range.end(),
1226 sample_scratch_data,
1237 template <
typename Worker,
1240 typename ScratchData,
1246 const ScratchData & sample_scratch_data,
1247 const CopyData & sample_copy_data,
1249 const unsigned int chunk_size = 8)
1253 iterator_range.
end(),
1256 sample_scratch_data,
1264 template <
typename Worker,
1267 typename ScratchData,
1270 run(
const std::vector<std::vector<Iterator>> &colored_iterators,
1273 const ScratchData & sample_scratch_data,
1274 const CopyData & sample_copy_data,
1275 const unsigned int queue_length,
1276 const unsigned int chunk_size)
1279 ExcMessage(
"The queue length must be at least one, and preferably "
1280 "larger than the number of processors on this system."));
1282 Assert(chunk_size > 0,
ExcMessage(
"The chunk_size must be at least one."));
1288# ifdef DEAL_II_WITH_TBB
1292 sample_scratch_data,
1306 sample_scratch_data,
1354 template <
typename MainClass,
1356 typename ScratchData,
1361 MainClass & main_object,
1362 void (MainClass::*worker)(const Iterator &, ScratchData &, CopyData &),
1363 void (MainClass::*copier)(const CopyData &),
1364 const ScratchData &sample_scratch_data,
1365 const CopyData & sample_copy_data,
1367 const unsigned
int chunk_size = 8)
1373 [&main_object, worker](
const Iterator &iterator,
1374 ScratchData & scratch_data,
1375 CopyData & copy_data) {
1376 (main_object.*worker)(iterator, scratch_data, copy_data);
1378 [&main_object, copier](
const CopyData ©_data) {
1379 (main_object.*copier)(copy_data);
1381 sample_scratch_data,
1388 template <
typename MainClass,
1390 typename ScratchData,
1395 MainClass &main_object,
1396 void (MainClass::*worker)(const Iterator &, ScratchData &, CopyData &),
1397 void (MainClass::*copier)(const CopyData &),
1398 const ScratchData &sample_scratch_data,
1399 const CopyData & sample_copy_data,
1401 const unsigned
int chunk_size = 8)
1407 [&main_object, worker](
const Iterator &iterator,
1408 ScratchData & scratch_data,
1409 CopyData & copy_data) {
1410 (main_object.*worker)(iterator, scratch_data, copy_data);
1412 [&main_object, copier](
const CopyData ©_data) {
1413 (main_object.*copier)(copy_data);
1415 sample_scratch_data,
1430 template <
typename MainClass,
1431 typename IteratorRangeType,
1432 typename ScratchData,
1434 typename = std::enable_if_t<has_begin_and_end<IteratorRangeType>>>
1437 IteratorRangeType iterator_range,
1438 MainClass & main_object,
1439 void (MainClass::*worker)(
1440 const typename
std_cxx20::type_identity_t<IteratorRangeType>::iterator &,
1443 void (MainClass::*copier)(const CopyData &),
1444 const ScratchData &sample_scratch_data,
1445 const CopyData & sample_copy_data,
1447 const unsigned
int chunk_size = 8)
1450 run(std::begin(iterator_range),
1451 std::end(iterator_range),
1455 sample_scratch_data,
1466 template <
typename MainClass,
1468 typename ScratchData,
1472 MainClass & main_object,
1473 void (MainClass::*worker)(const Iterator &, ScratchData &, CopyData &),
1474 void (MainClass::*copier)(const CopyData &),
1475 const ScratchData &sample_scratch_data,
1476 const CopyData & sample_copy_data,
1478 const unsigned
int chunk_size = 8)
1481 run(std::begin(iterator_range),
1482 std::end(iterator_range),
1486 sample_scratch_data,
IteratorOverIterators end() const
IteratorOverIterators begin()
static unsigned int n_threads()
A class that provides a separate storage location on each thread that accesses the object.
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)
void run(const Iterator &begin, const std_cxx20::type_identity_t< Iterator > &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 std_cxx20::type_identity_t< Iterator > &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)
typename type_identity< T >::type type_identity_t
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