![]() |
Peano
|
Functions | |
void | spawnAndWaitAsTaskLoop (const std::vector< tarch::multicore::Task * > &tasks) |
Map onto native tasking. | |
void | processFusedTask (Task *myTask, const std::list< tarch::multicore::Task * > &tasksOfSameType, int device) |
Process a fused task. | |
void tarch::multicore::native::processFusedTask | ( | Task * | myTask, |
const std::list< tarch::multicore::Task * > & | tasksOfSameType, | ||
int | device ) |
Process a fused task.
Process a fused task (an assembly of multiple tasks of the same type)
A fused task is a task (which can be fused) and a list of further tasks which are of the same type and, hence, can be fused, too. The list can be empty. Efficient implementations should spawn the fused tasks as a further ready task and return immediately.
If no multithreading is enabled, then we map it onto a plain task via a spawnTask(). This spawn has no dependencies.
firstTask | First task. This is a task which can be fused. The pointer is valid. The ownership of firstTask is handed over to the called routine, i.e. processFusedTask() has to ensure that it is deleted. |
otherTasks | List of tasks of the same type. The list can be empty. processFusedTask() has to ensure that all tasks stored within the list are executed and subsequently destroyed. |
device | Target device on which the fused tasks should be executed. Can be host if the tasks should end up on the host. |
It is not clear what happens if I use tasksOfSameType directly within the task. It is clear that a pure reference cannot be used within a task, as the task uses firstprivate by default. Therefore, it would copy something which ceases to exist. It is not clear what happens with const references, but we had some memory issues with the newer Intel/LLVM versions. Therefore, I manually copy the list and pass this one into fuse(). The firstprivate annotation is not required, as this is the default. But I leave it in here to highlight that three variables are copied, but tasksOfSameType is not copied and not used within the task.
Definition at line 141 of file Tasks.cpp.
References tarch::multicore::Task::fuse(), and tarch::multicore::NoOutDependencies.
Referenced by tarch::multicore::taskfusion::ProcessReadyTask::run().
void tarch::multicore::native::spawnAndWaitAsTaskLoop | ( | const std::vector< tarch::multicore::Task * > & | tasks | ) |
Map onto native tasking.
Native mapping of a task loop onto a SYCL/oneTBB loop.
Run over the tasks and issue native tasks. If the tasks spawn, in return, further subtasks, these will either end up in a thread-local queue or will be mapped onto native tasks. The behaviour here depends on decisions within tarch::multicore::spawnTask() guided by the orchestration. If the subtasks enqueue tasks into the thread-local queue, they will remain there. This routine does not touch the thread-local queue.
The responsibility for the pointers in tasks is handed over to the runtime of choice, i.e. you don't have to delete them.
tasks | Set of tasks. Is guaranteed to be non-empty. |
In TBB, the convenient way to model fork-join parallelism is the creation of a task group. We can then assign all tasks to that task group and eventually wait for all of its tasks to terminate.
Each task within the task group (aka BSP thread - though these logical threads are internally mapped onto lightweight tasks) can spawn additional tasks. As part of the enclave concept, we don't have to wait for these children tasks at the end of the BSP section. Therefore, the BSP tasks enqueue their new children into a separate task group/arena (see spawnTask()) and `‘forget’' them.
I do not explicitly submit the new task group into a task arena, i.e. I use the task arena of the surrounding task. Peano uses nested parallelism. We therefore might submit spawnAndWaitAsTaskLoop() for different areas with different priorities.
This realisation remark clarifies that we do not consider task priorities here.
If we worked with a task arena explicitly, we would have to write
Definition at line 111 of file Tasks.cpp.
References assertion, tarch::multicore::Core::getInstance(), and tarch::multicore::Core::yield().