Peano
Loading...
Searching...
No Matches
tarch::multicore::Task Class Referenceabstract

Abstract super class for a job. More...

#include <Task.h>

Inheritance diagram for tarch::multicore::Task:

Public Member Functions

 Task (int taskType, int priority)
 Construct task.
virtual ~Task ()
int getTaskType () const
int getPriority () const
void setPriority (int priority)
 Set priority.
virtual bool canFuse () const
virtual void run ()=0
 Run the task.
virtual void fuse (const std::vector< Task * > &otherTasks, int targetDevice=Host)
 Fuse multiple tasks.
virtual std::string toString () const

Static Public Attributes

static constexpr int DefaultPriority = 1024
static constexpr int Host = -1
static constexpr int DontFuse = -1

Protected Attributes

const int _taskType
int _priority

Detailed Description

Abstract super class for a job.

Definition at line 21 of file Task.h.

Constructor & Destructor Documentation

◆ Task()

tarch::multicore::Task::Task ( int taskType,
int priority )

Construct task.

Task types

Each task in Peano has to have a task type. All tasks that do the same, i.e. are of the same type, should have the same task type integer marker. Peano's tarch can use multiple tasks of the same type and fuse/batch them into one task call. However, if you don't want Peano to even thing about task fusion, pass in DontFuse as argument for the type. In this case, the tasking subsystem becomes agnostic of the type.

In principle, it is totally up to the user to manage the task type numbers. However, they have to be unique. This quickly becomes challenging - notably if you combine multiple solvers. Therefore, Peano offers a factory mechanism peano4::parallel::getTaskType() to create task types, which Peano applications should use.

If you have a proper task class, I recommend that you introduce a static field for this class and you initialise it with the outcome of peano4::parallel::getTaskType(). If there's one dedicated code line in your code which produces exclusively all the tasks of one type, you can also do

static int taskType = peano4::parallel::getTaskType("MyFancyClassName");
...
int getTaskType(const std::string &className)
Get unique number (id) for task.
Definition parallel.cpp:13

Task numbers

Some codes also have task numbers. They need this, if they have to identify unique tasks among a set of tasks of the same type. Applications for that are task that are offloaded to other ranks. For the latter tasks, we have to match data sent back by another rank to the task that would have produced these results locally. Anyway, task numbers are not baked into the generic interface, as we don't need them for all tasks all the time, and I want to avoid that the construction of unique task numbers becomes too expensive.

Some extensions that work with task numbers provide factory methods for these, which is kind of good practice. ExaHyPE for example offers exahype2::EnclaveTask::reserveTaskNumber() which ensures that task numbers are unique among multiple threads and also recycled, such that they do not overflow.

See also
The overview page Multicore programming discusses different task types and how they are mapped onto realisations.
Parameters
taskTypeUnique task (type) number for this task. Pass in DontFuse if you don't want this task to be fused.
priorityInteger value that indicates what priority you want to assign a task. Value has to be non-negative. Use DefaultPriority if there is no bespoke priority.

Definition at line 25 of file Task.cpp.

References _priority, _taskType, and assertion2.

Referenced by tarch::multicore::EmptyTask::EmptyTask(), exahype2::EnclaveTask::EnclaveTask(), tarch::multicore::taskfusion::LogReadyTask::LogReadyTask(), tarch::multicore::taskfusion::ProcessOneReadyTask::ProcessOneReadyTask(), tarch::multicore::taskfusion::ProcessSetOfReadyTasks::ProcessSetOfReadyTasks(), tarch::multicore::taskfusion::ProcessOneReadyTask::run(), tarch::multicore::TaskWithCopyOfFunctor::TaskWithCopyOfFunctor(), tarch::multicore::TaskWithoutCopyOfFunctor::TaskWithoutCopyOfFunctor(), and peano4::parallel::SpacetreeSet::TraverseTask::TraverseTask().

Here is the caller graph for this function:

◆ ~Task()

virtual tarch::multicore::Task::~Task ( )
virtual

Definition at line 92 of file Task.h.

Member Function Documentation

◆ canFuse()

bool tarch::multicore::Task::canFuse ( ) const
virtual
Returns
true if the taskType is not DontFuse.

Definition at line 31 of file Task.cpp.

References _taskType, and DontFuse.

Referenced by fuse(), and tarch::multicore::spawnTask().

Here is the caller graph for this function:

◆ fuse()

void tarch::multicore::Task::fuse ( const std::vector< Task * > & otherTasks,
int targetDevice = Host )
virtual

Fuse multiple tasks.

Fuse the task with a list of further tasks. The routine is guaranteed to be called only for tasks with the same taskType. As long as you take care that every task type has a unique number, you can downcast all the objects within otherTasks into the type this virtual function is called for.

This operation is invoked on a task. However, it is also given N=otherTasks.size further tasks of the same type. In the routine, you have to process the N+1 tasks in one rush, i.e. all tasks from otherTasks and the task represented by the actual object on which fuse is called. In this case, you return false, as the task on which fuse has been called can be destroyed by the runtime.

Default implementation

My default implementation executes all the passed tasks one by one.

Memory ownership

fuse() has to complete all the instances within otherTasks, but it does not have to delete anything. This is done outside, i.e. the calling routine will delete otherTasks' instances as well as the one it has called fuse() for.

Parameters
otherTasksList of tasks to fuse and process. Will all have the same type as the present object. It is the tasks responsibility to get these tasks done.
targetDeviceOn which device should the task be processed? A negative number means local host anything greater or equal to zero denotes an accelerator.

Definition at line 42 of file Task.cpp.

References assertion, canFuse(), and run().

Referenced by tarch::multicore::processFusedTask().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ getPriority()

int tarch::multicore::Task::getPriority ( ) const

◆ getTaskType()

int tarch::multicore::Task::getTaskType ( ) const

Definition at line 40 of file Task.cpp.

References _taskType.

Referenced by tarch::multicore::taskfusion::handleFusableTask().

Here is the caller graph for this function:

◆ run()

◆ setPriority()

void tarch::multicore::Task::setPriority ( int priority)

Set priority.

Parameters
priorityHas to be non-negative

Definition at line 35 of file Task.cpp.

References _priority, _taskType, and assertion3.

Referenced by tarch::multicore::taskfusion::handleFusableTask_LazyEvaluation(), and tarch::multicore::taskfusion::handleFusableTask_ProducerConsumerTaskSequence().

Here is the caller graph for this function:

◆ toString()

std::string tarch::multicore::Task::toString ( ) const
virtual

Reimplemented in tarch::multicore::EmptyTask, and tarch::multicore::TaskWithCopyOfFunctor.

Definition at line 51 of file Task.cpp.

Referenced by exahype2::EnclaveTask::EnclaveTask().

Here is the caller graph for this function:

Field Documentation

◆ _priority

int tarch::multicore::Task::_priority
protected

Definition at line 24 of file Task.h.

Referenced by getPriority(), setPriority(), and Task().

◆ _taskType

const int tarch::multicore::Task::_taskType
protected

Definition at line 23 of file Task.h.

Referenced by canFuse(), getTaskType(), setPriority(), and Task().

◆ DefaultPriority

◆ DontFuse

◆ Host


The documentation for this class was generated from the following files: