**Convergence Pointer
Convergence pointer 的寻找过程,本质上是让“标记上每个格子的身份”沿着回溯路径一层层往前传播,直到所有路径都携带同一个身份。 下面以 TALCO-XDrop 为例,把整个过程拆开讲清楚。
1. 先理解 convergence pointer 是什么
在 TALCO 中,marker 是一个特殊的 frontier,记作 。
Marker 上最多有 个格子。
Convergence pointer 是每个格子的一个“身份标签”,它回答:
从这个格子沿 traceback 往回走,最终会落到 marker 上的哪个格子?
比如:
- 某个格子的 convergence pointer = 5;
- 意思是:它回溯到 marker 时,会经过 marker 上编号为 5 的那个格子。
所以 convergence pointer 不是指针方向,而是一个指向 marker 格子的索引,用 位表示。
2. 初始化:marker 上的每个格子先指向自己
当算法到达 marker 时:
if j - i = M - 1 then
ConvPrprev ← 为 Scurr 中每个 cell 分配唯一 id
Smarker ← Scurr
end if
此时 Scurr 就是 marker frontier 的分数。
对 marker 上的每个格子,给它一个唯一 id:
- 格子 0 → id = 0
- 格子 1 → id = 1
- 格子 2 → id = 2
- …
然后 ConvPrprev 就是:
ConvPrprev[0] = 0
ConvPrprev[1] = 1
ConvPrprev[2] = 2
...
意思是:marker 上的每个格子,目前只知道自己指向自己。
这是传播的起点。
3. 传播:redirect 函数
进入 Phase 2 后,每推进一个 frontier,就做一次:
ConvPrcurr ← redirect(Prf, ConvPrprev)
redirect 做的事情是:
对当前 frontier 的每个格子,看它的 traceback pointer 指向上一 frontier 的哪个格子,然后继承那个格子的 convergence pointer。
用公式表示:
其中:
Prf[i]:当前 frontier 第 个格子的 traceback pointer;- 它指向上一 frontier 的某个格子;
ConvPrprev[那个格子]:那个格子已经携带的 marker 身份;- 把这个身份赋给当前格子。
这样,marker 的身份就沿着回溯路径,一层一层往前传播。
4. 一个具体例子
假设 marker 上有 3 个格子,编号 0、1、2。
初始化
ConvPrprev = [0, 1, 2]
第一个 frontier 之后
假设当前 frontier 有 3 个格子 A、B、C:
- A 的 traceback pointer 指向 marker 的格子 1;
- B 的 traceback pointer 指向 marker 的格子 1;
- C 的 traceback pointer 指向 marker 的格子 2。
那么:
ConvPrcurr[A] = ConvPrprev[1] = 1
ConvPrcurr[B] = ConvPrprev[1] = 1
ConvPrcurr[C] = ConvPrprev[2] = 2
结果:
ConvPrcurr = [1, 1, 2]
还没收敛,因为不是所有值都相同。
第二个 frontier 之后
假设新的 frontier 有 D、E、F:
- D 的指针指向 A;
- E 的指针指向 B;
- F 的指针指向 C。
那么:
ConvPrcurr[D] = ConvPrcurr[A] = 1
ConvPrcurr[E] = ConvPrcurr[B] = 1
ConvPrcurr[F] = ConvPrcurr[C] = 2
结果还是:
ConvPrcurr = [1, 1, 2]
第三个 frontier 之后
假设 G、H、I:
- G 的指针指向 D → 1
- H 的指针指向 E → 1
- I 的指针指向 E(而不是 F)→ 1
那么:
ConvPrcurr = [1, 1, 1]
所有值都等于 1,收敛了。
此时 ,也就是 marker 上编号为 1 的那个格子。
TALCO 就令:
然后从这个格子开始回溯当前 tile。
5. 怎么判断收敛?
判断条件很简单:
当前 frontier 上所有格子的 convergence pointer 是否都等于同一个值?
- 如果是,就收敛,取这个值为 ;
- 如果不是,就继续推进。
在硬件中,这个判断由 Reduction Tree 完成。
它把当前 frontier 上所有格子的 convergence pointer 收集起来,检查是否全部相同。
6. 为什么这样传播是正确的?
关键在于 traceback pointer 的依赖关系。
在 X-Drop 中,frontier 包含两条相邻 wavefront 和 。
任何从 出发的 traceback 路径,必然经过 上的某个格子。
所以:
- 如果 上所有格子的 convergence pointer 都指向 marker 上的 ;
- 那么从 往后任何格子出发的回溯路径,都会经过 上某个格子;
- 那个格子的 convergence pointer 是 ;
- 所以整条回溯路径必然经过 。
这就是为什么一旦收敛, 就是所有后续路径的必经点。
7. 特殊情况
情况 A:一直不收敛
如果 Phase 2 一直不收敛,但已经到达序列末尾:
C_tb ← ConvPrlatt
ConvPrlatt 是之前保存的、局部最大分格子 Clast 对应的 convergence pointer。
对于全局比对,Clast 是终点 ;对于局部比对,Clast 是当前最大分格子。
所以即使没有收敛,也能用这个值作为回溯起点。
情况 B:局部最大分在收敛前更新
if Clast was updated in the current tile then
ConvPrlatt ← ConvPrcurr[Clast]
end if
这保证局部比对的最大分格子对应的 convergence pointer 被保存下来,以备后用。
8. WFA-Adapt 中的区别
在 TALCO-WFAA 中:
- frontier 是两行,不是两条 wavefront;
- 但 convergence pointer 的传播逻辑一样:
- marker 上的格子先指向自己;
- 每推进一行,用 traceback pointer 继承上一行的 convergence pointer;
- 检查所有 convergence pointer 是否相同;
- 相同则收敛。
区别只在于 frontier 的定义和 traceback pointer 的编码方式,传播机制是相同的。
9. 一句话总结
Convergence pointer 的寻找过程是:marker 上的每个格子先获得唯一 id;然后每推进一个 frontier,每个格子根据它的 traceback pointer 继承上一 frontier 对应格子的 id;这样 marker 的身份就沿着回溯路径一层层传播;当当前 frontier 上所有格子的 id 都相同时,就找到了收敛点 ,它就是当前 tile 的安全回溯起点 。