16 #ifndef dealii_work_stream_h 17 # define dealii_work_stream_h 20 # include <deal.II/base/config.h> 22 # include <deal.II/base/graph_coloring.h> 23 # include <deal.II/base/iterator_range.h> 24 # include <deal.II/base/multithread_info.h> 25 # include <deal.II/base/parallel.h> 26 # include <deal.II/base/template_constraints.h> 27 # include <deal.II/base/thread_local_storage.h> 28 # include <deal.II/base/thread_management.h> 30 # ifdef DEAL_II_WITH_THREADS 31 # include <deal.II/base/thread_management.h> 33 # include <tbb/pipeline.h> 36 # include <functional> 42 DEAL_II_NAMESPACE_OPEN
151 # ifdef DEAL_II_WITH_THREADS 172 namespace Implementation2
177 template <
typename Iterator,
typename ScratchData,
typename CopyData>
196 std::shared_ptr<ScratchData> scratch_data;
197 bool currently_in_use;
203 : currently_in_use(false)
208 , currently_in_use(in_use)
222 : scratch_data(o.scratch_data)
223 , currently_in_use(o.currently_in_use)
319 const Iterator & end,
320 const unsigned int buffer_size,
323 const CopyData & sample_copy_data)
331 for (
unsigned int element = 0; element <
item_buffer.size();
368 for (
unsigned int i = 0; i <
item_buffer.size(); ++i)
375 Assert(current_item !=
nullptr,
376 ExcMessage(
"This can't be. There must be a free item!"));
393 if (current_item->
n_items == 0)
469 template <
typename Iterator,
typename ScratchData,
typename CopyData>
479 const std::function<
void(
const Iterator &, ScratchData &, CopyData &)>
482 : tbb::filter( false)
500 ItemType *current_item =
static_cast<ItemType *
>(item);
513 ScratchData *scratch_data =
nullptr;
515 typename ItemType::ScratchDataList &scratch_data_list =
516 current_item->scratch_data->get();
520 for (
typename ItemType::ScratchDataList::iterator p =
521 scratch_data_list.begin();
522 p != scratch_data_list.end();
524 if (p->currently_in_use ==
false)
526 scratch_data = p->scratch_data.get();
527 p->currently_in_use =
true;
532 if (scratch_data ==
nullptr)
535 new ScratchData(*current_item->sample_scratch_data);
537 typename ItemType::ScratchDataList::value_type
538 new_scratch_object(scratch_data,
true);
539 scratch_data_list.push_back(new_scratch_object);
547 for (
unsigned int i = 0; i < current_item->n_items; ++i)
552 worker(current_item->work_items[i],
554 current_item->copy_datas[i]);
556 catch (
const std::exception &exc)
558 Threads::internal::handle_std_exception(exc);
562 Threads::internal::handle_unknown_exception();
570 typename ItemType::ScratchDataList &scratch_data_list =
571 current_item->scratch_data->get();
573 for (
typename ItemType::ScratchDataList::iterator p =
574 scratch_data_list.begin();
575 p != scratch_data_list.end();
577 if (p->scratch_data.get() == scratch_data)
580 p->currently_in_use =
false;
586 current_item->currently_in_use =
false;
600 const std::function<void(const Iterator &, ScratchData &, CopyData &)>
617 template <
typename Iterator,
typename ScratchData,
typename CopyData>
645 ItemType *current_item =
static_cast<ItemType *
>(item);
650 for (
unsigned int i = 0; i < current_item->n_items; ++i)
655 copier(current_item->copy_datas[i]);
657 catch (
const std::exception &exc)
659 Threads::internal::handle_std_exception(exc);
663 Threads::internal::handle_unknown_exception();
668 current_item->currently_in_use =
false;
681 const std::function<void(const CopyData &)>
copier;
694 namespace Implementation3
701 template <
typename Iterator,
typename ScratchData,
typename CopyData>
704 std::shared_ptr<ScratchData> scratch_data;
705 std::shared_ptr<CopyData> copy_data;
706 bool currently_in_use;
712 : currently_in_use(false)
720 , currently_in_use(in_use)
733 : scratch_data(o.scratch_data)
734 , copy_data(o.copy_data)
735 , currently_in_use(o.currently_in_use)
746 template <
typename Iterator,
typename ScratchData,
typename CopyData>
754 const std::function<
void(
const Iterator &, ScratchData &, CopyData &)>
756 const std::function<
void(
const CopyData &)> &
copier,
758 const CopyData & sample_copy_data)
762 , sample_copy_data(sample_copy_data)
772 typename std::vector<Iterator>::const_iterator> &range)
784 ScratchData *scratch_data =
nullptr;
785 CopyData * copy_data =
nullptr;
791 for (
typename ScratchAndCopyDataList::iterator p =
792 scratch_and_copy_data_list.begin();
793 p != scratch_and_copy_data_list.end();
795 if (p->currently_in_use ==
false)
797 scratch_data = p->scratch_data.get();
798 copy_data = p->copy_data.get();
799 p->currently_in_use =
true;
805 if (scratch_data ==
nullptr)
809 copy_data =
new CopyData(sample_copy_data);
811 scratch_and_copy_data_list.emplace_back(scratch_data,
819 for (
typename std::vector<Iterator>::const_iterator p = range.begin();
826 worker(*p, *scratch_data, *copy_data);
830 catch (
const std::exception &exc)
832 Threads::internal::handle_std_exception(exc);
836 Threads::internal::handle_unknown_exception();
846 for (
typename ScratchAndCopyDataList::iterator p =
847 scratch_and_copy_data_list.begin();
848 p != scratch_and_copy_data_list.end();
850 if (p->scratch_data.get() == scratch_data)
853 p->currently_in_use =
false;
860 ScratchAndCopyDataObjects<Iterator, ScratchData, CopyData>;
874 const std::function<void(const Iterator &, ScratchData &, CopyData &)>
881 const std::function<void(const CopyData &)>
copier;
887 const CopyData & sample_copy_data;
894 # endif // DEAL_II_WITH_THREADS 931 template <
typename Worker,
934 typename ScratchData,
937 run(
const std::vector<std::vector<Iterator>> &colored_iterators,
940 const ScratchData & sample_scratch_data,
941 const CopyData & sample_copy_data,
943 const unsigned int chunk_size = 8);
980 template <
typename Worker,
983 typename ScratchData,
986 run(
const Iterator & begin,
987 const typename identity<Iterator>::type &end,
990 const ScratchData & sample_scratch_data,
991 const CopyData & sample_copy_data,
993 const unsigned int chunk_size = 8)
996 ExcMessage(
"The queue length must be at least one, and preferably " 997 "larger than the number of processors on this system."));
1004 if (!(begin != end))
1009 # ifdef DEAL_II_WITH_THREADS 1014 ScratchData scratch_data = sample_scratch_data;
1015 CopyData copy_data = sample_copy_data;
1017 for (Iterator i = begin; i != end; ++i)
1021 if (
static_cast<const std::function<
1022 void(
const Iterator &, ScratchData &, CopyData &)
> &>(worker))
1023 worker(i, scratch_data, copy_data);
1024 if (
static_cast<const std::function<void(const CopyData &)> &
>(
1029 # ifdef DEAL_II_WITH_THREADS 1033 if (
static_cast<const std::function<void(const CopyData &)> &
>(copier))
1036 internal::Implementation2::
1037 IteratorRangeToItemStream<Iterator, ScratchData, CopyData>
1038 iterator_range_to_item_stream(begin,
1042 sample_scratch_data,
1046 worker_filter(worker);
1048 copier_filter(copier);
1051 tbb::pipeline assembly_line;
1052 assembly_line.add_filter(iterator_range_to_item_stream);
1053 assembly_line.add_filter(worker_filter);
1054 assembly_line.add_filter(copier_filter);
1057 assembly_line.run(queue_length);
1059 assembly_line.clear();
1077 std::vector<std::vector<Iterator>> all_iterators(1);
1078 for (Iterator p = begin; p != end; ++p)
1079 all_iterators[0].push_back(p);
1084 sample_scratch_data,
1102 template <
typename Worker,
1104 typename IteratorRangeType,
1105 typename ScratchData,
1107 typename =
typename std::enable_if<
1110 run(IteratorRangeType iterator_range,
1113 const ScratchData &sample_scratch_data,
1114 const CopyData & sample_copy_data,
1116 const unsigned int chunk_size = 8)
1119 run(iterator_range.begin(),
1120 iterator_range.end(),
1123 sample_scratch_data,
1134 template <
typename Worker,
1137 typename ScratchData,
1143 const ScratchData & sample_scratch_data,
1144 const CopyData & sample_copy_data,
1146 const unsigned int chunk_size = 8)
1150 iterator_range.
end(),
1153 sample_scratch_data,
1161 template <
typename Worker,
1164 typename ScratchData,
1167 run(
const std::vector<std::vector<Iterator>> &colored_iterators,
1170 const ScratchData & sample_scratch_data,
1171 const CopyData & sample_copy_data,
1172 const unsigned int queue_length,
1173 const unsigned int chunk_size)
1176 ExcMessage(
"The queue length must be at least one, and preferably " 1177 "larger than the number of processors on this system."));
1179 Assert(chunk_size > 0,
ExcMessage(
"The chunk_size must be at least one."));
1184 # ifdef DEAL_II_WITH_THREADS 1189 ScratchData scratch_data = sample_scratch_data;
1190 CopyData copy_data = sample_copy_data;
1192 for (
unsigned int color = 0; color < colored_iterators.size(); ++color)
1193 for (
typename std::vector<Iterator>::const_iterator p =
1194 colored_iterators[color].begin();
1195 p != colored_iterators[color].end();
1200 if (
static_cast<const std::function<
void(
1201 const Iterator &, ScratchData &, CopyData &)
> &>(worker))
1202 worker(*p, scratch_data, copy_data);
1203 if (
static_cast<const std::function<void(const CopyData &)> &
>(
1208 # ifdef DEAL_II_WITH_THREADS 1212 for (
unsigned int color = 0; color < colored_iterators.size(); ++color)
1213 if (colored_iterators[color].size() > 0)
1215 using WorkerAndCopier = internal::Implementation3::
1216 WorkerAndCopier<Iterator, ScratchData, CopyData>;
1218 using RangeType =
typename std::vector<Iterator>::const_iterator;
1220 WorkerAndCopier worker_and_copier(worker,
1222 sample_scratch_data,
1226 colored_iterators[color].begin(),
1227 colored_iterators[color].end(),
1228 std::bind(&WorkerAndCopier::operator(),
1229 std::ref(worker_and_copier),
1230 std::placeholders::_1),
1268 template <
typename MainClass,
1270 typename ScratchData,
1274 const typename identity<Iterator>::type &end,
1275 MainClass & main_object,
1276 void (MainClass::*worker)(
const Iterator &, ScratchData &, CopyData &),
1277 void (MainClass::*copier)(
const CopyData &),
1278 const ScratchData &sample_scratch_data,
1279 const CopyData & sample_copy_data,
1281 const unsigned int chunk_size = 8)
1287 std::ref(main_object),
1288 std::placeholders::_1,
1289 std::placeholders::_2,
1290 std::placeholders::_3),
1291 std::bind(copier, std::ref(main_object), std::placeholders::_1),
1292 sample_scratch_data,
1299 template <
typename MainClass,
1301 typename ScratchData,
1306 MainClass &main_object,
1307 void (MainClass::*worker)(
const Iterator &, ScratchData &, CopyData &),
1308 void (MainClass::*copier)(
const CopyData &),
1309 const ScratchData &sample_scratch_data,
1310 const CopyData & sample_copy_data,
1312 const unsigned int chunk_size = 8)
1318 std::ref(main_object),
1319 std::placeholders::_1,
1320 std::placeholders::_2,
1321 std::placeholders::_3),
1322 std::bind(copier, std::ref(main_object), std::placeholders::_1),
1323 sample_scratch_data,
1338 template <
typename MainClass,
1339 typename IteratorRangeType,
1340 typename ScratchData,
1342 typename =
typename std::enable_if<
1345 run(IteratorRangeType iterator_range,
1346 MainClass & main_object,
1347 void (MainClass::*worker)(
1351 void (MainClass::*copier)(
const CopyData &),
1352 const ScratchData &sample_scratch_data,
1353 const CopyData & sample_copy_data,
1355 const unsigned int chunk_size = 8)
1358 run(std::begin(iterator_range),
1359 std::end(iterator_range),
1363 sample_scratch_data,
1374 template <
typename MainClass,
1376 typename ScratchData,
1380 MainClass & main_object,
1381 void (MainClass::*worker)(
const Iterator &, ScratchData &, CopyData &),
1382 void (MainClass::*copier)(
const CopyData &),
1383 const ScratchData &sample_scratch_data,
1384 const CopyData & sample_copy_data,
1386 const unsigned int chunk_size = 8)
1389 run(std::begin(iterator_range),
1390 std::end(iterator_range),
1394 sample_scratch_data,
1404 DEAL_II_NAMESPACE_CLOSE
void * operator()(void *item) override
const std::function< void(const Iterator &, ScratchData &, CopyData &)> worker
const std::function< void(const CopyData &)> copier
std::pair< Iterator, Iterator > remaining_iterator_range
std::list< ScratchAndCopyDataObjects > ScratchAndCopyDataList
IteratorOverIterators begin()
void parallel_for(Iterator x_begin, Iterator x_end, const Functor &functor, const unsigned int grainsize)
const std::function< void(const Iterator &, ScratchData &, CopyData &)> worker
ScratchAndCopyDataObjects()
std::vector< Iterator > work_items
virtual void * operator()(void *) override
void * operator()(void *item) override
void operator()(const tbb::blocked_range< typename std::vector< Iterator >::const_iterator > &range)
Threads::ThreadLocalStorage< ScratchDataList > * scratch_data
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)
static ::ExceptionBase & ExcMessage(std::string arg1)
#define Assert(cond, exc)
const ScratchData & sample_scratch_data
std::vector< ItemType > item_buffer
Worker(const std::function< void(const Iterator &, ScratchData &, CopyData &)> &worker, bool copier_exist=true)
std::vector< CopyData > copy_datas
std::list< ScratchDataObject > ScratchDataList
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)
const ScratchData * sample_scratch_data
const std::function< void(const CopyData &)> copier
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)
static unsigned int n_threads()
Threads::ThreadLocalStorage< typename ItemType::ScratchDataList > thread_local_scratch
const unsigned int chunk_size
Copier(const std::function< void(const CopyData &)> &copier)
const ScratchData & sample_scratch_data
static ::ExceptionBase & ExcInternalError()
IteratorOverIterators end() const