is a union of the accesses within its task body and the accesses performed by its spawned tasks. This information can
be gathered as part of the task return step. However, this
metadata collection can be extremely inefficient and introduce significant overheads during normal execution.
We employ a versioning scheme to track non-speculative
updates to data blocks. Each data block starts with version
0. Every task writing to a data block increments its version
number. In a data-race free program, writes to a data block
are serialized. Therefore, this version number update can be
performed without expensive locks or atomic actions.
A speculative thread performs its updates on a shadow
version of the data blocks and tracks the version numbers
of any data blocks it reads or writes. When all computations preceding the sync being speculated—the task’s outstanding children—complete, the current version numbers
are compared with those accessed in the speculation phase.
A difference in the version numbers indicates a conflict.