16 #ifndef dealii_work_stream_h 17 # define dealii_work_stream_h 30 # ifdef DEAL_II_WITH_THREADS 31 # include <tbb/pipeline.h> 34 # include <functional> 159 # ifdef DEAL_II_WITH_THREADS 175 namespace Implementation2
180 template <
typename Iterator,
typename ScratchData,
typename CopyData>
206 : currently_in_use(false)
211 , currently_in_use(in_use)
296 , scratch_data(nullptr)
297 , sample_scratch_data(nullptr)
298 , currently_in_use(false)
310 const unsigned int buffer_size,
313 const CopyData & sample_copy_data)
317 , sample_scratch_data(sample_scratch_data)
318 , chunk_size(chunk_size)
321 for (
unsigned int element = 0; element <
item_buffer.size();
358 for (
unsigned int i = 0; i <
item_buffer.size(); ++i)
365 Assert(current_item !=
nullptr,
366 ExcMessage(
"This can't be. There must be a free item!"));
383 if (current_item->
n_items == 0)
459 template <
typename Iterator,
typename ScratchData,
typename CopyData>
469 const std::function<
void(
const Iterator &, ScratchData &, CopyData &)>
471 bool copier_exist =
true)
472 : tbb::filter( false)
474 , copier_exist(copier_exist)
506 current_item->scratch_data->get();
510 for (
typename ItemType::ScratchDataList::iterator p =
511 scratch_data_list.begin();
512 p != scratch_data_list.end();
514 if (p->currently_in_use ==
false)
516 scratch_data = p->scratch_data.get();
517 p->currently_in_use =
true;
522 if (scratch_data ==
nullptr)
525 new ScratchData(*current_item->sample_scratch_data);
527 typename ItemType::ScratchDataList::value_type
528 new_scratch_object(scratch_data,
true);
529 scratch_data_list.push_back(std::move(new_scratch_object));
537 for (
unsigned int i = 0; i < current_item->n_items; ++i)
542 worker(current_item->work_items[i],
544 current_item->copy_datas[i]);
546 catch (
const std::exception &exc)
561 current_item->scratch_data->get();
563 for (
typename ItemType::ScratchDataList::iterator p =
564 scratch_data_list.begin();
565 p != scratch_data_list.end();
570 p->currently_in_use =
false;
575 if (copier_exist ==
false)
576 current_item->currently_in_use =
false;
590 const std::function<void(const Iterator &, ScratchData &, CopyData &)>
607 template <
typename Iterator,
typename ScratchData,
typename CopyData>
617 Copier(
const std::function<
void(
const CopyData &)> &copier)
640 for (
unsigned int i = 0; i < current_item->n_items; ++i)
645 copier(current_item->copy_datas[i]);
647 catch (
const std::exception &exc)
658 current_item->currently_in_use =
false;
671 const std::function<void(const CopyData &)>
copier;
684 namespace Implementation3
691 template <
typename Iterator,
typename ScratchData,
typename CopyData>
702 : currently_in_use(false)
710 , currently_in_use(in_use)
723 : scratch_data(o.scratch_data)
724 , copy_data(o.copy_data)
725 , currently_in_use(o.currently_in_use)
736 template <
typename Iterator,
typename ScratchData,
typename CopyData>
744 const std::function<
void(
const Iterator &, ScratchData &, CopyData &)>
746 const std::function<
void(
const CopyData &)> &copier,
748 const CopyData & sample_copy_data)
751 , sample_scratch_data(sample_scratch_data)
752 , sample_copy_data(sample_copy_data)
762 typename std::vector<Iterator>::const_iterator> &range)
775 CopyData * copy_data =
nullptr;
781 for (
typename ScratchAndCopyDataList::iterator p =
782 scratch_and_copy_data_list.begin();
783 p != scratch_and_copy_data_list.end();
785 if (p->currently_in_use ==
false)
787 scratch_data = p->scratch_data.get();
788 copy_data = p->copy_data.get();
789 p->currently_in_use =
true;
795 if (scratch_data ==
nullptr)
799 copy_data =
new CopyData(sample_copy_data);
801 scratch_and_copy_data_list.emplace_back(scratch_data,
809 for (
typename std::vector<Iterator>::const_iterator p = range.begin();
816 worker(*p, *scratch_data, *copy_data);
820 catch (
const std::exception &exc)
836 for (
typename ScratchAndCopyDataList::iterator p =
837 scratch_and_copy_data_list.begin();
838 p != scratch_and_copy_data_list.end();
843 p->currently_in_use =
false;
850 ScratchAndCopyDataObjects<Iterator, ScratchData, CopyData>;
864 const std::function<void(const Iterator &, ScratchData &, CopyData &)>
871 const std::function<void(const CopyData &)>
copier;
884 # endif // DEAL_II_WITH_THREADS 934 template <
typename Worker,
937 typename ScratchData,
940 run(
const std::vector<std::vector<Iterator>> &colored_iterators,
944 const CopyData & sample_copy_data,
998 template <
typename Worker,
1001 typename ScratchData,
1008 const ScratchData & sample_scratch_data,
1009 const CopyData & sample_copy_data,
1014 ExcMessage(
"The queue length must be at least one, and preferably " 1015 "larger than the number of processors on this system."));
1022 if (!(begin != end))
1027 # ifdef DEAL_II_WITH_THREADS 1033 CopyData copy_data = sample_copy_data;
1035 for (Iterator i = begin; i !=
end; ++i)
1039 if (
static_cast<const std::function<
1040 void(
const Iterator &, ScratchData &, CopyData &)
> &>(worker))
1041 worker(i, scratch_data, copy_data);
1042 if (
static_cast<const std::function<void(const CopyData &)> &
>(
1047 # ifdef DEAL_II_WITH_THREADS 1051 if (
static_cast<const std::function<void(const CopyData &)> &
>(copier))
1054 internal::Implementation2::
1055 IteratorRangeToItemStream<Iterator, ScratchData, CopyData>
1056 iterator_range_to_item_stream(begin,
1060 sample_scratch_data,
1064 worker_filter(worker);
1066 copier_filter(copier);
1069 tbb::pipeline assembly_line;
1070 assembly_line.add_filter(iterator_range_to_item_stream);
1071 assembly_line.add_filter(worker_filter);
1072 assembly_line.add_filter(copier_filter);
1075 assembly_line.run(queue_length);
1077 assembly_line.clear();
1095 std::vector<std::vector<Iterator>> all_iterators(1);
1096 for (Iterator p = begin; p !=
end; ++p)
1097 all_iterators[0].push_back(p);
1102 sample_scratch_data,
1120 template <
typename Worker,
1122 typename IteratorRangeType,
1123 typename ScratchData,
1125 typename =
typename std::enable_if<
1128 run(IteratorRangeType iterator_range,
1131 const ScratchData &sample_scratch_data,
1132 const CopyData & sample_copy_data,
1137 run(iterator_range.begin(),
1138 iterator_range.end(),
1152 template <
typename Worker,
1155 typename ScratchData,
1161 const ScratchData & sample_scratch_data,
1162 const CopyData & sample_copy_data,
1168 iterator_range.
end(),
1179 template <
typename Worker,
1182 typename ScratchData,
1185 run(
const std::vector<std::vector<Iterator>> &colored_iterators,
1188 const ScratchData & sample_scratch_data,
1189 const CopyData & sample_copy_data,
1190 const unsigned int queue_length,
1194 ExcMessage(
"The queue length must be at least one, and preferably " 1195 "larger than the number of processors on this system."));
1197 Assert(chunk_size > 0,
ExcMessage(
"The chunk_size must be at least one."));
1202 # ifdef DEAL_II_WITH_THREADS 1208 CopyData copy_data = sample_copy_data;
1210 for (
unsigned int color = 0; color < colored_iterators.size(); ++color)
1211 for (
typename std::vector<Iterator>::const_iterator p =
1212 colored_iterators[color].
begin();
1213 p != colored_iterators[color].end();
1218 if (
static_cast<const std::function<
void(
1219 const Iterator &, ScratchData &, CopyData &)
> &>(worker))
1220 worker(*p, scratch_data, copy_data);
1221 if (
static_cast<const std::function<void(const CopyData &)> &
>(
1226 # ifdef DEAL_II_WITH_THREADS 1230 for (
unsigned int color = 0; color < colored_iterators.size(); ++color)
1231 if (colored_iterators[color].size() > 0)
1233 using WorkerAndCopier = internal::Implementation3::
1234 WorkerAndCopier<Iterator, ScratchData, CopyData>;
1236 using RangeType =
typename std::vector<Iterator>::const_iterator;
1238 WorkerAndCopier worker_and_copier(worker,
1240 sample_scratch_data,
1244 colored_iterators[color].
begin(),
1245 colored_iterators[color].
end(),
1246 [&worker_and_copier](
1247 const tbb::blocked_range<
1248 typename std::vector<Iterator>::const_iterator> &range) {
1249 worker_and_copier(range);
1300 template <
typename MainClass,
1302 typename ScratchData,
1307 MainClass & main_object,
1308 void (MainClass::*worker)(
const Iterator &, ScratchData &, CopyData &),
1309 void (MainClass::*copier)(
const CopyData &),
1310 const ScratchData &sample_scratch_data,
1311 const CopyData & sample_copy_data,
1318 [&main_object, worker](
const Iterator &iterator,
1320 CopyData & copy_data) {
1321 (main_object.*worker)(iterator, scratch_data, copy_data);
1323 [&main_object, copier](
const CopyData ©_data) {
1324 (main_object.*copier)(copy_data);
1333 template <
typename MainClass,
1335 typename ScratchData,
1340 MainClass &main_object,
1341 void (MainClass::*worker)(
const Iterator &, ScratchData &, CopyData &),
1342 void (MainClass::*copier)(
const CopyData &),
1343 const ScratchData &sample_scratch_data,
1344 const CopyData & sample_copy_data,
1351 [&main_object, worker](
const Iterator &iterator,
1353 CopyData & copy_data) {
1354 (main_object.*worker)(iterator, scratch_data, copy_data);
1356 [&main_object, copier](
const CopyData ©_data) {
1357 (main_object.*copier)(copy_data);
1374 template <
typename MainClass,
1375 typename IteratorRangeType,
1376 typename ScratchData,
1378 typename =
typename std::enable_if<
1381 run(IteratorRangeType iterator_range,
1382 MainClass & main_object,
1383 void (MainClass::*worker)(
1387 void (MainClass::*copier)(
const CopyData &),
1388 const ScratchData &sample_scratch_data,
1389 const CopyData & sample_copy_data,
1399 sample_scratch_data,
1410 template <
typename MainClass,
1412 typename ScratchData,
1416 MainClass & main_object,
1417 void (MainClass::*worker)(
const Iterator &, ScratchData &, CopyData &),
1418 void (MainClass::*copier)(
const CopyData &),
1419 const ScratchData &sample_scratch_data,
1420 const CopyData & sample_copy_data,
1430 sample_scratch_data,
void * operator()(void *item) override
typename Implementation3::ScratchAndCopyDataObjects< Iterator, ScratchData, CopyData > ScratchAndCopyDataObjects
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()
std::unique_ptr< ScratchData > scratch_data
ScratchAndCopyDataObjects(ScratchData *p, CopyData *q, const bool in_use)
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
std::unique_ptr< ScratchData > scratch_data
ScratchAndCopyDataObjects(const ScratchAndCopyDataObjects &o)
virtual void * operator()(void *) override
void * operator()(void *item) override
void operator()(const tbb::blocked_range< typename std::vector< Iterator >::const_iterator > &range)
ScratchDataObject(ScratchData *p, const bool in_use)
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
#define DEAL_II_NAMESPACE_CLOSE
VectorType::value_type * end(VectorType &V)
Worker(const std::function< void(const Iterator &, ScratchData &, CopyData &)> &worker, bool copier_exist=true)
std::vector< CopyData > copy_datas
const CopyData & sample_copy_data
std::list< ScratchDataObject > ScratchDataList
MatrixTableIterators::Iterator< TransposeTable< T >, Constness, MatrixTableIterators::Storage::column_major > Iterator
#define DEAL_II_NAMESPACE_OPEN
VectorType::value_type * begin(VectorType &V)
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
std::unique_ptr< CopyData > copy_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
void handle_std_exception(const std::exception &exc)
const unsigned int chunk_size
Copier(const std::function< void(const CopyData &)> &copier)
void handle_unknown_exception()
const ScratchData & sample_scratch_data
Threads::ThreadLocalStorage< ScratchAndCopyDataList > data
static ::ExceptionBase & ExcInternalError()
IteratorOverIterators end() const