Unit content
Task parallelism and fork-join execution
Task parallelism expresses a computation as units of work that may execute independently when their dependencies allow it.
A common model is fork-join. A running task forks child tasks, allowing them to execute concurrently, then joins them before using their combined results.
For example, to sum an array recursively:
sum(A):
if A is small: return sequential_sum(A)
fork left = sum(first half of A)
right = sum(second half of A)
join left
return left + right
The two recursive halves have no data dependency and may run simultaneously. The final addition depends on both results.
Forking does not require one operating-system thread per task. A runtime can maintain many logical tasks and schedule them onto a smaller worker pool.
Nested fork-join naturally creates a dependency tree or DAG. The useful parallelism comes from the structure of that graph; the runtime's job is to map ready tasks onto available processors.
Creating tasks has overhead, so practical programs stop subdividing once work becomes small enough that sequential execution is cheaper.