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/std_cxx11/function.h> 26 #include <deal.II/base/std_cxx11/bind.h> 27 #include <deal.II/base/thread_local_storage.h> 28 #include <deal.II/base/parallel.h> 30 #ifdef DEAL_II_WITH_THREADS 31 # include <deal.II/base/thread_management.h> 32 # include <tbb/pipeline.h> 40 DEAL_II_NAMESPACE_OPEN
150 #ifdef DEAL_II_WITH_THREADS 172 namespace Implementation2
177 template <
typename Iterator,
178 typename ScratchData,
198 std_cxx11::shared_ptr<ScratchData> scratch_data;
199 bool currently_in_use;
206 currently_in_use (false)
213 currently_in_use (in_use)
226 scratch_data (o.scratch_data),
227 currently_in_use (o.currently_in_use)
325 const unsigned int buffer_size,
328 const CopyData &sample_copy_data)
337 for (
unsigned int element=0; element<
item_buffer.size(); ++element)
380 Assert (current_item != 0,
ExcMessage (
"This can't be. There must be a free item!"));
398 if (current_item->
n_items == 0)
473 template <
typename Iterator,
474 typename ScratchData,
484 Worker (
const std_cxx11::function<
void (
const Iterator &,
489 tbb::filter ( false),
505 ItemType *current_item =
static_cast<ItemType *
> (item);
518 ScratchData *scratch_data = 0;
520 typename ItemType::ScratchDataList &
525 for (
typename ItemType::ScratchDataList::iterator
526 p = scratch_data_list.begin();
527 p != scratch_data_list.end(); ++p)
528 if (p->currently_in_use ==
false)
530 scratch_data = p->scratch_data.get();
531 p->currently_in_use =
true;
536 if (scratch_data == 0)
538 scratch_data =
new ScratchData(*current_item->sample_scratch_data);
540 typename ItemType::ScratchDataList::value_type
541 new_scratch_object (scratch_data,
true);
542 scratch_data_list.push_back (new_scratch_object);
550 for (
unsigned int i=0; i<current_item->n_items; ++i)
555 worker (current_item->work_items[i],
557 current_item->copy_datas[i]);
559 catch (
const std::exception &exc)
561 Threads::internal::handle_std_exception (exc);
565 Threads::internal::handle_unknown_exception ();
573 typename ItemType::ScratchDataList &
574 scratch_data_list = current_item->scratch_data->get();
576 for (
typename ItemType::ScratchDataList::iterator p =
577 scratch_data_list.begin(); p != scratch_data_list.end();
579 if (p->scratch_data.get() == scratch_data)
582 p->currently_in_use =
false;
588 current_item->currently_in_use =
false;
602 const std_cxx11::function<void (
const Iterator &,
620 template <
typename Iterator,
621 typename ScratchData,
649 ItemType *current_item =
static_cast<ItemType *
> (item);
654 for (
unsigned int i=0; i<current_item->n_items; ++i)
659 copier (current_item->copy_datas[i]);
661 catch (
const std::exception &exc)
663 Threads::internal::handle_std_exception (exc);
667 Threads::internal::handle_unknown_exception ();
672 current_item->currently_in_use =
false;
685 const std_cxx11::function<void (const CopyData &)>
copier;
698 namespace Implementation3
705 template <
typename Iterator,
706 typename ScratchData,
710 std_cxx11::shared_ptr<ScratchData> scratch_data;
711 std_cxx11::shared_ptr<CopyData> copy_data;
712 bool currently_in_use;
719 currently_in_use (false)
728 currently_in_use (in_use)
741 scratch_data (o.scratch_data),
742 copy_data (o.copy_data),
743 currently_in_use (o.currently_in_use)
756 template <
typename Iterator,
757 typename ScratchData,
768 const std_cxx11::function<
void (
const CopyData &)> &
copier,
770 const CopyData &sample_copy_data)
775 sample_copy_data (sample_copy_data)
783 void operator() (
const tbb::blocked_range<
typename std::vector<Iterator>::const_iterator> &range)
795 ScratchData *scratch_data = 0;
796 CopyData *copy_data = 0;
802 for (
typename ScratchAndCopyDataList::iterator
803 p = scratch_and_copy_data_list.begin();
804 p != scratch_and_copy_data_list.end(); ++p)
805 if (p->currently_in_use ==
false)
807 scratch_data = p->scratch_data.get();
808 copy_data = p->copy_data.get();
809 p->currently_in_use =
true;
814 if (scratch_data == 0)
818 copy_data =
new CopyData(sample_copy_data);
820 typename ScratchAndCopyDataList::value_type
821 new_scratch_object (scratch_data, copy_data,
true);
822 scratch_and_copy_data_list.push_back (new_scratch_object);
828 for (
typename std::vector<Iterator>::const_iterator p=range.begin();
829 p != range.end(); ++p)
840 catch (
const std::exception &exc)
842 Threads::internal::handle_std_exception (exc);
846 Threads::internal::handle_unknown_exception ();
856 for (
typename ScratchAndCopyDataList::iterator p =
857 scratch_and_copy_data_list.begin(); p != scratch_and_copy_data_list.end();
859 if (p->scratch_data.get() == scratch_data)
862 p->currently_in_use =
false;
885 const std_cxx11::function<void (
const Iterator &,
893 const std_cxx11::function<void (const CopyData &)>
copier;
899 const CopyData &sample_copy_data;
906 #endif // DEAL_II_WITH_THREADS 943 template <
typename Worker,
946 typename ScratchData,
949 run (
const std::vector<std::vector<Iterator> > &colored_iterators,
952 const ScratchData &sample_scratch_data,
953 const CopyData &sample_copy_data,
955 const unsigned int chunk_size = 8);
992 template <
typename Worker,
995 typename ScratchData,
998 run (
const Iterator &begin,
999 const typename identity<Iterator>::type &end,
1002 const ScratchData &sample_scratch_data,
1003 const CopyData &sample_copy_data,
1005 const unsigned int chunk_size = 8)
1007 Assert (queue_length > 0,
1008 ExcMessage (
"The queue length must be at least one, and preferably " 1009 "larger than the number of processors on this system."));
1012 ExcMessage (
"The chunk_size must be at least one."));
1017 if (!(begin != end))
1022 #ifdef DEAL_II_WITH_THREADS 1027 ScratchData scratch_data = sample_scratch_data;
1028 CopyData copy_data = sample_copy_data;
1030 for (Iterator i=begin; i!=end; ++i)
1034 if (
static_cast<const std_cxx11::function<
void (
const Iterator &,
1036 CopyData &)
>& >(worker))
1037 worker (i, scratch_data, copy_data);
1038 if (
static_cast<const std_cxx11::function<void (const CopyData &)>&
> 1043 #ifdef DEAL_II_WITH_THREADS 1047 if (
static_cast<const std_cxx11::function<void (const CopyData &)>&
>(copier))
1051 iterator_range_to_item_stream (begin, end,
1054 sample_scratch_data,
1061 tbb::pipeline assembly_line;
1062 assembly_line.add_filter (iterator_range_to_item_stream);
1063 assembly_line.add_filter (worker_filter);
1064 assembly_line.add_filter (copier_filter);
1067 assembly_line.run (queue_length);
1069 assembly_line.clear ();
1087 std::vector<std::vector<Iterator> > all_iterators (1);
1088 for (Iterator p=begin; p!=end; ++p)
1089 all_iterators[0].push_back (p);
1093 sample_scratch_data,
1104 template <
typename Worker,
1107 typename ScratchData,
1110 run (
const std::vector<std::vector<Iterator> > &colored_iterators,
1113 const ScratchData &sample_scratch_data,
1114 const CopyData &sample_copy_data,
1115 const unsigned int queue_length,
1116 const unsigned int chunk_size)
1118 Assert (queue_length > 0,
1119 ExcMessage (
"The queue length must be at least one, and preferably " 1120 "larger than the number of processors on this system."));
1123 ExcMessage (
"The chunk_size must be at least one."));
1128 #ifdef DEAL_II_WITH_THREADS 1133 ScratchData scratch_data = sample_scratch_data;
1134 CopyData copy_data = sample_copy_data;
1136 for (
unsigned int color=0; color<colored_iterators.size(); ++color)
1137 for (
typename std::vector<Iterator>::const_iterator p = colored_iterators[color].begin();
1138 p != colored_iterators[color].end(); ++p)
1142 if (
static_cast<const std_cxx11::function<
void (
const Iterator &,
1144 CopyData &)
>& >(worker))
1145 worker (*p, scratch_data, copy_data);
1146 if (
static_cast<const std_cxx11::function<void (const CopyData &)>&
>(copier))
1150 #ifdef DEAL_II_WITH_THREADS 1154 for (
unsigned int color=0; color<colored_iterators.size(); ++color)
1155 if (colored_iterators[color].size() > 0)
1162 typename std::vector<Iterator>::const_iterator
1165 WorkerAndCopier worker_and_copier (worker,
1167 sample_scratch_data,
1170 tbb::parallel_for (tbb::blocked_range<RangeType>
1171 (colored_iterators[color].begin(),
1172 colored_iterators[color].end(),
1174 std_cxx11::bind (&WorkerAndCopier::operator(),
1175 std_cxx11::ref(worker_and_copier),
1177 tbb::auto_partitioner());
1216 template <
typename MainClass,
1218 typename ScratchData,
1222 const typename identity<Iterator>::type &end,
1223 MainClass &main_object,
1224 void (MainClass::*worker) (
const Iterator &,
1227 void (MainClass::*copier) (
const CopyData &),
1228 const ScratchData &sample_scratch_data,
1229 const CopyData &sample_copy_data,
1231 const unsigned int chunk_size = 8)
1235 std_cxx11::bind (worker,
1236 std_cxx11::ref (main_object),
1237 std_cxx11::_1, std_cxx11::_2, std_cxx11::_3),
1238 std_cxx11::bind (copier,
1239 std_cxx11::ref (main_object),
1241 sample_scratch_data,
1252 DEAL_II_NAMESPACE_CLOSE
void * operator()(void *item)
ScratchAndCopyDataObjects()
std::vector< Iterator > work_items
const std_cxx11::function< void(const Iterator &, ScratchData &, CopyData &)> worker
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::list< ScratchDataObject > ScratchDataList
std::vector< ItemType > item_buffer
void * operator()(void *item)
Worker(const std_cxx11::function< void(const Iterator &, ScratchData &, CopyData &)> &worker, bool copier_exist=true)
std::vector< CopyData > copy_datas
const std_cxx11::function< void(const CopyData &)> copier
const std_cxx11::function< void(const Iterator &, ScratchData &, CopyData &)> worker
std::list< ScratchAndCopyDataObjects > ScratchAndCopyDataList
const std_cxx11::function< void(const CopyData &)> copier
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_cxx11::function< void(const CopyData &)> &copier)
WorkerAndCopier(const std_cxx11::function< void(const Iterator &, ScratchData &, CopyData &)> &worker, const std_cxx11::function< void(const CopyData &)> &copier, const ScratchData &sample_scratch_data, const CopyData &sample_copy_data)
const ScratchData & sample_scratch_data
static ::ExceptionBase & ExcInternalError()