MADNESS 0.10.1
macrotaskq.h
Go to the documentation of this file.
1/**
2 \file macrotaskq.h
3 \brief Declares the \c macrotaskq and MacroTaskBase classes
4 \ingroup mra
5
6 A MacroTaskq executes tasks on World objects, e.g. differentiation of a function or other
7 arithmetic. Complex algorithms can be implemented.
8
9 The universe world is split into subworlds, each of them executing macrotasks of the task queue.
10 This improves locality and speedups for large number of compute nodes, by reducing communications
11 within worlds.
12
13 The user defines a macrotask (an example is found in test_vectormacrotask.cc), the tasks are
14 lightweight and carry only bookkeeping information, actual input and output are stored in a
15 cloud (see cloud.h)
16
17 The user-defined macrotask is derived from MacroTaskIntermediate and must implement the run()
18 method. A heterogeneous task queue is possible.
19
20 The result of a macrotask is an object that lives in the universe and that is accessible from all
21 subworlds. The result is accumulated in the universe and must therefore be a WorldObject. Currently we
22 have implemented
23 - Function<T,NDIM>
24 - std::vector<Function<T,NDIM>> (a vector of Function<T,NDIM>)
25 - ScalarResultImpl<T> (a scalar value)
26 - std::vector<std::shared_ptr<ScalarResultImpl<T>>> (a vector of scalar values), shared_ptr for technical reasons
27
28 - std::tuple<std::vector<XXX>, std::vector<YYY>> (a tuple of n vectors of WorldObjects: XXX, YYY, .. = {Function, ScalarResultImpl, ...})
29
30
31 TODO: priority q
32 TODO: task submission from inside task (serialize task instead of replicate)
33 TODO: update documentation
34 TODO: consider serializing task member variables
35
36*/
37
38
39
40#ifndef SRC_MADNESS_MRA_MACROTASKQ_H_
41#define SRC_MADNESS_MRA_MACROTASKQ_H_
42
43// #include <madness/external/gtest/include/gtest/internal/gtest-port.h>
44#include <madness/world/cloud.h>
45#include <madness/world/world.h>
47
48namespace madness {
49
50/// helper class for returning the result of a task, which is not a madness Function, but a simple scalar
51
52/// the result value is accumulated via gaxpy in universe rank=0, after completion of the taskq the final
53/// value can be obtained via get(), which includes a broadcast of the final value to all processes
54template<typename T>
55class ScalarResultImpl : public WorldObject<ScalarResultImpl<T>> {
56public:
57 typedef T value_type;
61
62 /// Disable the default copy constructor
63 ScalarResultImpl(const ScalarResultImpl& other) = delete;
64 // ScalarResultImpl<T>(ScalarResultImpl<T>&& ) = default;
65
66 /// disable assignment operator
68
70 // print("calling destructor of ScalarResultImpl",this->id());
71 // std::cout << std::flush;
72 }
73
74 /// simple assignment of the scalar value
76 value = x;
77 return *this;
78 }
79
81 gaxpy(1.0, x, 1.0,true);
82 return *this;
83 }
84
85 /// accumulate, optional fence
86 void gaxpy(const double a, const T& right, double b, const bool fence=true) {
87 if (this->get_world().rank()==0) {
88 value =a*value + b * right;
89 }
90 else this->send(0, &ScalarResultImpl<T>::gaxpy, a, right, b, fence);
91 }
92
93 template<typename Archive>
94 void serialize(Archive &ar) {
95 ar & value;
96 }
97
98 /// after completion of the taskq get the final value
99 T get() {
100 this->get_world().gop.broadcast_serializable(*this, 0);
101 return value;
102 }
103
104 /// get the local value of this rank, which might differ for different ranks
105 /// for the final value use get()
106 T get_local() const {
107 return value;
108 }
109
110private:
111 /// the scalar value
113};
114
115template<typename T=double>
117public:
119 std::shared_ptr<implT> impl;
120
121 ScalarResult() = default;
122 ScalarResult(World &world) : impl(new implT(world)) {}
123 ScalarResult(const std::shared_ptr<implT>& impl) : impl(impl) {}
125 *(this->impl) = x;
126 return *this;
127 }
128
129 std::shared_ptr<implT> get_impl() const {
130 return impl;
131 }
132
133 void set_impl(const std::shared_ptr<implT>& newimpl) {
134 impl=newimpl;
135 }
136
137 uniqueidT id() const {
138 return impl->id();
139 }
140
141 /// accumulate, optional fence
142 void gaxpy(const double a, const T& right, double b, const bool fence=true) {
143 impl->gaxpy(a,right,b,fence);
144 }
145
146 template<typename Archive>
147 void serialize(Archive &ar) {
148 ar & impl;
149 }
150
151 /// after completion of the taskq get the final value
152 T get() {
153 return impl->get();
154 }
155
156 /// after completion of the taskq get the final value
157 T get_local() const {
158 return impl->get_local();
159 }
160
161};
162
163/// helper function to create a vector of ScalarResultImpl, circumventing problems with the constructors
164template<typename T>
165std::vector<ScalarResult<T>> scalar_result_vector(World& world, std::size_t n) {
166 std::vector<ScalarResult<T>> v;
167 for (std::size_t i=0; i<n; ++i) v.emplace_back(ScalarResult<T>(world));
168 return v;
169}
170
171
172// type traits to check if a template parameter is a WorldContainer
173template<typename>
174struct is_scalar_result_ptr : std::false_type {};
175
176template <typename T>
177struct is_scalar_result_ptr<std::shared_ptr<madness::ScalarResultImpl<T>>> : std::true_type {};
178
179template<typename>
180struct is_scalar_result_ptr_vector : std::false_type {
181};
182
183template<typename T>
184struct is_scalar_result_ptr_vector<std::vector<std::shared_ptr<typename madness::ScalarResultImpl<T>>>> : std::true_type {
185};
186
187// type traits to check if a template parameter is a WorldContainer
188template<typename>
189struct is_scalar_result : std::false_type {};
190
191template <typename T>
192struct is_scalar_result<madness::ScalarResult<T>> : std::true_type {};
193
194template<typename>
195struct is_scalar_result_impl : std::false_type {};
196
197template <typename T>
198struct is_scalar_result<madness::ScalarResultImpl<T>> : std::true_type {};
199
200template<typename>
201struct is_scalar_result_vector : std::false_type {
202};
203
204template<typename T>
205struct is_scalar_result_vector<std::vector<typename madness::ScalarResult<T>>> : std::true_type {
206};
207
208/// check if type is a valid task result: it must be a WorldObject and must implement gaxpy
209template <typename T>
210inline constexpr bool is_valid_task_result_v =
211 is_madness_function<T>::value // Function<T,NDIM>
212 || is_madness_function_vector<T>::value // std::vector<Function<T,NDIM>>
213 || is_scalar_result<T>::value // ScalarResultImpl<T>
214 || is_scalar_result_vector<T>::value // std::vector<std::shared_ptr<ScalarResultImpl<T>>>
215 || is_scalar_result_ptr<T>::value // ScalarResultImpl<T>
216 || is_scalar_result_ptr_vector<T>::value; // std::vector<std::shared_ptr<ScalarResultImpl<T>>>
217
218
219template<typename> struct is_tuple : std::false_type { };
220template<typename ...T> struct is_tuple<std::tuple<T...>> : std::true_type { };
221
222/// given a tuple check recursively if all elements are valid task results
223template<typename tupleT, std::size_t I>
225
226 typedef decay_tuple <tupleT> argtupleT; // removes const, &, etc
227
228 if constexpr(I >= std::tuple_size_v<tupleT>) {
229 // Last case, if nothing is left to iterate, then exit the function
230 return true;
231 } else {
232 using typeT = typename std::tuple_element<I, argtupleT>::type;// use decay types for determining a vector
233 if constexpr (not is_valid_task_result_v<typeT>) {
234 return false;
235 } else {
236 // Going for next element.
237 return check_tuple_is_valid_task_result<tupleT,I+1>();
238 }
239 }
240}
241
242
243
244/// the result type of a macrotask must implement gaxpy
245template<typename T>
246void gaxpy(const double a, ScalarResult<T>& left, const double b, const T& right, const bool fence=true) {
247 left.gaxpy(a, right, b, fence);
248}
249
250template <class Archive, typename T>
251struct madness::archive::ArchiveStoreImpl<Archive, std::shared_ptr<ScalarResultImpl<T>>> {
252 static void store(const Archive& ar, const std::shared_ptr<ScalarResultImpl<T>>& ptr) {
253 bool exists=(ptr) ? true : false;
254 ar & exists;
255 if (exists) ar & ptr->id();
256 }
257};
258
259
260template <class Archive, typename T>
261struct madness::archive::ArchiveLoadImpl<Archive, std::shared_ptr<ScalarResultImpl<T>>> {
262 static void load(const Archive& ar, std::shared_ptr<ScalarResultImpl<T>>& ptr) {
263 bool exists=false;
264 ar & exists;
265 if (exists) {
266 uniqueidT id;
267 ar & id;
268 World* world = World::world_from_id(id.get_world_id());
269 MADNESS_ASSERT(world);
270 auto ptr_opt = (world->ptr_from_id< ScalarResultImpl<T> >(id));
271 if (!ptr_opt)
272 MADNESS_EXCEPTION("ScalarResultImpl: remote operation attempting to use a locally uninitialized object",0);
273 ptr.reset(ptr_opt.value(), [] (ScalarResultImpl<T> *p_) -> void {}); // disable destruction
274 if (!ptr)
275 MADNESS_EXCEPTION("ScalarResultImpl<T> operation attempting to use an unregistered object",0);
276 } else {
277 ptr=nullptr;
278 }
279 }
280};
281
282
283/// base class
285public:
286
287 typedef std::vector<std::shared_ptr<MacroTaskBase> > taskqT;
288
290 virtual ~MacroTaskBase() {};
291
292 double priority=1.0;
294
298
299 bool is_complete() const {return stat==Complete;}
300 bool is_running() const {return stat==Running;}
301 bool is_waiting() const {return stat==Waiting;}
302
303 virtual void run(World& world, Cloud& cloud, taskqT& taskq, const long element, const bool debug) = 0;
304 virtual void cleanup() = 0; // clear static data (presumably persistent input data)
305
306 virtual void print_me(std::string s="") const {
307 printf("this is task with priority %4.1f\n",priority);
308 }
309 virtual void print_me_as_table(std::string s="") const {
310 print("nothing to print");
311 }
313 std::stringstream ss;
314 ss << std::setw(5) << this->get_priority() << " " <<this->stat;
315 return ss.str();
316 }
317
318 double get_priority() const {return priority;}
319 void set_priority(const double p) {priority=p;}
320
321 friend std::ostream& operator<<(std::ostream& os, const MacroTaskBase::Status s) {
322 if (s==MacroTaskBase::Status::Running) os << "Running";
323 if (s==MacroTaskBase::Status::Waiting) os << "Waiting";
324 if (s==MacroTaskBase::Status::Complete) os << "Complete";
325 if (s==MacroTaskBase::Status::Unknown) os << "Unknown";
326 return os;
327 }
328};
329
330
331template<typename macrotaskT>
333
334public:
335
337
339
340 void cleanup() {};
341};
342
343
344
345class MacroTaskQ : public WorldObject< MacroTaskQ> {
346
348 std::shared_ptr<World> subworld_ptr;
350 std::mutex taskq_mutex;
352 long nsubworld=1;
353 std::shared_ptr< WorldDCPmapInterface< Key<1> > > pmap1;
354 std::shared_ptr< WorldDCPmapInterface< Key<2> > > pmap2;
355 std::shared_ptr< WorldDCPmapInterface< Key<3> > > pmap3;
356 std::shared_ptr< WorldDCPmapInterface< Key<4> > > pmap4;
357 std::shared_ptr< WorldDCPmapInterface< Key<5> > > pmap5;
358 std::shared_ptr< WorldDCPmapInterface< Key<6> > > pmap6;
359
360 bool printdebug() const {return printlevel>=10;}
361 bool printprogress() const {return (printlevel>=3) and (not (printdebug()));}
362 bool printtimings() const {return universe.rank()==0 and printlevel>=3;}
363
364public:
365
368 long get_nsubworld() const {return nsubworld;}
369 void set_printlevel(const long p) {printlevel=p;}
370
371 /// create an empty taskq and initialize the subworlds
372 MacroTaskQ(World& universe, int nworld, const long printlevel=0)
375 , taskq()
377 , nsubworld(nworld)
378 , cloud(universe)
379 {
380
382 this->process_pending();
383 }
384
386
387 /// for each process create a world using a communicator shared with other processes by round-robin
388 /// copy-paste from test_world.cc
389static std::shared_ptr<World> create_worlds(World& universe, const std::size_t nsubworld) {
390
391 int color = universe.rank() % nsubworld;
393
394 std::shared_ptr<World> all_worlds;
395 all_worlds.reset(new World(comm));
396
398 return all_worlds;
399 }
400
401 /// run all tasks
402 void run_all() {
403
404 if (printdebug()) print_taskq();
405 if (printtimings()) {
406 print("number of tasks in taskq",taskq.size());
407 print("redirecting output to files task.#####");
408 }
409
410 double cpu0=cpu_time();
413 double cpu1=cpu_time();
414 if (printtimings()) print("cloud replication wall time",cpu1-cpu0);
416 universe.gop.set_forbid_fence(true); // make sure there are no hidden universe fences
424
425 double cpu00=cpu_time();
426
427 World& subworld=get_subworld();
428// if (printdebug()) print("I am subworld",subworld.id());
429 double tasktime=0.0;
430 if (printprogress() and universe.rank()==0) std::cout << "progress in percent: " << std::flush;
431 while (true) {
432 long element=get_scheduled_task_number(subworld);
433 double cpu0=cpu_time();
434 if (element<0) break;
435 std::shared_ptr<MacroTaskBase> task=taskq[element];
436 if (printdebug()) print("starting task no",element, "in subworld",subworld.id(),"at time",wall_time());
437
438 task->run(subworld,cloud, taskq, element, printdebug());
439
440 double cpu1=cpu_time();
441 set_complete(element);
442 tasktime+=(cpu1-cpu0);
443 if (printdebug()) printf("completed task %3ld after %6.1fs at time %6.1fs\n",element,cpu1-cpu0,wall_time());
444
445 // print progress
446 const std::size_t ntask=taskq.size();
447 // return percentile of ntask for element
448 auto in_percentile = [&ntask](const long element) {
449 return std::floor(element/(0.1*(ntask+1)));
450 };
451 auto is_first_in_percentile = [&](const long element) {
452 return (in_percentile(element)!=in_percentile(element-1));
453 };
454 if (printprogress() and is_first_in_percentile(element)) {
455 std::cout << int(in_percentile(element)*10) << " " << std::flush;
456 }
457 }
460 universe.gop.sum(tasktime);
461 if (printprogress() and universe.rank()==0) std::cout << std::endl;
462 double cpu11=cpu_time();
464 if (printtimings()) {
465 printf("completed taskqueue after %4.1fs at time %4.1fs\n", cpu11 - cpu00, wall_time());
466 printf(" total cpu time / per world %4.1fs %4.1fs\n", tasktime, tasktime / universe.size());
467 }
468
469 // cleanup task-persistent input data
470 for (auto& task : taskq) task->cleanup();
471 cloud.clear_cache(subworld);
472 cloud.clear();
473 subworld.gop.fence();
474 subworld.gop.fence();
483 }
484
486 for (const auto& t : vtask) {
487 if (universe.rank()==0) t->set_waiting();
489 }
490 }
491
492 void print_taskq() const {
494 if (universe.rank()==0) {
495 print("\ntaskq on universe rank",universe.rank());
496 print("total number of tasks: ",taskq.size());
497 print(" task batch priority status");
498 for (const auto& t : taskq) t->print_me_as_table();
499 }
501 }
502
503private:
504 void add_replicated_task(const std::shared_ptr<MacroTaskBase>& task) {
505 taskq.push_back(task);
506 }
507
508 /// scheduler is located on universe.rank==0
510 long number=0;
511 if (subworld.rank()==0) {
513 number=r.get();
514 }
515 subworld.gop.broadcast_serializable(number, 0);
516 subworld.gop.fence();
517 return number;
518
519 }
520
523 std::lock_guard<std::mutex> lock(taskq_mutex);
524
525 auto is_Waiting = [](const std::shared_ptr<MacroTaskBase>& mtb_ptr) {return mtb_ptr->is_waiting();};
526 auto it=std::find_if(taskq.begin(),taskq.end(),is_Waiting);
527 if (it!=taskq.end()) {
528 it->get()->set_running();
529 long element=it-taskq.begin();
530 return element;
531 }
532// print("could not find task to schedule");
533 return -1;
534 }
535
536 /// scheduler is located on rank==0
537 void set_complete(const long task_number) const {
538 this->task(ProcessID(0), &MacroTaskQ::set_complete_local, task_number);
539 }
540
541 /// scheduler is located on rank==0
542 void set_complete_local(const long task_number) const {
544 taskq[task_number]->set_complete();
545 }
546
547public:
556private:
557 std::size_t size() const {
558 return taskq.size();
559 }
560
561};
562
563
564
565
566template<typename taskT>
569
570 template<typename Q>
571 struct is_vector : std::false_type {
572 };
573 template<typename Q>
574 struct is_vector<std::vector<Q>> : std::true_type {
575 };
576
577 typedef typename taskT::resultT resultT;
578 typedef typename taskT::argtupleT argtupleT;
580 taskT task;
581 bool debug=false;
582
583 /// RAII class to redirect cout to a file
584 struct io_redirect {
585 std::streambuf* stream_buffer_cout;
586 std::ofstream ofile;
587 bool debug=false;
588
589 io_redirect(const long task_number, std::string filename, bool debug=false) : debug(debug) {
590 constexpr std::size_t bufsize=256;
591 char cfilename[bufsize];
592 std::snprintf(cfilename,bufsize,"%s.%5.5ld",filename.c_str(),task_number);
593 ofile=std::ofstream(cfilename);
594 if (debug) std::cout << "redirecting to file " << cfilename << std::endl;
595 stream_buffer_cout = std::cout.rdbuf(ofile.rdbuf());
596 std::cout.sync_with_stdio(true);
597 }
598
600 std::cout.rdbuf(stream_buffer_cout);
601 ofile.close();
602 std::cout.sync_with_stdio(true);
603 if (debug) std::cout << "redirecting back to cout" << std::endl;
604 }
605 };
606
607
608public:
609
610 /// constructor takes the actual task
611 MacroTask(World &world, taskT &task, std::shared_ptr<MacroTaskQ> taskq_ptr = 0)
613 if (taskq_ptr) {
614 // for the time being this condition must hold because tasks are
615 // constructed as replicated objects and are not broadcast to other processes
616 MADNESS_CHECK(world.id()==taskq_ptr->get_world().id());
617 }
618 }
619
620 void set_debug(const bool value) {
621 debug=value;
622 }
623
624
625 /// this mimicks the original call to the task functor, called from the universe
626
627 /// store all input to the cloud, create output Function<T,NDIM> in the universe,
628 /// create the batched task and shove it into the taskq. Possibly execute the taskq.
629 template<typename ... Ts>
630 resultT operator()(const Ts &... args) {
631
632 const bool immediate_execution = (not taskq_ptr);
633 if (not taskq_ptr) taskq_ptr.reset(new MacroTaskQ(world, world.size()));
634 if (debug) taskq_ptr->set_printlevel(20);
635
636 auto argtuple = std::tie(args...);
637 static_assert(std::is_same<decltype(argtuple), argtupleT>::value, "type or number of arguments incorrect");
638
639 // partition the argument vector into batches
640 auto partitioner=task.partitioner;
641 if (not partitioner) partitioner.reset(new MacroTaskPartitioner);
642 partitioner->set_nsubworld(world.size());
643 partitionT partition = partitioner->partition_tasks(argtuple);
644
645 // store input and output: output being a pointer to a universe function (vector)
646 recordlistT inputrecords = taskq_ptr->cloud.store(world, argtuple);
647 resultT result = task.allocator(world, argtuple);
648 auto outputrecords =prepare_output_records(taskq_ptr->cloud, result);
649
650 // create tasks and add them to the taskq
652 for (const auto& batch_prio : partition) {
653 vtask.push_back(
654 std::shared_ptr<MacroTaskBase>(new MacroTaskInternal(task, batch_prio, inputrecords, outputrecords)));
655 }
656 taskq_ptr->add_tasks(vtask);
657
658 if (immediate_execution) taskq_ptr->run_all();
659
660 return result;
661 }
662
663//private:
664
666 std::shared_ptr<MacroTaskQ> taskq_ptr;
667private:
668
669
670 /// store *pointers* to the result WorldObject in the cloud and return the recordlist
672 if constexpr (is_tuple<resultT>::value) {
673 static_assert(check_tuple_is_valid_task_result<resultT,0>(),
674 "tuple has invalid result type in prepare_output_records");
675 } else {
676 static_assert(is_valid_task_result_v<resultT>, "unknown result type in prepare_output_records");
677 }
678
679 if (debug) print("storing pointers to output in cloud");
680 // store an element of the tuple only
681 auto store_output_records = [&](const auto& result) {
682 recordlistT outputrecords;
683 typedef std::decay_t<decltype(result)> argT;
684 if constexpr (is_madness_function<argT>::value) {
685 outputrecords += cloud.store(world, result.get_impl().get()); // store pointer to FunctionImpl
686 } else if constexpr (is_madness_function_vector<argT>::value) {
687 outputrecords += cloud.store(world, get_impl(result));
688 } else if constexpr (is_scalar_result<argT>::value) {
689 outputrecords += cloud.store(world, result.get_impl()); // store pointer to ScalarResultImpl
690 } else if constexpr (is_vector<argT>::value) {
692 // argT = std::vector<ScalarResult<T>>
693 std::vector<std::shared_ptr<typename argT::value_type::implT>> v;
694 for (const auto& ptr : result) v.push_back(ptr.get_impl());
695 outputrecords+=cloud.store(world,v);
696 } else {
697 MADNESS_EXCEPTION("\n\n unknown vector result type in prepare_input ", 1);
698 }
699 } else {
700 MADNESS_EXCEPTION("should not be here",1);
701 }
702 return outputrecords;
703 };
704
705 recordlistT outputrecords;
706 if constexpr (is_tuple<resultT>::value) {
707 // loop over tuple elements -- args is the individual tuple element
708 std::apply([&](auto &&... args) {
709 (( outputrecords+=store_output_records(args) ), ...);
710 }, result);
711 } else {
712 outputrecords=store_output_records(result);
713 }
714 return outputrecords;
715 }
716
717
718 class MacroTaskInternal : public MacroTaskIntermediate<MacroTask> {
719
720 typedef decay_tuple<typename taskT::argtupleT> argtupleT; // removes const, &, etc
721 typedef typename taskT::resultT resultT;
724 public:
725 taskT task;
726 std::string get_name() const {
727 if (task.name=="unknown_task") return typeid(task).name();
728 return task.name;
729 }
730
731 MacroTaskInternal(const taskT &task, const std::pair<Batch,double> &batch_prio,
734 if constexpr (is_tuple<resultT>::value) {
735 static_assert(check_tuple_is_valid_task_result<resultT,0>(),
736 "tuple has invalid result type in prepare_output_records");
737 } else {
738 static_assert(is_valid_task_result_v<resultT>, "unknown result type in prepare_output_records");
739 }
740 this->task.batch=batch_prio.first;
741 this->priority=batch_prio.second;
742 }
743
744
745 virtual void print_me(std::string s="") const {
746 print("this is task",get_name(),"with batch", task.batch,"priority",this->get_priority());
747 }
748
749 virtual void print_me_as_table(std::string s="") const {
750 std::stringstream ss;
751 std::string name=get_name();
752 std::size_t namesize=std::min(std::size_t(28),name.size());
753 name += std::string(28-namesize,' ');
754
755 std::stringstream ssbatch;
756 ssbatch << task.batch;
757 std::string strbatch=ssbatch.str();
758 int nspaces=std::max(int(0),35-int(ssbatch.str().size()));
759 strbatch+=std::string(nspaces,' ');
760
761 ss << name
762 << std::setw(10) << strbatch
764 print(ss.str());
765 }
766
767 /// loop over the tuple elements of both tuples and execute the operation op on each element pair
768 template<typename tupleT, typename tupleR, typename opT, std::size_t I=0>
769 void binary_tuple_loop(tupleT& tuple1, tupleR& tuple2, opT& op) const {
770 if constexpr(I < std::tuple_size_v<tupleT>) {
771 auto& element1=std::get<I>(tuple1);
772 auto& element2=std::get<I>(tuple2);
773 op(element1,element2);
774 binary_tuple_loop<tupleT, tupleR, opT, I+1>(tuple1,tuple2,op);
775 }
776 }
777
778 template<typename tupleT, typename opT, std::size_t I=0>
779 void unary_tuple_loop(tupleT& tuple, opT& op) const {
780 if constexpr(I < std::tuple_size_v<tupleT>) {
781 auto& element1=std::get<I>(tuple);
782 op(element1);
783 unary_tuple_loop<tupleT,opT, I+1>(tuple,op);
784 }
785 }
786
787 /// accumulate the result of the task into the final result living in the universe
788 template<typename resultT1, std::size_t I=0>
789 typename std::enable_if<is_tuple<resultT1>::value, void>::type
790 accumulate_into_final_result(World &subworld, resultT1 &final_result, const resultT1 &tmp_result, const argtupleT& argtuple) {
791 if constexpr(I < std::tuple_size_v<resultT1>) {
792 using elementT = typename std::tuple_element<I, resultT>::type;// use decay types for determining a vector
793 auto element_final=std::get<I>(final_result);
794 auto element_tmp=std::get<I>(tmp_result);
795 accumulate_into_final_result<elementT>(subworld, element_final, element_tmp, argtuple);
796 accumulate_into_final_result<resultT1,I+1>(subworld, final_result, tmp_result, argtuple);
797 }
798 }
799
800 /// accumulate the result of the task into the final result living in the universe
801 template<typename resultT1>
802 typename std::enable_if<not is_tuple<resultT1>::value, void>::type
803 accumulate_into_final_result(World &subworld, resultT1 &result, const resultT1 &result_tmp, const argtupleT& argtuple) {
805 result_tmp.compress();
806 gaxpy(1.0,result,1.0, result_tmp);
808 compress(subworld, result_tmp);
809 // resultT1 tmp1=task.allocator(subworld,argtuple);
810 // tmp1=task.batch.template insert_result_batch(tmp1,result_tmp);
811 gaxpy(1.0,result,1.0,result_tmp,false);
812 // was using operator+=, but this requires a fence, which is not allowed here..
813 // result += tmp1;
814 } else if constexpr (is_scalar_result<resultT1>::value) {
815 gaxpy(1.0, result, 1.0, result_tmp.get_local(), false);
816 } else if constexpr (is_scalar_result_vector<resultT1>::value) {
817 // resultT1 tmp1=task.allocator(subworld,argtuple);
818 // tmp1=task.batch.template insert_result_batch(tmp1,result_tmp);
819 std::size_t sz=result.size();
820 for (int i=0; i<sz; ++i) {
821 gaxpy(1.0, result[i], 1.0, result_tmp[i].get_local(), false);
822 }
823 }
824
825 }
826
827
828 void run(World &subworld, Cloud &cloud, MacroTaskBase::taskqT &taskq, const long element, const bool debug) {
829 io_redirect io(element,get_name()+"_task",debug);
830 const argtupleT argtuple = cloud.load<argtupleT>(subworld, inputrecords);
831 const argtupleT batched_argtuple = task.batch.template copy_input_batch(argtuple);
832 try {
833 print("starting task no",element, ", '",get_name(),"', in subworld",subworld.id(),"at time",wall_time());
834 double cpu0=cpu_time();
835 resultT result_batch = std::apply(task, batched_argtuple); // lives in the subworld, is a batch of the full vector (if applicable)
836 double cpu1=cpu_time();
837 std::size_t bufsize=256;
838 char buffer[bufsize];
839 std::snprintf(buffer,bufsize,"completed task %3ld after %6.1fs at time %6.1fs\n",element,cpu1-cpu0,wall_time());
840 print(std::string(buffer));
841
842 // move the result from the batch to the final result, all still in subworld
843 auto insert_batch = [&](auto& element1, auto& element2) {
844 typedef std::decay_t<decltype(element1)> decay_type;;
845 if constexpr (is_vector<decay_type>::value) {
846 element1=task.batch.template insert_result_batch(element1,element2);
847 } else {
848 std::swap(element1,element2);
849 }
850 };
851 resultT result_subworld=task.allocator(subworld,argtuple);
852 if constexpr (is_tuple<resultT>::value) {
853 binary_tuple_loop(result_subworld, result_batch, insert_batch);
854 } else {
855 insert_batch(result_subworld,result_batch);
856 }
857
858 // accumulate the subworld-local results into the final, universe result
859 resultT result_universe=get_output(subworld, cloud); // lives in the universe
860
861 accumulate_into_final_result<resultT>(subworld, result_universe, result_subworld, argtuple);
862
863 } catch (std::exception& e) {
864 print("failing task no",element,"in subworld",subworld.id(),"at time",wall_time());
865 print(e.what());
867 print("\n\n");
868 MADNESS_EXCEPTION("failing task",1);
869 }
870
871 };
872
873 template<typename T, std::size_t NDIM>
874 static Function<T,NDIM> pointer2WorldObject(const std::shared_ptr<FunctionImpl<T,NDIM>> impl) {
875 Function<T,NDIM> result;
876 result.set_impl(impl);
877 return result;
878 }
879
880 template<typename T, std::size_t NDIM>
881 static std::vector<Function<T,NDIM>> pointer2WorldObject(const std::vector<std::shared_ptr<FunctionImpl<T,NDIM>>> v_impl) {
882 std::vector<Function<T,NDIM>> vresult;
883 vresult.resize(v_impl.size());
884 set_impl(vresult,v_impl);
885 return vresult;
886 }
887
888 template<typename T>
889 static ScalarResult<T> pointer2WorldObject(const std::shared_ptr<ScalarResultImpl<T>> sr_impl) {
890 return ScalarResult(sr_impl);
891 }
892
893 template<typename T>
894 static std::vector<ScalarResult<T>> pointer2WorldObject(const std::vector<std::shared_ptr<ScalarResultImpl<T>>> v_sr_impl) {
895 std::vector<ScalarResult<T>> vresult(v_sr_impl.size());
896 for (auto i=0; i<v_sr_impl.size(); ++i) {
897 vresult[i].set_impl(v_sr_impl[i]);
898 }
899 return vresult;
900 }
901
902 /// return the WorldObjects or the result functions living in the universe
903
904 /// read the pointers to the universe WorldObjects from the cloud,
905 /// convert them to actual WorldObjects and return them
906 resultT get_output(World &subworld, Cloud &cloud) {
907 resultT result;
908
909 // save outputrecords, because they will be consumed by the cloud
910 auto outputrecords1 = this->outputrecords;
911
912 // turn an element of the tuple of pointers into an element of the tuple of WorldObjects
913 auto doit = [&](auto& element) {
914 typedef std::decay_t<decltype(element)> elementT;
915
916 // load the elements from the cloud -- they contain pointers to WorldObjects
918 typedef typename elementT::value_type::implT implT;
919 auto ptr_element = cloud.consuming_load<std::vector<std::shared_ptr<implT>>>(
920 subworld, outputrecords1);
921 element = pointer2WorldObject(ptr_element);
922 }
923 else if constexpr (is_madness_function<elementT>::value) {
924 typedef typename elementT::implT implT;
925 auto ptr_element = cloud.consuming_load<std::shared_ptr<implT>>(subworld, outputrecords1);
926 element = pointer2WorldObject(ptr_element);
927 }
928 else if constexpr (is_scalar_result_vector<elementT>::value) { // std::vector<ScalarResult<T>>
929 typedef typename elementT::value_type ScalarResultT;
930 typedef typename ScalarResultT::implT implT;
931 typedef std::vector<std::shared_ptr<implT>> vptrT;
932 auto ptr_element = cloud.consuming_load<vptrT>(subworld, outputrecords1);
933 element = pointer2WorldObject(ptr_element);
934 }
935 else if constexpr (is_scalar_result<elementT>::value) {
936 // elementT is a ScalarResultImpl<T>
937 // in cloud we store a std::shared_ptr<ScalarResultImpl<T>>
938 auto ptr_element = cloud.consuming_load<std::shared_ptr<typename elementT::implT>>(subworld, outputrecords1);
939 element = pointer2WorldObject(ptr_element);
940 }
941 else {
942 MADNESS_EXCEPTION("confused about the type of the result", 1);
943 }
944 };
945 if constexpr (is_tuple<resultT>::value) {
946 static_assert(check_tuple_is_valid_task_result<resultT, 0>(),
947 "invalid tuple task result -- must be vectors of functions");
948 static_assert(is_tuple<resultT>::value, "is a tuple");
949
950 // loop over all tuple elements
951 // 1. load the pointers to the WorldObjects living in the universe
952 // 2. create WorldObjects from the pointers and copy them into the tuple of type resultT
953
954 // turn the tuple of pointers into a tuple of WorldObjects
955 unary_tuple_loop(result,doit);
956
957
958 } else {
959 doit(result);
960
961 }
962 return result;
963 }
964
965 };
966
967};
968
970public:
972 std::string name="unknown_task";
973 std::shared_ptr<MacroTaskPartitioner> partitioner=0;
975};
976
977
978} /* namespace madness */
979
980#endif /* SRC_MADNESS_MRA_MACROTASKQ_H_ */
Wrapper around MPI_Comm. Has a shallow copy constructor; use Create(Get_group()) for deep copy.
Definition safempi.h:490
Intracomm Split(int Color, int Key=0) const
Definition safempi.h:635
a batch consists of a 2D-input batch and a 1D-output batch: K-batch <- (I-batch, J-batch)
Definition macrotaskpartitioner.h:139
cloud class
Definition cloud.h:147
void clear()
Definition cloud.h:258
recordlistT store(madness::World &world, const T &source)
Definition cloud.h:314
Recordlist< keyT > recordlistT
Definition cloud.h:160
void replicate(const std::size_t chunk_size=INT_MAX)
Definition cloud.h:337
void print_size(World &universe)
Definition cloud.h:193
T load(madness::World &world, const recordlistT recordlist) const
Definition cloud.h:274
void clear_cache(World &subworld)
Definition cloud.h:252
void print_timings(World &universe) const
Definition cloud.h:230
T consuming_load(madness::World &world, recordlistT &recordlist) const
similar to load, but will consume the recordlist
Definition cloud.h:287
static void set_default_pmap(World &world)
Sets the default process map.
Definition mraimpl.h:3574
static std::shared_ptr< WorldDCPmapInterface< Key< NDIM > > > & get_pmap()
Returns the default process map.
Definition funcdefaults.h:389
static void set_pmap(const std::shared_ptr< WorldDCPmapInterface< Key< NDIM > > > &value)
Sets the default process map (does not redistribute existing functions)
Definition funcdefaults.h:405
FunctionImpl holds all Function state to facilitate shallow copy semantics.
Definition funcimpl.h:945
A multiresolution adaptive numerical function.
Definition mra.h:139
void set_impl(const std::shared_ptr< FunctionImpl< T, NDIM > > &impl)
Replace current FunctionImpl with provided new one.
Definition mra.h:646
A future is a possibly yet unevaluated value.
Definition future.h:373
T & get(bool dowork=true) &
Gets the value, waiting if necessary.
Definition future.h:574
base class
Definition macrotaskq.h:284
void set_running()
Definition macrotaskq.h:296
virtual ~MacroTaskBase()
Definition macrotaskq.h:290
void set_waiting()
Definition macrotaskq.h:297
MacroTaskBase()
Definition macrotaskq.h:289
virtual void cleanup()=0
virtual void print_me(std::string s="") const
Definition macrotaskq.h:306
std::string print_priority_and_status_to_string() const
Definition macrotaskq.h:312
void set_complete()
Definition macrotaskq.h:295
double priority
Definition macrotaskq.h:292
bool is_complete() const
Definition macrotaskq.h:299
Status
Definition macrotaskq.h:293
@ Complete
Definition macrotaskq.h:293
@ Running
Definition macrotaskq.h:293
@ Unknown
Definition macrotaskq.h:293
@ Waiting
Definition macrotaskq.h:293
bool is_running() const
Definition macrotaskq.h:300
enum madness::MacroTaskBase::Status stat
double get_priority() const
Definition macrotaskq.h:318
void set_priority(const double p)
Definition macrotaskq.h:319
virtual void print_me_as_table(std::string s="") const
Definition macrotaskq.h:309
std::vector< std::shared_ptr< MacroTaskBase > > taskqT
Definition macrotaskq.h:287
virtual void run(World &world, Cloud &cloud, taskqT &taskq, const long element, const bool debug)=0
friend std::ostream & operator<<(std::ostream &os, const MacroTaskBase::Status s)
Definition macrotaskq.h:321
bool is_waiting() const
Definition macrotaskq.h:301
Definition macrotaskq.h:332
MacroTaskIntermediate()
Definition macrotaskq.h:336
void cleanup()
Definition macrotaskq.h:340
~MacroTaskIntermediate()
Definition macrotaskq.h:338
Definition macrotaskq.h:969
MacroTaskOperationBase()
Definition macrotaskq.h:974
Batch batch
Definition macrotaskq.h:971
std::shared_ptr< MacroTaskPartitioner > partitioner
Definition macrotaskq.h:973
std::string name
Definition macrotaskq.h:972
partition one (two) vectors into 1D (2D) batches.
Definition macrotaskpartitioner.h:197
std::list< std::pair< Batch, double > > partitionT
Definition macrotaskpartitioner.h:201
Definition macrotaskq.h:345
long nsubworld
Definition macrotaskq.h:352
std::mutex taskq_mutex
Definition macrotaskq.h:350
bool printdebug() const
Definition macrotaskq.h:360
static void set_pmap(World &world)
Definition macrotaskq.h:548
void run_all()
run all tasks
Definition macrotaskq.h:402
void set_complete(const long task_number) const
scheduler is located on rank==0
Definition macrotaskq.h:537
World & universe
Definition macrotaskq.h:347
std::shared_ptr< WorldDCPmapInterface< Key< 1 > > > pmap1
Definition macrotaskq.h:353
std::shared_ptr< WorldDCPmapInterface< Key< 3 > > > pmap3
Definition macrotaskq.h:355
MacroTaskBase::taskqT taskq
Definition macrotaskq.h:349
void add_tasks(MacroTaskBase::taskqT &vtask)
Definition macrotaskq.h:485
long get_scheduled_task_number(World &subworld)
scheduler is located on universe.rank==0
Definition macrotaskq.h:509
void set_complete_local(const long task_number) const
scheduler is located on rank==0
Definition macrotaskq.h:542
World & get_subworld()
Definition macrotaskq.h:367
MacroTaskQ(World &universe, int nworld, const long printlevel=0)
create an empty taskq and initialize the subworlds
Definition macrotaskq.h:372
std::shared_ptr< WorldDCPmapInterface< Key< 4 > > > pmap4
Definition macrotaskq.h:356
std::size_t size() const
Definition macrotaskq.h:557
std::shared_ptr< WorldDCPmapInterface< Key< 5 > > > pmap5
Definition macrotaskq.h:357
void print_taskq() const
Definition macrotaskq.h:492
std::shared_ptr< World > subworld_ptr
Definition macrotaskq.h:348
bool printtimings() const
Definition macrotaskq.h:362
std::shared_ptr< WorldDCPmapInterface< Key< 2 > > > pmap2
Definition macrotaskq.h:354
bool printprogress() const
Definition macrotaskq.h:361
std::shared_ptr< WorldDCPmapInterface< Key< 6 > > > pmap6
Definition macrotaskq.h:358
void set_printlevel(const long p)
Definition macrotaskq.h:369
long printlevel
Definition macrotaskq.h:351
madness::Cloud cloud
Definition macrotaskq.h:366
long get_nsubworld() const
Definition macrotaskq.h:368
void add_replicated_task(const std::shared_ptr< MacroTaskBase > &task)
Definition macrotaskq.h:504
~MacroTaskQ()
Definition macrotaskq.h:385
static std::shared_ptr< World > create_worlds(World &universe, const std::size_t nsubworld)
Definition macrotaskq.h:389
long get_scheduled_task_number_local()
Definition macrotaskq.h:521
Definition macrotaskq.h:718
taskT task
Definition macrotaskq.h:725
MacroTaskInternal(const taskT &task, const std::pair< Batch, double > &batch_prio, const recordlistT &inputrecords, const recordlistT &outputrecords)
Definition macrotaskq.h:731
std::enable_if< notis_tuple< resultT1 >::value, void >::type accumulate_into_final_result(World &subworld, resultT1 &result, const resultT1 &result_tmp, const argtupleT &argtuple)
accumulate the result of the task into the final result living in the universe
Definition macrotaskq.h:803
static ScalarResult< T > pointer2WorldObject(const std::shared_ptr< ScalarResultImpl< T > > sr_impl)
Definition macrotaskq.h:889
decay_tuple< typename taskT::argtupleT > argtupleT
Definition macrotaskq.h:720
static std::vector< Function< T, NDIM > > pointer2WorldObject(const std::vector< std::shared_ptr< FunctionImpl< T, NDIM > > > v_impl)
Definition macrotaskq.h:881
virtual void print_me_as_table(std::string s="") const
Definition macrotaskq.h:749
taskT::resultT resultT
Definition macrotaskq.h:721
void run(World &subworld, Cloud &cloud, MacroTaskBase::taskqT &taskq, const long element, const bool debug)
Definition macrotaskq.h:828
recordlistT outputrecords
Definition macrotaskq.h:723
std::string get_name() const
Definition macrotaskq.h:726
void binary_tuple_loop(tupleT &tuple1, tupleR &tuple2, opT &op) const
loop over the tuple elements of both tuples and execute the operation op on each element pair
Definition macrotaskq.h:769
resultT get_output(World &subworld, Cloud &cloud)
return the WorldObjects or the result functions living in the universe
Definition macrotaskq.h:906
static Function< T, NDIM > pointer2WorldObject(const std::shared_ptr< FunctionImpl< T, NDIM > > impl)
Definition macrotaskq.h:874
static std::vector< ScalarResult< T > > pointer2WorldObject(const std::vector< std::shared_ptr< ScalarResultImpl< T > > > v_sr_impl)
Definition macrotaskq.h:894
virtual void print_me(std::string s="") const
Definition macrotaskq.h:745
void unary_tuple_loop(tupleT &tuple, opT &op) const
Definition macrotaskq.h:779
std::enable_if< is_tuple< resultT1 >::value, void >::type accumulate_into_final_result(World &subworld, resultT1 &final_result, const resultT1 &tmp_result, const argtupleT &argtuple)
accumulate the result of the task into the final result living in the universe
Definition macrotaskq.h:790
recordlistT inputrecords
Definition macrotaskq.h:722
Definition macrotaskq.h:567
taskT::resultT resultT
Definition macrotaskq.h:577
std::shared_ptr< MacroTaskQ > taskq_ptr
Definition macrotaskq.h:666
taskT::argtupleT argtupleT
Definition macrotaskq.h:578
MacroTask(World &world, taskT &task, std::shared_ptr< MacroTaskQ > taskq_ptr=0)
constructor takes the actual task
Definition macrotaskq.h:611
World & world
Definition macrotaskq.h:665
resultT operator()(const Ts &... args)
this mimicks the original call to the task functor, called from the universe
Definition macrotaskq.h:630
bool debug
Definition macrotaskq.h:581
taskT task
Definition macrotaskq.h:580
MacroTaskPartitioner::partitionT partitionT
Definition macrotaskq.h:568
Cloud::recordlistT recordlistT
Definition macrotaskq.h:579
void set_debug(const bool value)
Definition macrotaskq.h:620
recordlistT prepare_output_records(Cloud &cloud, resultT &result)
store pointers to the result WorldObject in the cloud and return the recordlist
Definition macrotaskq.h:671
helper class for returning the result of a task, which is not a madness Function, but a simple scalar
Definition macrotaskq.h:55
void gaxpy(const double a, const T &right, double b, const bool fence=true)
accumulate, optional fence
Definition macrotaskq.h:86
void serialize(Archive &ar)
Definition macrotaskq.h:94
T get()
after completion of the taskq get the final value
Definition macrotaskq.h:99
ScalarResultImpl< T > & operator=(const T &x)
simple assignment of the scalar value
Definition macrotaskq.h:75
ScalarResultImpl(const ScalarResultImpl &other)=delete
Disable the default copy constructor.
ScalarResultImpl< T > & operator=(const ScalarResultImpl< T > &other)=delete
disable assignment operator
ScalarResultImpl< T > & operator+=(const T &x)
Definition macrotaskq.h:80
~ScalarResultImpl()
Definition macrotaskq.h:69
T value
the scalar value
Definition macrotaskq.h:112
T get_local() const
Definition macrotaskq.h:106
T value_type
Definition macrotaskq.h:57
ScalarResultImpl(World &world)
Definition macrotaskq.h:58
Definition macrotaskq.h:116
void serialize(Archive &ar)
Definition macrotaskq.h:147
ScalarResult(const std::shared_ptr< implT > &impl)
Definition macrotaskq.h:123
void gaxpy(const double a, const T &right, double b, const bool fence=true)
accumulate, optional fence
Definition macrotaskq.h:142
ScalarResultImpl< T > implT
Definition macrotaskq.h:118
T get()
after completion of the taskq get the final value
Definition macrotaskq.h:152
ScalarResult(World &world)
Definition macrotaskq.h:122
std::shared_ptr< implT > impl
Definition macrotaskq.h:119
ScalarResult & operator=(const T &x)
Definition macrotaskq.h:124
std::shared_ptr< implT > get_impl() const
Definition macrotaskq.h:129
void set_impl(const std::shared_ptr< implT > &newimpl)
Definition macrotaskq.h:133
T get_local() const
after completion of the taskq get the final value
Definition macrotaskq.h:157
uniqueidT id() const
Definition macrotaskq.h:137
void broadcast_serializable(objT &obj, ProcessID root)
Broadcast a serializable object.
Definition worldgop.h:754
void fence(bool debug=false)
Synchronizes all processes in communicator AND globally ensures no pending AM or tasks.
Definition worldgop.cc:161
bool set_forbid_fence(bool value)
Set forbid_fence flag to new value and return old value.
Definition worldgop.h:674
void sum(T *buf, size_t nelem)
Inplace global sum while still processing AM & tasks.
Definition worldgop.h:870
SafeMPI::Intracomm & comm()
Returns the associated SafeMPI communicator.
Definition worldmpi.h:286
Implements most parts of a globally addressable object (via unique ID).
Definition world_object.h:364
World & get_world() const
Returns a reference to the world.
Definition world_object.h:717
World & world
The World this object belongs to. (Think globally, act locally).
Definition world_object.h:381
void process_pending()
To be called from derived constructor to process pending messages.
Definition world_object.h:656
detail::task_result_type< memfnT >::futureT send(ProcessID dest, memfnT memfn) const
Definition world_object.h:731
detail::task_result_type< memfnT >::futureT task(ProcessID dest, memfnT memfn, const TaskAttributes &attr=TaskAttributes()) const
Sends task to derived class method returnT (this->*memfn)().
Definition world_object.h:1005
A parallel world class.
Definition world.h:132
static World * world_from_id(std::uint64_t id)
Convert a World ID to a World pointer.
Definition world.h:492
ProcessID rank() const
Returns the process rank in this World (same as MPI_Comm_rank()).
Definition world.h:320
WorldMpiInterface & mpi
MPI interface.
Definition world.h:204
ProcessID size() const
Returns the number of processes in this World (same as MPI_Comm_size()).
Definition world.h:330
unsigned long id() const
Definition world.h:315
WorldGopInterface & gop
Global operations.
Definition world.h:207
std::optional< T * > ptr_from_id(uniqueidT id) const
Look up a local pointer from a world-wide unique ID.
Definition world.h:416
Class for unique global IDs.
Definition uniqueid.h:53
Declares the Cloud class for storing data and transfering them between worlds.
char * p(char *buf, const char *name, int k, int initial_level, double thresh, int order)
Definition derivatives.cc:72
const std::size_t bufsize
Definition derivatives.cc:16
static bool debug
Definition dirac-hatom.cc:16
auto T(World &world, response_space &f) -> response_space
Definition global_functions.cc:34
static const double v
Definition hatom_sf_dirac.cc:20
Tensor< double > op(const Tensor< double > &x)
Definition kain.cc:508
#define MADNESS_CHECK(condition)
Check a condition — even in a release build the condition is always evaluated so it can have side eff...
Definition madness_exception.h:182
#define MADNESS_EXCEPTION(msg, value)
Macro for throwing a MADNESS exception.
Definition madness_exception.h:119
#define MADNESS_ASSERT(condition)
Assert a condition that should be free of side-effects since in release builds this might be a no-op.
Definition madness_exception.h:134
Namespace for all elements and tools of MADNESS.
Definition DFParameters.h:10
std::vector< ScalarResult< T > > scalar_result_vector(World &world, std::size_t n)
helper function to create a vector of ScalarResultImpl, circumventing problems with the constructors
Definition macrotaskq.h:165
static const char * filename
Definition legendre.cc:96
static double cpu_time()
Returns the cpu time in seconds relative to an arbitrary origin.
Definition timers.h:127
void set_impl(std::vector< Function< T, NDIM > > &v, const std::vector< std::shared_ptr< FunctionImpl< T, NDIM > > > vimpl)
Definition vmra.h:645
std::vector< std::shared_ptr< FunctionImpl< T, NDIM > > > get_impl(const std::vector< Function< T, NDIM > > &v)
Definition vmra.h:638
void compress(World &world, const std::vector< Function< T, NDIM > > &v, bool fence=true)
Compress a vector of functions.
Definition vmra.h:145
constexpr bool check_tuple_is_valid_task_result()
given a tuple check recursively if all elements are valid task results
Definition macrotaskq.h:224
static const Slice _(0,-1, 1)
void print(const T &t, const Ts &... ts)
Print items to std::cout (items separated by spaces) and terminate with a new line.
Definition print.h:225
constexpr bool is_valid_task_result_v
check if type is a valid task result: it must be a WorldObject and must implement gaxpy
Definition macrotaskq.h:210
decltype(decay_types(std::declval< T >())) decay_tuple
Definition macrotaskpartitioner.h:22
double wall_time()
Returns the wall time in seconds relative to an arbitrary origin.
Definition timers.cc:48
std::string type(const PairType &n)
Definition PNOParameters.h:18
std::string name(const FuncType &type, const int ex=-1)
Definition ccpairfunction.h:28
void gaxpy(const double a, ScalarResult< T > &left, const double b, const T &right, const bool fence=true)
the result type of a macrotask must implement gaxpy
Definition macrotaskq.h:246
Definition mraimpl.h:50
static const double b
Definition nonlinschro.cc:119
static const double a
Definition nonlinschro.cc:118
RAII class to redirect cout to a file.
Definition macrotaskq.h:584
io_redirect(const long task_number, std::string filename, bool debug=false)
Definition macrotaskq.h:589
std::streambuf * stream_buffer_cout
Definition macrotaskq.h:585
~io_redirect()
Definition macrotaskq.h:599
bool debug
Definition macrotaskq.h:587
std::ofstream ofile
Definition macrotaskq.h:586
Definition macrotaskq.h:571
Default load of an object via serialize(ar, t).
Definition archive.h:666
Default store of an object via serialize(ar, t).
Definition archive.h:611
Definition macrotaskpartitioner.h:25
Definition mra.h:2796
Definition macrotaskq.h:195
Definition macrotaskq.h:180
Definition macrotaskq.h:174
Definition macrotaskq.h:201
Definition macrotaskq.h:189
Definition macrotaskq.h:219
static void load(const Archive &ar, std::shared_ptr< ScalarResultImpl< T > > &ptr)
Definition macrotaskq.h:262
static void store(const Archive &ar, const std::shared_ptr< ScalarResultImpl< T > > &ptr)
Definition macrotaskq.h:252
static const double_complex I
Definition tdse1d.cc:164
void doit(World &world)
Definition tdse.cc:921
void e()
Definition test_sig.cc:75
Declares the World class for the parallel runtime environment.
int ProcessID
Used to clearly identify process number/rank.
Definition worldtypes.h:43