Peano
Loading...
Searching...
No Matches
EnclaveTasking.EnclaveTask.template.cpp
Go to the documentation of this file.
1// This file is part of the ExaHyPE2 project. For conditions of distribution and
2// use, please see the copyright notice at www.peano-framework.org
3#include "{{CLASSNAME}}.h"
4
5{{SOLVER_INCLUDES}}
6
7#include "config.h"
8
9#include "exahype2/CellData.h"
12
14
16
17#include "peano4/utils/Loop.h"
18
20
23
26
28
29#if defined(UseSmartMPI)
30#include "communication/Tags.h"
31#endif
32
33#include <string.h>
34#include <memory>
35
36tarch::logging::Log {{NAMESPACE | join("::")}}::{{CLASSNAME}}::_log( "{{NAMESPACE | join("::")}}::{{CLASSNAME}}" );
37int {{NAMESPACE | join("::")}}::{{CLASSNAME}}::_enclaveTaskTypeId(peano4::parallel::getTaskType("{{NAMESPACE | join("::")}}::{{CLASSNAME}}"));
38
39int {{NAMESPACE | join("::")}}::{{CLASSNAME}}::getEnclaveTaskTypeId() {
40 return _enclaveTaskTypeId;
41}
42
43double {{NAMESPACE | join("::")}}::{{CLASSNAME}}::applyKernelToCell(
44 const ::peano4::datamanagement::CellMarker& marker,
45 double t,
46 double dt,
47 double* __restrict__ reconstructedPatch,
48 double* __restrict__ targetPatch
49) {
50 ::exahype2::CellData patchData(reconstructedPatch, marker.x(), marker.h(), t, dt, targetPatch);
51
52 {% if STATELESS_PDE_TERMS %}
53 if (repositories::{{SOLVER_INSTANCE}}.patchCanUseStatelessPDETerms(
54 marker.x(),
55 marker.h(),
56 t,
57 dt
58 )) {
59 ::exahype2::fv::{{KERNEL_NAMESPACE}}::{{COMPUTE_KERNEL_CALL_STATELESS}}
60 } else
61 {% endif %}
62
63 ::exahype2::fv::{{KERNEL_NAMESPACE}}::{{COMPUTE_KERNEL_CALL}}
64
66 targetPatch,
67 {{NUMBER_OF_UNKNOWNS}},
68 {{NUMBER_OF_AUXILIARY_VARIABLES}},
69 {{NUMBER_OF_VOLUMES_PER_AXIS}},
70 0, // halo
71 std::string(__FILE__) + "(" + std::to_string(__LINE__) + "): " + marker.toString()
72 ); // outcome has to be valid
73
75
76 {% if COMPUTE_MAX_EIGENVALUE %}
77 return patchData.maxEigenvalue[0];
78 {% else %}
79 return 0.0;
80 {% endif %}
81}
82
83{{NAMESPACE | join("::")}}::{{CLASSNAME}}::{{CLASSNAME}}(
84 const ::peano4::datamanagement::CellMarker& marker,
85 double t,
86 double dt,
87 double* __restrict__ reconstructedPatch,
88 double* __restrict__ output
89):
90 ::exahype2::EnclaveTask(
91 _enclaveTaskTypeId,
92 marker,
93 t,
94 dt,
95 reconstructedPatch,
96 output,
97 #if Dimensions==2
98 {{NUMBER_OF_DOUBLE_VALUES_IN_PATCH_PLUS_HALO_2D}},
99 {{NUMBER_OF_DOUBLE_VALUES_IN_PATCH_2D}},
100 #else
101 {{NUMBER_OF_DOUBLE_VALUES_IN_PATCH_PLUS_HALO_3D}},
102 {{NUMBER_OF_DOUBLE_VALUES_IN_PATCH_3D}},
103 #endif
104 [&]() -> void {
105 _maxEigenvalue = applyKernelToCell(
106 _marker,
107 _t,
108 _dt,
109 _inputValues,
110 _outputValues
111 );
112 }
113 )
114 #ifdef UseSmartMPI
115 , smartmpi::Task(_enclaveTaskTypeId)
116 #endif
117{
118 setPriority({{ENCLAVE_TASK_PRIORITY}});
119}
120
121
122#ifdef UseSmartMPI
123bool {{NAMESPACE | join("::")}}::{{CLASSNAME}}::isSmartMPITask() const {
124 #ifdef UseSmartMPI
125 return true;
126 #else
127 return false;
128 #endif
129}
130
131
132void {{NAMESPACE | join("::")}}::{{CLASSNAME}}::runLocally() {
133 computeTask();
134 if (_remoteTaskId != -1) {
135 ::exahype2::EnclaveBookkeeping::getInstance().finishedTask(_remoteTaskId,_numberOfResultValues,_outputValues,_maxEigenvalue);
136 } else {
137 ::exahype2::EnclaveBookkeeping::getInstance().finishedTask(getTaskId(),_numberOfResultValues,_outputValues,_maxEigenvalue);
138 }
139}
140
141void {{NAMESPACE | join("::")}}::{{CLASSNAME}}::moveTask(int rank, int tag, MPI_Comm communicator) {
142 ::tarch::mpi::DoubleMessage tMessage(_t);
143 ::tarch::mpi::DoubleMessage dtMessage(_dt);
144 ::tarch::mpi::IntegerMessage taskIdMessage;
145
146 if ( tag != smartmpi::communication::MoveTaskToMyServerForEvaluationTag &&
147 tag != smartmpi::communication::MoveTaskToComputesComputeRankTag ) {
148 taskIdMessage.setValue(_remoteTaskId);
149 } else {
150 taskIdMessage.setValue(getTaskId());
151 }
152
153 ::peano4::datamanagement::CellMarker::send( _marker, rank, tag, communicator );
154 ::tarch::mpi::DoubleMessage::send( tMessage, rank, tag, communicator );
155 ::tarch::mpi::DoubleMessage::send( dtMessage, rank, tag, communicator );
156 ::tarch::mpi::IntegerMessage::send( taskIdMessage, rank, tag, communicator );
157
158 MPI_Request request;
159 MPI_Isend( _inputValues, _numberOfInputValues, MPI_DOUBLE, rank, tag, communicator, &request );
160
161 logInfo(
162 "moveTask(...)",
163 "sent (" << _marker.toString() << "," << tMessage.toString() << "," << dtMessage.toString() << "," << _numberOfInputValues <<
164 "," << taskIdMessage.toString() << ") to rank " << rank <<
165 " via tag " << tag
166 );
167}
168
169smartmpi::Task* {{NAMESPACE | join("::")}}::{{CLASSNAME}}::receiveTask(int rank, int tag, MPI_Comm communicator) {
171 const int NumberOfInputValues =
172 #if Dimensions==2
173 {{NUMBER_OF_DOUBLE_VALUES_IN_PATCH_PLUS_HALO_2D}};
174 #else
175 {{NUMBER_OF_DOUBLE_VALUES_IN_PATCH_PLUS_HALO_3D}};
176 #endif
177
180 ::tarch::mpi::IntegerMessage taskIdMessage;
181 ::peano4::datamanagement::CellMarker markerMessage(dummyEvent);
183
184 ::peano4::datamanagement::CellMarker::receive( markerMessage, rank, tag, communicator );
185 ::tarch::mpi::DoubleMessage::receive( tMessage, rank, tag, communicator );
186 ::tarch::mpi::DoubleMessage::receive( dtMessage, rank, tag, communicator );
187 ::tarch::mpi::IntegerMessage::receive( taskIdMessage, rank, tag, communicator );
188
189 logInfo(
190 "receiveTask(...)",
191 "received (" << markerMessage.toString() << "," << tMessage.toString() << "," << dtMessage.toString() << "," << taskIdMessage.toString() << ") from rank " << rank <<
192 " via tag " << tag << " and will now receive " << NumberOfInputValues << " doubles"
193 );
194
195 MPI_Recv( inputValues, NumberOfInputValues, MPI_DOUBLE, rank, tag, communicator,
196 MPI_STATUS_IGNORE
197 );
198
199 {{CLASSNAME}}* result = new {{CLASSNAME}}(
200 markerMessage,
201 tMessage.getValue(),
202 dtMessage.getValue(),
203 inputValues
204 );
205 result->_remoteTaskId = taskIdMessage.getValue();
206 return result;
207}
208
209void {{NAMESPACE | join("::")}}::{{CLASSNAME}}::runLocallyAndSendTaskOutputToRank(int rank, int tag, MPI_Comm communicator) {
211
212// _functor(_inputValues,_outputValues,_marker,_t,_dt,_maxEigenvalue);
213// tarch::freeMemory(_inputValues,tarch::MemoryLocation::ManagedSharedAcceleratorDeviceMemory );
214 _functor();
215
216 logInfo(
217 "runLocallyAndSendTaskOutputToRank(...)",
218 "executed remote task on this rank. Will start to send result back"
219 );
220
221 forwardTaskOutputToRank(rank, tag, communicator);
222}
223
224void {{NAMESPACE | join("::")}}::{{CLASSNAME}}::forwardTaskOutputToRank(int rank, int tag, MPI_Comm communicator) {
225 logInfo(
226 "forwardTaskOutputToRank(...)",
227 "will start to forward task output (which has already been computed)"
228 );
229
230 ::tarch::mpi::DoubleMessage tMessage(_t);
231 ::tarch::mpi::DoubleMessage dtMessage(_dt);
232 ::tarch::mpi::DoubleMessage eValueMessage(_maxEigenvalue);
233 ::tarch::mpi::IntegerMessage taskIdMessage(_remoteTaskId);
234
235 ::peano4::datamanagement::CellMarker::send( _marker, rank, tag, communicator );
236 ::tarch::mpi::DoubleMessage::send( tMessage, rank, tag, communicator );
237 ::tarch::mpi::DoubleMessage::send( dtMessage, rank, tag, communicator );
238 ::tarch::mpi::DoubleMessage::send( eValueMessage, rank, tag, communicator );
239 ::tarch::mpi::IntegerMessage::send( taskIdMessage, rank, tag, communicator );
240
241 MPI_Request request;
242 MPI_Isend( _outputValues, _numberOfResultValues, MPI_DOUBLE, rank, tag, communicator, &request );
243
244 logInfo(
245 "forwardTaskOutputToRank(...)",
246 "sent (" << _marker.toString() << "," << tMessage.toString() << "," << dtMessage.toString() << "," << _numberOfResultValues <<
247 "," << taskIdMessage.toString() << ") to rank " << rank <<
248 " via tag " << tag
249 );
250
251 // tarch::freeMemory(_outputValues,tarch::MemoryLocation::ManagedSharedAcceleratorDeviceMemory );
252}
253
254smartmpi::Task* {{NAMESPACE | join("::")}}::{{CLASSNAME}}::receiveOutcome(int rank, int tag, MPI_Comm communicator, const bool intentionToForward) {
255 logInfo( "receiveOutcome(...)", "rank=" << rank << ", tag=" << tag );
257 const int NumberOfResultValues =
258 #if Dimensions==2
259 {{NUMBER_OF_DOUBLE_VALUES_IN_PATCH_2D}};
260 #else
261 {{NUMBER_OF_DOUBLE_VALUES_IN_PATCH_3D}};
262 #endif
263
266 ::tarch::mpi::DoubleMessage eValueMessage;
267 ::tarch::mpi::IntegerMessage taskIdMessage;
268 ::peano4::datamanagement::CellMarker markerMessage(dummyEvent);
269 double* outputValues = tarch::allocateMemory( NumberOfResultValues, tarch::MemoryLocation::ManagedSharedAcceleratorDeviceMemory );
270
271 ::peano4::datamanagement::CellMarker::receive( markerMessage, rank, tag, communicator );
272 ::tarch::mpi::DoubleMessage::receive( tMessage, rank, tag, communicator );
273 ::tarch::mpi::DoubleMessage::receive( dtMessage, rank, tag, communicator );
274 ::tarch::mpi::DoubleMessage::receive( eValueMessage, rank, tag, communicator );
275 ::tarch::mpi::IntegerMessage::receive( taskIdMessage, rank, tag, communicator );
276
277 logInfo(
278 "receiveOutcome(...)",
279 "received (" << markerMessage.toString() << "," << tMessage.toString() << "," << dtMessage.toString() << "," << taskIdMessage.toString() << ") from rank " << rank <<
280 " via tag " << tag << " and will now receive " << NumberOfResultValues << " doubles"
281 );
282
283 MPI_Recv( outputValues, NumberOfResultValues, MPI_DOUBLE, rank, tag, communicator,
284 MPI_STATUS_IGNORE
285 );
286
293 if(intentionToForward) {
294 double* inputValues = nullptr; // no input as already computed
295
296 {{CLASSNAME}}* result = new {{CLASSNAME}}(
297 markerMessage,
298 tMessage.getValue(),
299 dtMessage.getValue(),
300 inputValues
301 );
302 result->_remoteTaskId = taskIdMessage.getValue();
303 result->_outputValues = outputValues;
304 result->_maxEigenvalue = eValueMessage.getValue();
305 return result;
306 }
307 logInfo(
308 "receiveOutcome(...)",
309 "bookmark outcome of task " << taskIdMessage.getValue()
310 );
311 ::exahype2::EnclaveBookkeeping::getInstance().finishedTask(taskIdMessage.getValue(),NumberOfResultValues,outputValues,eValueMessage.getValue());
312 return nullptr;
313}
314#endif
315
316
317{% if STATELESS_PDE_TERMS %}
318
319bool {{NAMESPACE | join("::")}}::{{CLASSNAME}}::canFuse() const {
320 return repositories::{{SOLVER_INSTANCE}}.patchCanUseStatelessPDETerms(
321 _marker.x(),
322 _marker.h(),
323 _t,
324 _dt
325 );
326}
327
328
332bool {{NAMESPACE | join("::")}}::{{CLASSNAME}}::fuse(const std::list<Task*>& otherTasks, int targetDevice) {
333 logDebug("fuse(...)", "rank " << tarch::mpi::Rank::getInstance().getRank()
334 << " asked to fuse " << (otherTasks.size() + 1) << " tasks into one large GPU task on device " << targetDevice);
335
336 ::exahype2::CellData patchData(otherTasks.size() + 1, tarch::MemoryLocation::ManagedSharedAcceleratorDeviceMemory, targetDevice);
337 int currentTask = 0;
338 for (auto& p: otherTasks) {
339 patchData.QIn[currentTask] = static_cast<{{NAMESPACE | join("::")}}::{{CLASSNAME}}*>(p)->_inputValues;
340 patchData.cellCentre[currentTask] = static_cast<{{NAMESPACE | join("::")}}::{{CLASSNAME}}*>(p)->_marker.x();
341 patchData.cellSize[currentTask] = static_cast<{{NAMESPACE | join("::")}}::{{CLASSNAME}}*>(p)->_marker.h();
342 patchData.t[currentTask] = static_cast<{{NAMESPACE | join("::")}}::{{CLASSNAME}}*>(p)->_t;
343 patchData.dt[currentTask] = static_cast<{{NAMESPACE | join("::")}}::{{CLASSNAME}}*>(p)->_dt;
344 patchData.id[currentTask] = static_cast<{{NAMESPACE | join("::")}}::{{CLASSNAME}}*>(p)->_taskNumber;
345 patchData.QOut[currentTask] = tarch::allocateMemory<double>(_numberOfResultValues, tarch::MemoryLocation::ManagedSharedAcceleratorDeviceMemory, targetDevice);
346 delete p;
347 currentTask++;
348 }
349 patchData.QIn[currentTask] = _inputValues;
350 patchData.cellCentre[currentTask] = _marker.x();
351 patchData.cellSize[currentTask] = _marker.h();
352 patchData.t[currentTask] = _t;
353 patchData.dt[currentTask] = _dt;
354 patchData.id[currentTask] = _taskNumber;
355 patchData.QOut[currentTask] = tarch::allocateMemory<double>(_numberOfResultValues, tarch::MemoryLocation::ManagedSharedAcceleratorDeviceMemory, targetDevice);
356
357 //
358 // =========================
359 // Invoke stateless kernels
360 // =========================
361 //
362 bool foundOffloadingBranch = false;
363
364#if defined(GPUOffloadingOMP)
365 if (targetDevice >= 0) {
366 foundOffloadingBranch = true;
367 ::exahype2::fv::{{KERNEL_NAMESPACE}}::omp::{{FUSED_COMPUTE_KERNEL_CALL_STATELESS_GPU}}
368 }
369#endif
370
371#if defined(GPUOffloadingHIP)
372 if (targetDevice >= 0) {
373 foundOffloadingBranch = true;
374 ::exahype2::fv::{{KERNEL_NAMESPACE}}::hip::{{FUSED_COMPUTE_KERNEL_CALL_STATELESS_GPU}}
375 }
376#endif
377
378#if defined(GPUOffloadingSYCL)
379 if (targetDevice >= 0 or targetDevice == Host) {
380 foundOffloadingBranch = true;
381 ::exahype2::fv::{{KERNEL_NAMESPACE}}::sycl::{{FUSED_COMPUTE_KERNEL_CALL_STATELESS_GPU}}
382 }
383#endif
384
385#if defined(GPUOffloadingCPP)
386 if (targetDevice >= 0 or targetDevice == Host) {
387 foundOffloadingBranch = true;
388 ::exahype2::fv::{{KERNEL_NAMESPACE}}::cpp::{{FUSED_COMPUTE_KERNEL_CALL_STATELESS_GPU}}
389 }
390#endif
391
392 if (not foundOffloadingBranch) {
393 logDebug("fuse(...)", "rank " << tarch::mpi::Rank::getInstance().getRank()
394 << " cannot find offloading branch for device " << targetDevice << ". Process fused tasks on the CPU.");
395 ::exahype2::fv::{{KERNEL_NAMESPACE}}::{{FUSED_COMPUTE_KERNEL_CALL_STATELESS_CPU}}
396 }
397
398 //
399 // ==================
400 // Bring back results
401 // ==================
402 //
403 for (int i = 0; i < patchData.numberOfCells; i++) {
404 // Delete reconstructed data which has been allocated before spawning the tasks.
406 ::exahype2::EnclaveBookkeeping::getInstance().finishedTask(patchData.id[i], _numberOfResultValues, patchData.QOut[i], patchData.maxEigenvalue[i]);
407 }
408
409 // Don't rerun, so return false.
410 return false;
411}
412
413{% endif %}
#define logDebug(methodName, logMacroMessageStream)
Definition Log.h:50
#define logInfo(methodName, logMacroMessageStream)
Wrapper macro around tarch::tarch::logging::Log to improve logging.
Definition Log.h:411
static EnclaveBookkeeping & getInstance()
void finishedTask(int taskNumber, int numberOfResultValues, double *data, double maxEigenvalue)
Usually called directly by EnclaveTask.
Log Device.
Definition Log.h:516
static Rank & getInstance()
This operation returns the singleton instance.
Definition Rank.cpp:539
tarch::logging::Log _log("exahype2::fv")
float dt
Definition DSL_test.py:5
void validatePatch(const double *__restrict__ Q, int unknowns, int auxiliaryVariables, int numberOfVolumesPerAxisInPatch, int haloSize, const std::string &location="", bool triggerNonCriticalAssertion=true, double *minValues=nullptr, double *maxValues=nullptr)
Just runs over the patch and ensures that no entry is non or infinite.
For the generic kernels that I use here most of the time.
Definition CellAccess.h:13
int getTaskType(const std::string &className)
Get unique number (id) for task.
Definition parallel.cpp:7
void freeMemory(void *data, MemoryLocation location, int device=accelerator::Device::HostDevice)
Free memory.
@ ManagedSharedAcceleratorDeviceMemory
To be used on host only.
T * allocateMemory(std::size_t count, MemoryLocation location, int device=accelerator::Device::HostDevice)
Allocates memory on the specified memory location.
Definition accelerator.h:99
Representation of a number of cells which contains all information that's required to process the sto...
Definition CellData.h:77
static void receive(CellMarker &buffer, int source, int tag, MPI_Comm communicator)
static void send(const CellMarker &buffer, int destination, int tag, MPI_Comm communicator)
In DaStGen (the first version), I had a non-static version of the send as well as the receive.
std::string toString() const
static void receive(tarch::mpi::DoubleMessage &buffer, int source, int tag, MPI_Comm communicator)
static void send(const tarch::mpi::DoubleMessage &buffer, int destination, int tag, MPI_Comm communicator)
In DaStGen (the first version), I had a non-static version of the send as well as the receive.
std::string toString() const
static void receive(tarch::mpi::IntegerMessage &buffer, int source, int tag, MPI_Comm communicator)
static void send(const tarch::mpi::IntegerMessage &buffer, int destination, int tag, MPI_Comm communicator)
In DaStGen (the first version), I had a non-static version of the send as well as the receive.