16 #ifndef dealii_work_stream_h 17 #define dealii_work_stream_h 20 #include <deal.II/base/config.h> 21 #include <deal.II/base/graph_coloring.h> 22 #include <deal.II/base/multithread_info.h> 23 #include <deal.II/base/thread_management.h> 24 #include <deal.II/base/template_constraints.h> 25 #include <deal.II/base/thread_local_storage.h> 26 #include <deal.II/base/parallel.h> 28 #ifdef DEAL_II_WITH_THREADS 29 # include <deal.II/base/thread_management.h> 30 # include <tbb/pipeline.h> 38 DEAL_II_NAMESPACE_OPEN
148 #ifdef DEAL_II_WITH_THREADS 170 namespace Implementation2
175 template <
typename Iterator,
176 typename ScratchData,
196 std::shared_ptr<ScratchData> scratch_data;
197 bool currently_in_use;
204 currently_in_use (false)
211 currently_in_use (in_use)
224 scratch_data (o.scratch_data),
225 currently_in_use (o.currently_in_use)
323 const unsigned int buffer_size,
326 const CopyData &sample_copy_data)
335 for (
unsigned int element=0; element<
item_buffer.size(); ++element)
378 Assert (current_item !=
nullptr,
ExcMessage (
"This can't be. There must be a free item!"));
396 if (current_item->
n_items == 0)
471 template <
typename Iterator,
472 typename ScratchData,
482 Worker (
const std::function<
void (
const Iterator &,
487 tbb::filter ( false),
503 ItemType *current_item =
static_cast<ItemType *
> (item);
516 ScratchData *scratch_data =
nullptr;
518 typename ItemType::ScratchDataList &
523 for (
typename ItemType::ScratchDataList::iterator
524 p = scratch_data_list.begin();
525 p != scratch_data_list.end(); ++p)
526 if (p->currently_in_use ==
false)
528 scratch_data = p->scratch_data.get();
529 p->currently_in_use =
true;
534 if (scratch_data ==
nullptr)
536 scratch_data =
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 (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)
559 Threads::internal::handle_std_exception (exc);
563 Threads::internal::handle_unknown_exception ();
571 typename ItemType::ScratchDataList &
572 scratch_data_list = current_item->scratch_data->get();
574 for (
typename ItemType::ScratchDataList::iterator p =
575 scratch_data_list.begin(); 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 &,
618 template <
typename Iterator,
619 typename ScratchData,
647 ItemType *current_item =
static_cast<ItemType *
> (item);
652 for (
unsigned int i=0; i<current_item->n_items; ++i)
657 copier (current_item->copy_datas[i]);
659 catch (
const std::exception &exc)
661 Threads::internal::handle_std_exception (exc);
665 Threads::internal::handle_unknown_exception ();
670 current_item->currently_in_use =
false;
683 const std::function<void (const CopyData &)>
copier;
696 namespace Implementation3
703 template <
typename Iterator,
704 typename ScratchData,
708 std::shared_ptr<ScratchData> scratch_data;
709 std::shared_ptr<CopyData> copy_data;
710 bool currently_in_use;
717 currently_in_use (false)
726 currently_in_use (in_use)
739 scratch_data (o.scratch_data),
740 copy_data (o.copy_data),
741 currently_in_use (o.currently_in_use)
754 template <
typename Iterator,
755 typename ScratchData,
766 const std::function<
void (
const CopyData &)> &
copier,
768 const CopyData &sample_copy_data)
773 sample_copy_data (sample_copy_data)
781 void operator() (
const tbb::blocked_range<
typename std::vector<Iterator>::const_iterator> &range)
793 ScratchData *scratch_data =
nullptr;
794 CopyData *copy_data =
nullptr;
800 for (
typename ScratchAndCopyDataList::iterator
801 p = scratch_and_copy_data_list.begin();
802 p != scratch_and_copy_data_list.end(); ++p)
803 if (p->currently_in_use ==
false)
805 scratch_data = p->scratch_data.get();
806 copy_data = p->copy_data.get();
807 p->currently_in_use =
true;
812 if (scratch_data ==
nullptr)
816 copy_data =
new CopyData(sample_copy_data);
818 scratch_and_copy_data_list.emplace_back (scratch_data, copy_data,
true);
824 for (
typename std::vector<Iterator>::const_iterator p=range.begin();
825 p != range.end(); ++p)
836 catch (
const std::exception &exc)
838 Threads::internal::handle_std_exception (exc);
842 Threads::internal::handle_unknown_exception ();
852 for (
typename ScratchAndCopyDataList::iterator p =
853 scratch_and_copy_data_list.begin(); p != scratch_and_copy_data_list.end();
855 if (p->scratch_data.get() == scratch_data)
858 p->currently_in_use =
false;
881 const std::function<void (
const Iterator &,
889 const std::function<void (const CopyData &)>
copier;
895 const CopyData &sample_copy_data;
902 #endif // DEAL_II_WITH_THREADS 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,
951 const unsigned int chunk_size = 8);
988 template <
typename Worker,
991 typename ScratchData,
994 run (
const Iterator &begin,
995 const typename identity<Iterator>::type &end,
998 const ScratchData &sample_scratch_data,
999 const CopyData &sample_copy_data,
1001 const unsigned int chunk_size = 8)
1003 Assert (queue_length > 0,
1004 ExcMessage (
"The queue length must be at least one, and preferably " 1005 "larger than the number of processors on this system."));
1008 ExcMessage (
"The chunk_size must be at least one."));
1013 if (!(begin != end))
1018 #ifdef DEAL_II_WITH_THREADS 1023 ScratchData scratch_data = sample_scratch_data;
1024 CopyData copy_data = sample_copy_data;
1026 for (Iterator i=begin; i!=end; ++i)
1030 if (
static_cast<const std::function<
void (
const Iterator &,
1032 CopyData &)
>& >(worker))
1033 worker (i, scratch_data, copy_data);
1034 if (
static_cast<const std::function<void (const CopyData &)>&
> 1039 #ifdef DEAL_II_WITH_THREADS 1043 if (
static_cast<const std::function<void (const CopyData &)>&
>(copier))
1047 iterator_range_to_item_stream (begin, end,
1050 sample_scratch_data,
1057 tbb::pipeline assembly_line;
1058 assembly_line.add_filter (iterator_range_to_item_stream);
1059 assembly_line.add_filter (worker_filter);
1060 assembly_line.add_filter (copier_filter);
1063 assembly_line.run (queue_length);
1065 assembly_line.clear ();
1083 std::vector<std::vector<Iterator> > all_iterators (1);
1084 for (Iterator p=begin; p!=end; ++p)
1085 all_iterators[0].push_back (p);
1089 sample_scratch_data,
1100 template <
typename Worker,
1103 typename ScratchData,
1106 run (
const std::vector<std::vector<Iterator> > &colored_iterators,
1109 const ScratchData &sample_scratch_data,
1110 const CopyData &sample_copy_data,
1111 const unsigned int queue_length,
1112 const unsigned int chunk_size)
1114 Assert (queue_length > 0,
1115 ExcMessage (
"The queue length must be at least one, and preferably " 1116 "larger than the number of processors on this system."));
1119 ExcMessage (
"The chunk_size must be at least one."));
1124 #ifdef DEAL_II_WITH_THREADS 1129 ScratchData scratch_data = sample_scratch_data;
1130 CopyData copy_data = sample_copy_data;
1132 for (
unsigned int color=0; color<colored_iterators.size(); ++color)
1133 for (
typename std::vector<Iterator>::const_iterator p = colored_iterators[color].begin();
1134 p != colored_iterators[color].end(); ++p)
1138 if (
static_cast<const std::function<
void (
const Iterator &,
1140 CopyData &)
>& >(worker))
1141 worker (*p, scratch_data, copy_data);
1142 if (
static_cast<const std::function<void (const CopyData &)>&
>(copier))
1146 #ifdef DEAL_II_WITH_THREADS 1150 for (
unsigned int color=0; color<colored_iterators.size(); ++color)
1151 if (colored_iterators[color].size() > 0)
1158 typename std::vector<Iterator>::const_iterator
1161 WorkerAndCopier worker_and_copier (worker,
1163 sample_scratch_data,
1166 tbb::parallel_for (tbb::blocked_range<RangeType>
1167 (colored_iterators[color].begin(),
1168 colored_iterators[color].end(),
1170 std::bind (&WorkerAndCopier::operator(),
1171 std::ref(worker_and_copier),
1172 std::placeholders::_1),
1173 tbb::auto_partitioner());
1212 template <
typename MainClass,
1214 typename ScratchData,
1218 const typename identity<Iterator>::type &end,
1219 MainClass &main_object,
1220 void (MainClass::*worker) (
const Iterator &,
1223 void (MainClass::*copier) (
const CopyData &),
1224 const ScratchData &sample_scratch_data,
1225 const CopyData &sample_copy_data,
1227 const unsigned int chunk_size = 8)
1232 std::ref (main_object),
1233 std::placeholders::_1, std::placeholders::_2, std::placeholders::_3),
1235 std::ref (main_object),
1236 std::placeholders::_1),
1237 sample_scratch_data,
1248 DEAL_II_NAMESPACE_CLOSE
void * operator()(void *item)
ScratchAndCopyDataObjects()
std::vector< Iterator > work_items
const std::function< void(const CopyData &)> copier
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)
const std::function< void(const Iterator &, ScratchData &, CopyData &)> worker
#define Assert(cond, exc)
const ScratchData & sample_scratch_data
std::list< ScratchDataObject > ScratchDataList
std::vector< ItemType > item_buffer
void * operator()(void *item)
Worker(const std::function< void(const Iterator &, ScratchData &, CopyData &)> &worker, bool copier_exist=true)
const std::function< void(const Iterator &, ScratchData &, CopyData &)> worker
std::vector< CopyData > copy_datas
const std::function< void(const CopyData &)> copier
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)
const ScratchData * sample_scratch_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 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
virtual void * operator()(void *)
const unsigned int chunk_size
std::pair< Iterator, Iterator > remaining_iterator_range
Copier(const std::function< void(const CopyData &)> &copier)
const ScratchData & sample_scratch_data
static ::ExceptionBase & ExcInternalError()