16 #ifndef dealii_work_stream_h
17 # define dealii_work_stream_h
30 # ifdef DEAL_II_WITH_TBB
31 # include <tbb/pipeline.h>
34 # include <functional>
164 # ifdef DEAL_II_WITH_TBB
179 namespace tbb_no_coloring
184 template <
typename Iterator,
typename ScratchData,
typename CopyData>
320 const Iterator &
end,
321 const unsigned int buffer_size,
324 const CopyData & sample_copy_data)
332 for (
unsigned int element = 0; element <
item_buffer.size();
369 for (
unsigned int i = 0; i <
item_buffer.size(); ++i)
376 Assert(current_item !=
nullptr,
377 ExcMessage(
"This can't be. There must be a free item!"));
394 if (current_item->
n_items == 0)
470 template <
typename Iterator,
typename ScratchData,
typename CopyData>
480 const std::function<
void(
const Iterator &, ScratchData &, CopyData &)>
483 : tbb::filter( false)
501 ItemType *current_item =
static_cast<ItemType *
>(item);
514 ScratchData *scratch_data =
nullptr;
516 typename ItemType::ScratchDataList &scratch_data_list =
517 current_item->scratch_data->get();
521 for (
typename ItemType::ScratchDataList::iterator p =
522 scratch_data_list.begin();
523 p != scratch_data_list.end();
525 if (p->currently_in_use ==
false)
527 scratch_data = p->scratch_data.get();
528 p->currently_in_use =
true;
533 if (scratch_data ==
nullptr)
536 new ScratchData(*current_item->sample_scratch_data);
538 typename ItemType::ScratchDataList::value_type
539 new_scratch_object(scratch_data,
true);
540 scratch_data_list.push_back(std::move(new_scratch_object));
548 for (
unsigned int i = 0; i < current_item->n_items; ++i)
553 worker(current_item->work_items[i],
555 current_item->copy_datas[i]);
557 catch (
const std::exception &exc)
571 typename ItemType::ScratchDataList &scratch_data_list =
572 current_item->scratch_data->get();
574 for (
typename ItemType::ScratchDataList::iterator p =
575 scratch_data_list.begin();
576 p != scratch_data_list.end();
578 if (p->scratch_data.get() == scratch_data)
581 p->currently_in_use =
false;
587 current_item->currently_in_use =
false;
601 const std::function<void(
const Iterator &, ScratchData &, CopyData &)>
618 template <
typename Iterator,
typename ScratchData,
typename CopyData>
646 ItemType *current_item =
static_cast<ItemType *
>(item);
651 for (
unsigned int i = 0; i < current_item->n_items; ++i)
656 copier(current_item->copy_datas[i]);
658 catch (
const std::exception &exc)
669 current_item->currently_in_use =
false;
682 const std::function<void(
const CopyData &)>
copier;
685 template <
typename Worker,
688 typename ScratchData,
695 const ScratchData & sample_scratch_data,
696 const CopyData & sample_copy_data,
697 const unsigned int queue_length,
702 iterator_range_to_item_stream(
begin,
713 tbb::pipeline assembly_line;
714 assembly_line.add_filter(iterator_range_to_item_stream);
715 assembly_line.add_filter(worker_filter);
716 assembly_line.add_filter(copier_filter);
719 assembly_line.run(queue_length);
721 assembly_line.clear();
739 template <
typename Worker,
742 typename ScratchData,
749 const ScratchData & sample_scratch_data,
750 const CopyData & sample_copy_data)
753 ScratchData scratch_data = sample_scratch_data;
754 CopyData copy_data = sample_copy_data;
758 const bool have_worker =
759 (
static_cast<const std::function<
760 void(
const Iterator &, ScratchData &, CopyData &)
> &>(worker)) !=
762 const bool have_copier =
763 (
static_cast<const std::function<
void(
const CopyData &)
> &>(
767 for (Iterator i =
begin; i !=
end; ++i)
770 worker(i, scratch_data, copy_data);
781 template <
typename Worker,
784 typename ScratchData,
787 run(
const std::vector<std::vector<Iterator>> &colored_iterators,
790 const ScratchData & sample_scratch_data,
791 const CopyData & sample_copy_data)
794 ScratchData scratch_data = sample_scratch_data;
795 CopyData copy_data = sample_copy_data;
799 const bool have_worker =
800 (
static_cast<const std::function<
801 void(
const Iterator &, ScratchData &, CopyData &)
> &>(worker)) !=
803 const bool have_copier =
804 (
static_cast<const std::function<
void(
const CopyData &)
> &>(
808 for (
unsigned int color = 0; color < colored_iterators.size(); ++color)
809 if (colored_iterators[color].size() > 0)
810 for (
auto &it : colored_iterators[color])
813 worker(it, scratch_data, copy_data);
823 # ifdef DEAL_II_WITH_TBB
831 namespace tbb_colored
838 template <
typename Iterator,
typename ScratchData,
typename CopyData>
853 std::unique_ptr<CopyData> && q,
875 template <
typename Iterator,
typename ScratchData,
typename CopyData>
883 const std::function<
void(
const Iterator &, ScratchData &, CopyData &)>
885 const std::function<
void(
const CopyData &)> &
copier,
901 typename std::vector<Iterator>::const_iterator> &range)
913 ScratchData *scratch_data =
nullptr;
914 CopyData * copy_data =
nullptr;
920 for (
typename ScratchAndCopyDataList::iterator p =
921 scratch_and_copy_data_list.begin();
922 p != scratch_and_copy_data_list.end();
924 if (p->currently_in_use ==
false)
926 scratch_data = p->scratch_data.get();
927 copy_data = p->copy_data.get();
928 p->currently_in_use =
true;
934 if (scratch_data ==
nullptr)
938 scratch_and_copy_data_list.emplace_back(
943 scratch_and_copy_data_list.back().scratch_data.get();
944 copy_data = scratch_and_copy_data_list.back().copy_data.get();
950 for (
typename std::vector<Iterator>::const_iterator p = range.begin();
957 worker(*p, *scratch_data, *copy_data);
961 catch (
const std::exception &exc)
977 for (
typename ScratchAndCopyDataList::iterator p =
978 scratch_and_copy_data_list.begin();
979 p != scratch_and_copy_data_list.end();
981 if (p->scratch_data.get() == scratch_data)
984 p->currently_in_use =
false;
991 ScratchAndCopyDataObjects<Iterator, ScratchData, CopyData>;
1005 const std::function<void(
const Iterator &, ScratchData &, CopyData &)>
1012 const std::function<void(
const CopyData &)>
copier;
1024 template <
typename Worker,
1027 typename ScratchData,
1030 run(
const std::vector<std::vector<Iterator>> &colored_iterators,
1033 const ScratchData & sample_scratch_data,
1034 const CopyData & sample_copy_data,
1038 for (
unsigned int color = 0; color < colored_iterators.size(); ++color)
1039 if (colored_iterators[color].size() > 0)
1042 WorkerAndCopier<Iterator, ScratchData, CopyData>;
1044 using RangeType =
typename std::vector<Iterator>::const_iterator;
1048 sample_scratch_data,
1052 colored_iterators[color].
begin(),
1053 colored_iterators[color].
end(),
1054 [&worker_and_copier](
1055 const tbb::blocked_range<
1056 typename std::vector<Iterator>::const_iterator> &range) {
1057 worker_and_copier(range);
1118 template <
typename Worker,
1121 typename ScratchData,
1124 run(
const std::vector<std::vector<Iterator>> &colored_iterators,
1127 const ScratchData & sample_scratch_data,
1128 const CopyData & sample_copy_data,
1182 template <
typename Worker,
1185 typename ScratchData,
1192 const ScratchData & sample_scratch_data,
1193 const CopyData & sample_copy_data,
1198 ExcMessage(
"The queue length must be at least one, and preferably "
1199 "larger than the number of processors on this system."));
1211 # ifdef DEAL_II_WITH_TBB
1212 if (
static_cast<const std::function<
void(
const CopyData &)
> &>(copier))
1219 sample_scratch_data,
1240 std::vector<std::vector<Iterator>> all_iterators(1);
1241 for (Iterator p =
begin; p !=
end; ++p)
1242 all_iterators[0].push_back(p);
1247 sample_scratch_data,
1260 begin,
end, worker, copier, sample_scratch_data, sample_copy_data);
1272 template <
typename Worker,
1274 typename IteratorRangeType,
1275 typename ScratchData,
1277 typename =
typename std::enable_if<
1280 run(IteratorRangeType iterator_range,
1283 const ScratchData &sample_scratch_data,
1284 const CopyData & sample_copy_data,
1289 run(iterator_range.begin(),
1290 iterator_range.end(),
1293 sample_scratch_data,
1304 template <
typename Worker,
1307 typename ScratchData,
1313 const ScratchData & sample_scratch_data,
1314 const CopyData & sample_copy_data,
1320 iterator_range.
end(),
1323 sample_scratch_data,
1331 template <
typename Worker,
1334 typename ScratchData,
1337 run(
const std::vector<std::vector<Iterator>> &colored_iterators,
1340 const ScratchData & sample_scratch_data,
1341 const CopyData & sample_copy_data,
1342 const unsigned int queue_length,
1346 ExcMessage(
"The queue length must be at least one, and preferably "
1347 "larger than the number of processors on this system."));
1355 # ifdef DEAL_II_WITH_TBB
1359 sample_scratch_data,
1373 sample_scratch_data,
1421 template <
typename MainClass,
1423 typename ScratchData,
1428 MainClass & main_object,
1429 void (MainClass::*worker)(
const Iterator &, ScratchData &, CopyData &),
1430 void (MainClass::*copier)(
const CopyData &),
1431 const ScratchData &sample_scratch_data,
1432 const CopyData & sample_copy_data,
1439 [&main_object, worker](
const Iterator &iterator,
1440 ScratchData & scratch_data,
1441 CopyData & copy_data) {
1442 (main_object.*worker)(iterator, scratch_data, copy_data);
1444 [&main_object, copier](
const CopyData ©_data) {
1445 (main_object.*copier)(copy_data);
1447 sample_scratch_data,
1454 template <
typename MainClass,
1456 typename ScratchData,
1461 MainClass &main_object,
1462 void (MainClass::*worker)(
const Iterator &, ScratchData &, CopyData &),
1463 void (MainClass::*copier)(
const CopyData &),
1464 const ScratchData &sample_scratch_data,
1465 const CopyData & sample_copy_data,
1472 [&main_object, worker](
const Iterator &iterator,
1473 ScratchData & scratch_data,
1474 CopyData & copy_data) {
1475 (main_object.*worker)(iterator, scratch_data, copy_data);
1477 [&main_object, copier](
const CopyData ©_data) {
1478 (main_object.*copier)(copy_data);
1480 sample_scratch_data,
1495 template <
typename MainClass,
1496 typename IteratorRangeType,
1497 typename ScratchData,
1499 typename =
typename std::enable_if<
1502 run(IteratorRangeType iterator_range,
1503 MainClass & main_object,
1504 void (MainClass::*worker)(
1508 void (MainClass::*copier)(
const CopyData &),
1509 const ScratchData &sample_scratch_data,
1510 const CopyData & sample_copy_data,
1520 sample_scratch_data,
1531 template <
typename MainClass,
1533 typename ScratchData,
1537 MainClass & main_object,
1538 void (MainClass::*worker)(
const Iterator &, ScratchData &, CopyData &),
1539 void (MainClass::*copier)(
const CopyData &),
1540 const ScratchData &sample_scratch_data,
1541 const CopyData & sample_copy_data,
1551 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)
virtual void * operator()(void *) override
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
TBBCopier(const std::function< void(const CopyData &)> &copier)
const std::function< void(const CopyData &)> copier
void * operator()(void *item) override
TBBWorker(const std::function< void(const Iterator &, ScratchData &, CopyData &)> &worker, bool copier_exist=true)
void * operator()(void *item) override
const std::function< void(const Iterator &, ScratchData &, CopyData &)> worker
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_NAMESPACE_CLOSE
static ::ExceptionBase & ExcInternalError()
#define Assert(cond, exc)
static ::ExceptionBase & ExcMessage(std::string arg1)
void handle_unknown_exception()
void handle_std_exception(const std::exception &exc)
VectorType::value_type * begin(VectorType &V)
VectorType::value_type * end(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)
std::vector< Iterator > work_items
const ScratchData * sample_scratch_data
std::list< ScratchDataObject > ScratchDataList
std::vector< CopyData > copy_datas
Threads::ThreadLocalStorage< ScratchDataList > * scratch_data