17 #ifndef __deal2__work_stream_h
18 #define __deal2__work_stream_h
21 #include <deal.II/base/config.h>
22 #include <deal.II/base/graph_coloring.h>
23 #include <deal.II/base/multithread_info.h>
24 #include <deal.II/base/thread_management.h>
25 #include <deal.II/base/template_constraints.h>
26 #include <deal.II/base/std_cxx1x/function.h>
27 #include <deal.II/base/std_cxx1x/bind.h>
28 #include <deal.II/base/thread_local_storage.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
138 #ifdef DEAL_II_WITH_THREADS
159 namespace Implementation2
164 template <
typename Iterator,
165 typename ScratchData,
184 std_cxx1x::shared_ptr<ScratchData> scratch_data;
185 bool currently_in_use;
192 currently_in_use (false)
199 currently_in_use (in_use)
212 scratch_data (o.scratch_data),
213 currently_in_use (o.currently_in_use)
312 const unsigned int buffer_size,
315 const CopyData &sample_copy_data)
320 sample_scratch_data (sample_scratch_data),
321 chunk_size (chunk_size)
324 for (
unsigned int element=0; element<
item_buffer.size(); ++element)
329 item_buffer[element].work_items.resize (chunk_size,
333 item_buffer[element].copy_datas.resize (chunk_size,
359 Assert (current_item != 0,
ExcMessage (
"This can't be. There must be a free item!"));
377 if (current_item->
n_items == 0)
458 const CopyData &sample_copy_data)
483 template <
typename Iterator,
484 typename ScratchData,
497 Worker (
const std_cxx1x::function<
void (
const Iterator &,
502 tbb::filter ( false),
518 ItemType *current_item =
static_cast<ItemType *
> (item);
531 ScratchData *scratch_data = 0;
533 typename ItemType::ScratchDataList &
538 for (
typename ItemType::ScratchDataList::iterator
539 p = scratch_data_list.begin();
540 p != scratch_data_list.end(); ++p)
541 if (p->currently_in_use ==
false)
543 scratch_data = p->scratch_data.get();
544 p->currently_in_use =
true;
549 if (scratch_data == 0)
551 scratch_data =
new ScratchData(*current_item->sample_scratch_data);
553 typename ItemType::ScratchDataList::value_type
554 new_scratch_object (scratch_data,
true);
555 scratch_data_list.push_back (new_scratch_object);
563 for (
unsigned int i=0; i<current_item->n_items; ++i)
568 worker (current_item->work_items[i],
570 current_item->copy_datas[i]);
572 catch (
const std::exception &exc)
574 Threads::internal::handle_std_exception (exc);
578 Threads::internal::handle_unknown_exception ();
586 typename ItemType::ScratchDataList &
587 scratch_data_list = current_item->scratch_data->get();
589 for (
typename ItemType::ScratchDataList::iterator p =
590 scratch_data_list.begin(); p != scratch_data_list.end();
592 if (p->scratch_data.get() == scratch_data)
595 p->currently_in_use =
false;
601 current_item->currently_in_use =
false;
616 const std_cxx1x::function<void (
const Iterator &,
637 template <
typename Iterator,
638 typename ScratchData,
671 ItemType *current_item =
static_cast<ItemType *
> (item);
676 for (
unsigned int i=0; i<current_item->n_items; ++i)
681 copier (current_item->copy_datas[i]);
683 catch (
const std::exception &exc)
685 Threads::internal::handle_std_exception (exc);
689 Threads::internal::handle_unknown_exception ();
694 current_item->currently_in_use =
false;
707 const std_cxx1x::function<void (const CopyData &)>
copier;
719 namespace Implementation3
724 template <
typename Iterator,
725 typename ScratchData,
744 std_cxx1x::shared_ptr<ScratchData> scratch_data;
745 std_cxx1x::shared_ptr<CopyData> copy_data;
746 bool currently_in_use;
753 currently_in_use (false)
762 currently_in_use (in_use)
775 scratch_data (o.scratch_data),
776 copy_data (o.copy_data),
777 currently_in_use (o.currently_in_use)
849 const typename std::vector<Iterator>::const_iterator &end,
850 const unsigned int buffer_size,
858 sample_scratch_data (sample_scratch_data),
859 sample_copy_data (sample_copy_data),
860 chunk_size (chunk_size)
862 Assert (begin != end,
ExcMessage (
"This class is not prepared to deal with empty ranges!"));
864 for (
unsigned int element=0; element<
item_buffer.size(); ++element)
873 item_buffer[element].work_items.resize (chunk_size,*begin);
901 Assert (current_item != 0,
ExcMessage (
"This can't be. There must be a free item!"));
923 if (current_item->
n_items == 0)
1011 template <
typename Iterator,
1012 typename ScratchData,
1028 const std_cxx1x::function<
void (
const CopyData &)> &
copier)
1030 tbb::filter ( false),
1046 ItemType *current_item =
static_cast<ItemType *
> (item);
1060 ScratchData *scratch_data = 0;
1061 CopyData *copy_data = 0;
1063 typename ItemType::ScratchAndCopyDataList &
1068 for (
typename ItemType::ScratchAndCopyDataList::iterator
1069 p = scratch_and_copy_data_list.begin();
1070 p != scratch_and_copy_data_list.end(); ++p)
1071 if (p->currently_in_use ==
false)
1073 scratch_data = p->scratch_data.get();
1074 copy_data = p->copy_data.get();
1075 p->currently_in_use =
true;
1080 if (scratch_data == 0)
1083 scratch_data =
new ScratchData(*current_item->sample_scratch_data);
1084 copy_data =
new CopyData(*current_item->sample_copy_data);
1086 typename ItemType::ScratchAndCopyDataList::value_type
1087 new_scratch_object (scratch_data, copy_data,
true);
1088 scratch_and_copy_data_list.push_back (new_scratch_object);
1096 for (
unsigned int i=0; i<current_item->n_items; ++i)
1101 worker (current_item->work_items[i],
1107 catch (
const std::exception &exc)
1109 Threads::internal::handle_std_exception (exc);
1113 Threads::internal::handle_unknown_exception ();
1121 typename ItemType::ScratchAndCopyDataList &
1122 scratch_and_copy_data_list = current_item->scratch_and_copy_data->get();
1124 for (
typename ItemType::ScratchAndCopyDataList::iterator p =
1125 scratch_and_copy_data_list.begin(); p != scratch_and_copy_data_list.end();
1127 if (p->scratch_data.get() == scratch_data)
1130 p->currently_in_use =
false;
1135 current_item->currently_in_use =
false;
1149 const std_cxx1x::function<void (
const Iterator &,
1157 const std_cxx1x::function<void (const CopyData &)>
copier;
1162 #endif // DEAL_II_WITH_THREADS
1200 template <
typename Worker,
1203 typename ScratchData,
1207 const typename identity<Iterator>::type &end,
1210 const ScratchData &sample_scratch_data,
1211 const CopyData &sample_copy_data,
1213 const unsigned int chunk_size = 8)
1215 Assert (queue_length > 0,
1216 ExcMessage (
"The queue length must be at least one, and preferably "
1217 "larger than the number of processors on this system."));
1220 ExcMessage (
"The chunk_size must be at least one."));
1225 if (!(begin != end))
1230 #ifdef DEAL_II_WITH_THREADS
1235 ScratchData scratch_data = sample_scratch_data;
1236 CopyData copy_data = sample_copy_data;
1238 for (Iterator i=begin; i!=end; ++i)
1242 if (
static_cast<const std_cxx1x::function<
void (
const Iterator &,
1244 CopyData &)
>& >(worker))
1245 worker (i, scratch_data, copy_data);
1246 if (
static_cast<const std_cxx1x::function<void (const CopyData &)>&
>
1251 #ifdef DEAL_II_WITH_THREADS
1256 iterator_range_to_item_stream (begin, end,
1259 sample_scratch_data,
1263 if (
static_cast<const std_cxx1x::function<void (const CopyData &)>&
>(copier))
1269 tbb::pipeline assembly_line;
1270 assembly_line.add_filter (iterator_range_to_item_stream);
1271 assembly_line.add_filter (worker_filter);
1272 assembly_line.add_filter (copier_filter);
1275 assembly_line.run (queue_length);
1277 assembly_line.clear ();
1284 tbb::pipeline assembly_line;
1285 assembly_line.add_filter (iterator_range_to_item_stream);
1286 assembly_line.add_filter (worker_filter);
1289 assembly_line.run (queue_length);
1291 assembly_line.clear ();
1333 template <
typename Worker,
1336 typename ScratchData,
1339 run (
const std::vector<std::vector<Iterator> > &colored_iterators,
1342 const ScratchData &sample_scratch_data,
1343 const CopyData &sample_copy_data,
1345 const unsigned int chunk_size = 8)
1347 Assert (queue_length > 0,
1348 ExcMessage (
"The queue length must be at least one, and preferably "
1349 "larger than the number of processors on this system."));
1352 ExcMessage (
"The chunk_size must be at least one."));
1357 #ifdef DEAL_II_WITH_THREADS
1362 ScratchData scratch_data = sample_scratch_data;
1363 CopyData copy_data = sample_copy_data;
1365 for (
unsigned int color=0; color<colored_iterators.size(); ++color)
1366 for (
typename std::vector<Iterator>::const_iterator p = colored_iterators[color].begin();
1367 p != colored_iterators[color].end(); ++p)
1371 if (
static_cast<const std_cxx1x::function<
void (
const Iterator &,
1373 CopyData &)
>& >(worker))
1374 worker (*p, scratch_data, copy_data);
1375 if (
static_cast<const std_cxx1x::function<void (const CopyData &)>&
>(copier))
1379 #ifdef DEAL_II_WITH_THREADS
1383 for (
unsigned int color=0; color<colored_iterators.size(); ++color)
1384 if (colored_iterators[color].size() > 0)
1388 iterator_range_to_item_stream (colored_iterators[color].begin(),
1389 colored_iterators[color].end(),
1392 sample_scratch_data,
1397 worker_and_copier_filter (worker, copier);
1400 tbb::pipeline assembly_line;
1401 assembly_line.add_filter (iterator_range_to_item_stream);
1402 assembly_line.add_filter (worker_and_copier_filter);
1405 assembly_line.run (queue_length);
1407 assembly_line.clear ();
1445 template <
typename MainClass,
1447 typename ScratchData,
1451 const typename identity<Iterator>::type &end,
1452 MainClass &main_object,
1453 void (MainClass::*worker) (
const Iterator &,
1456 void (MainClass::*copier) (
const CopyData &),
1457 const ScratchData &sample_scratch_data,
1458 const CopyData &sample_copy_data,
1460 const unsigned int chunk_size = 8)
1464 std_cxx1x::bind (worker,
1465 std_cxx1x::ref (main_object),
1466 std_cxx1x::_1, std_cxx1x::_2, std_cxx1x::_3),
1467 std_cxx1x::bind (copier,
1468 std_cxx1x::ref (main_object),
1470 sample_scratch_data,
1481 DEAL_II_NAMESPACE_CLOSE
IteratorRangeToItemStream(const typename std::vector< Iterator >::const_iterator &begin, const typename std::vector< Iterator >::const_iterator &end, const unsigned int buffer_size, const unsigned int chunk_size, const ScratchData &sample_scratch_data, const CopyData &sample_copy_data)
void init_buffer_elements(const unsigned int element)
void * operator()(void *item)
std::pair< typename std::vector< Iterator >::const_iterator, typename std::vector< Iterator >::const_iterator > remaining_iterator_range
::ExceptionBase & ExcMessage(std::string arg1)
std::vector< Iterator > work_items
void init_buffer_elements(const unsigned int element, const CopyData &sample_copy_data)
ScratchAndCopyDataObjects()
Copier(const std_cxx1x::function< void(const CopyData &)> &copier)
const std_cxx1x::function< void(const CopyData &)> copier
const std_cxx1x::function< void(const Iterator &, ScratchData &, CopyData &)> worker
const ScratchData & sample_scratch_data
std::vector< Iterator > work_items
const CopyData & sample_copy_data
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)
#define Assert(cond, exc)
const unsigned int chunk_size
const ScratchData & sample_scratch_data
std::list< ScratchDataObject > ScratchDataList
std::vector< ItemType > item_buffer
Worker(const std_cxx1x::function< void(const Iterator &, ScratchData &, CopyData &)> &worker, bool copier_exist=true)
std::vector< ItemType > item_buffer
const CopyData * sample_copy_data
std::list< ScratchAndCopyDataObjects > ScratchAndCopyDataList
const std_cxx1x::function< void(const Iterator &, ScratchData &, CopyData &)> worker
void * operator()(void *item)
std::vector< CopyData > copy_datas
const std_cxx1x::function< void(const CopyData &)> copier
WorkerAndCopier(const std_cxx1x::function< void(const Iterator &, ScratchData &, CopyData &)> &worker, const std_cxx1x::function< void(const CopyData &)> &copier)
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=2 *multithread_info.n_threads(), const unsigned int chunk_size=8)
const ScratchData * sample_scratch_data
Threads::ThreadLocalStorage< typename ItemType::ScratchAndCopyDataList > thread_local_scratch_and_copy
MultithreadInfo multithread_info
Threads::ThreadLocalStorage< typename ItemType::ScratchDataList > thread_local_scratch
void * operator()(void *item)
const ScratchData * sample_scratch_data
virtual void * operator()(void *)
const unsigned int chunk_size
::ExceptionBase & ExcInternalError()
std::pair< Iterator, Iterator > remaining_iterator_range
virtual void * operator()(void *)
Threads::ThreadLocalStorage< ScratchAndCopyDataList > * scratch_and_copy_data