Paper Reading | A Tree Clock Data Structure for Causal Orderings in Concurrent Executions

本文是对 A Tree Clock Data Structure for Causal Orderings in Concurrent Executions (ASPLOS’22) 这篇论文的学习笔记。

个人感觉这篇文章非常精妙,提出了 tree clock 这种数据结构来替代目前 Data Race 检测算法中广泛使用的数据结构 vector clock,极大的改善了计算 happen-before 关系时的时间复杂度。

Contribution

首先来看 tree clock 解决的是什么问题:

假设程序中有 k 个线程,那么 vector clock 的大小就是 k,那么 vector clock 在做 join 和 copy 操作时,就是 $\Theta(k)$ 的时间复杂度。因此,当 k 很大时,join 和 copy 就是 bottleneck。而 tree clock 可以优化该 linear 的时间复杂度为 sublinear。

Key Insight

vector clock 最基本的操作就是 join 操作,即 $\mathbb{C}{t_1} \sqcup \mathbb{C}{t_2} = \lambda t.\;max(\mathbb{C}{t_1}(t), \mathbb{C}{t_2}(t))$

考虑如下例子:

Tree Clock Data Structure

Tree clock 每一个节点对应 vector clock 中的一个 entry,每个节点 u 都由三个元素组成 (tid, clk, aclk),每个节点的子节点 Chld(u) 都是按照 aclk 的大小降序排序的。

我们举例来说明节点的每一个元素所代表的意义:

$sync(l)$ 表示同步操作,如图 2(a) 中线程 $t_1$ 和线程 $t_2$ 于事件 $e_1$ 和 $e_2$ 处进行同步,即线程 $t_1$ 在 $e_1$ 释放了锁 $l_1$,线程 $t_2$ 在 $e_2$ 获取了锁 $l_1$,事件 $e_1$ 和 事件 $e_2$ 满足 happen-before 关系。

图 3 左边的树对应图 2(a) 中线程 $t_4$ 在事件 $e_7$ 后的 tree clock:

图 3 右边的树对应图 2(b) 中线程 $t_4$ 在事件 $e_7$ 后的 tree clock:

Algorithm

Tree clock 详细的数据结构及算法如下图所示:

我们还是举例说明 tree clock 执行 Join 和 MonotoneCopy 这两个关键操作的算法流程。

Join

我们用 $TC_2.Join(TC_1)$ 表示 joins the tree clock TC1 to TC2。

以图 4 说明,$TC_2.Join(TC_1)$ 的流程:

MonotoneCopy

我们用 $TC_2.MonotoneCopy(TC_1)$ 表示 copy TC1 to TC2 when we know that TC2 ⊑ TC1 。

$TC_2.MonotoneCopy(TC_1)$ 的流程就不再详细解释了,这里以图 5 为例简单描述下:

Conclusion

本文提出了 tree clock 这种数据结构,一种用于在并发执行中维护逻辑时间的新数据结构。 与 vector clock 相比,核心思想就是 tree clock 额外保存了“当前 tree clock 中每一个 thread 的 clock 的值是何时从何处获取到的”这一信息,利用这一信息 tree clock 可以在 sublinear 时间内执行 join 和 copy 操作,从而尽可能避免了由于冗余操作造成的时间开销。

原本中还有很多部分都涉及到一些复杂的数学证明,我就没有涉猎了。

P.S. 这篇论文获得 ASPLOS 2022 的 Best Paper Awards 我觉得当之无愧。