Peano
Loading...
Searching...
No Matches
multicore.cpp
Go to the documentation of this file.
1// This file is part of the Peano project. For conditions of distribution and
2// use, please see the copyright notice at www.peano-framework.org
3#include "multicore.h"
4#include "tarch/Assertions.h"
5#include "tarch/mpi/Rank.h"
7
8#ifdef UseSmartMPI
9#include "smartmpi.h"
10#include "topology/topologies.h"
11#endif
12
19
21
22
23namespace {
25
26 tarch::logging::Log _log("tarch::multicore");
27
28 const std::string BSPConcurrencyLevelStatisticsIdentifier("tarch::multicore::bsp-concurrency-level");
29 const std::string SpawnedTasksStatisticsIdentifier("tarch::multicore::spawned-tasks");
30}
31
32
34 #ifdef UseSmartMPI
35 using namespace smartmpi::topology;
36 typedef UseSmartMPI MyTopology;
37 smartmpi::topology::Topology* smartMPITopology = new MyTopology(
38 tarch::mpi::Rank::getInstance().getCommunicator()
39 );
40 smartmpi::init( smartMPITopology );
41
42 smartmpi::appendToSchedulerChain( "HardcodedMigrationScheduler" );
43
44 tarch::mpi::Rank::getInstance().setCommunicator( smartMPITopology->computeNodeOrSmartServerCommunicator );
45 #endif
46}
47
48
50 #ifdef UseSmartMPI
51 smartmpi::shutdown();
52 #endif
53}
54
55
57 assertion(orchestrationStrategy != nullptr);
58 assertion(realisation != nullptr);
59
60 delete orchestrationStrategy;
61 orchestrationStrategy = realisation;
62}
63
64
66 assertion(orchestrationStrategy != nullptr);
67 assertion(realisation != nullptr);
68
69 tarch::multicore::orchestration::Strategy* result = orchestrationStrategy;
70 orchestrationStrategy = realisation;
71 return result;
72}
73
74
78
79
80void tarch::multicore::waitForTasks(const std::set<TaskNumber>& inDependencies) {
81 tarch::multicore::native::waitForTasks(inDependencies);
82}
83
84
85void tarch::multicore::waitForTask(const int taskNumber) {
86 std::set<int> tmp{taskNumber};
87 waitForTasks(tmp);
88}
89
90
91void tarch::multicore::spawnAndWait(const std::vector<Task*>& tasks) {
92 static tarch::logging::Log _log("tarch::multicore");
93
94 if (not tasks.empty()) {
95 static int nestedSpawnAndWaits = 0;
96 static tarch::multicore::BooleanSemaphore nestingSemaphore;
97
98 tarch::multicore::Lock nestingLock(nestingSemaphore, false);
99 nestingLock.lock();
100 nestedSpawnAndWaits++;
101 const int localNestedSpawnAndWaits = nestedSpawnAndWaits;
102 nestingLock.free();
103
104 orchestrationStrategy->startBSPSection(localNestedSpawnAndWaits);
105
106 switch (orchestrationStrategy->paralleliseForkJoinSection(localNestedSpawnAndWaits, tasks.size(), tasks[0]->getTaskType())) {
108 for (auto& p : tasks) {
109 while (p->run()) {
110 Core::getInstance().yield();
111 }
112 delete p;
113 }
114 break;
116 ::tarch::logging::Statistics::getInstance().inc(BSPConcurrencyLevelStatisticsIdentifier, static_cast<int>(tasks.size()), true);
117 native::spawnAndWaitAsTaskLoop(tasks);
118 ::tarch::logging::Statistics::getInstance().inc(BSPConcurrencyLevelStatisticsIdentifier, -static_cast<int>(tasks.size()), true);
119 break;
120 }
121
122 orchestrationStrategy->endBSPSection(localNestedSpawnAndWaits);
123
124 nestingLock.lock();
125 nestedSpawnAndWaits--;
126 nestingLock.free();
127 }
128}
129
130
132 native::waitForAllTasks();
133}
134
135
137 Task* task,
138 const std::set<TaskNumber>& inDependencies,
139 const TaskNumber& taskNumber
140) {
141 assertion(task != nullptr);
142
143 tarch::logging::Statistics::getInstance().inc(SpawnedTasksStatisticsIdentifier, 1, false, true);
144
145 if (task->canFuse()) {
146 taskfusion::translateFusableTaskIntoTaskSequence(task, inDependencies, taskNumber);
147 } else {
148 native::spawnTask(task, inDependencies, taskNumber);
149 }
150}
151
152
153#ifndef SharedMemoryParallelisation
154
155void tarch::multicore::native::spawnAndWaitAsTaskLoop(const std::vector<Task*>& tasks) {
156 for (auto& p : tasks) {
157 while (p->run()) {
158 }
159 delete p;
160 }
161}
162
163
164void tarch::multicore::native::processFusedTask(Task* myTask, const std::list<tarch::multicore::Task*>& tasksOfSameType, int device) {
165 bool stillExecuteLocally = myTask->fuse(tasksOfSameType, device);
166 if (stillExecuteLocally) {
167 tarch::multicore::native::spawnTask(myTask, std::set<TaskNumber>(), NoOutDependencies);
168 } else {
169 delete myTask;
170 }
171}
172
173
174void tarch::multicore::native::spawnTask(
175 Task* job,
176 const std::set<TaskNumber>& /*inDependencies*/,
177 const TaskNumber& /*taskNumber*/
178) {
179 while (job->run()) {
180 }
181 delete job;
182}
183
184
185void tarch::multicore::native::waitForTasks(const std::set<TaskNumber>& /*inDependencies*/) {}
186
187
188void tarch::multicore::native::waitForAllTasks() {}
189
190#endif
#define assertion(expr)
tarch::logging::Log _log("::")
Log Device.
Definition Log.h:516
void inc(const std::string &identifier, double value=1.0, bool disableSampling=false, bool clearAfterDatabaseDump=false)
Definition Statistics.h:107
static Statistics & getInstance()
This is not the canonical realisation of singletons as I use it usually for stats in Peano.
void setCommunicator(MPI_Comm communicator, bool recomputeRankAndWorld=true)
Set communicator to be used by Peano.
Definition Rank.cpp:580
static Rank & getInstance()
This operation returns the singleton instance.
Definition Rank.cpp:543
Create a lock around a boolean semaphore region.
Definition Lock.h:19
void free()
Free the lock.
Definition Lock.cpp:37
Abstract super class for a job.
Definition Task.h:21
virtual bool canFuse() const
Definition Task.cpp:31
Interface for any task orchestration.
Definition Strategy.h:25
void spawnAndWaitAsTaskLoop(const std::vector< tarch::multicore::Task * > &tasks)
Map onto native tasking.
Definition Tasks.cpp:143
void processFusedTask(Task *myTask, const std::list< tarch::multicore::Task * > &tasksOfSameType, int device)
Process a fused task.
Definition Tasks.cpp:219
void shutdownSmartMPI()
Definition multicore.cpp:49
tarch::multicore::orchestration::Strategy & getOrchestration()
Definition multicore.cpp:75
void waitForTask(const int taskNumber)
Wrapper around waitForTasks() with a single-element set.
Definition multicore.cpp:85
void waitForTasks(const std::set< TaskNumber > &inDependencies)
Wait for set of tasks.
Definition multicore.cpp:80
void setOrchestration(tarch::multicore::orchestration::Strategy *realisation)
Definition multicore.cpp:56
void spawnAndWait(const std::vector< Task * > &tasks)
Fork-join task submission pattern.
Definition multicore.cpp:91
tarch::multicore::orchestration::Strategy * swapOrchestration(tarch::multicore::orchestration::Strategy *realisation)
Swap the active orchestration.
Definition multicore.cpp:65
void spawnTask(Task *task, const std::set< TaskNumber > &inDependencies=tarch::multicore::NoInDependencies, const TaskNumber &taskNumber=tarch::multicore::NoOutDependencies)
Spawns a single task in a non-blocking fashion.
void initSmartMPI()
Switch on SmartMPI.
Definition multicore.cpp:33