pbqp/README.md

125 lines
3.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# QBQP 算法
寄存器分配算法。
## 约束方程的含义
主要就是约束方程了:
$$
min\{ \sum_{i \le i \lt j \le n} X_i^T C_{ij} X_j + \sum_{i=1}^n X_i^T \vec{E(t_i)} \}
$$
- $X_i = (x_{i, sp}, x_{i, r_1}, x_{i, r_2}, ..., x_{i, r_K})^T$
- 这里 $x_{i, sp}$ 表示将 $t_i$ spill -> stack 的代价。
- $X_i = (x, xxx, ..., x)^T$ 只有一个 分量=1其他都是 0
- K 表示 $t_i$ 有 K 个可选的寄存器(不一定是所有的 physical reg这是显然的比方说不想要破坏到 callee-saved 寄存器)。
- $C_{ij}$ 量化了 $t_i$ 和 $t_j$ 之间的相互影响
- i === j? (不一定比方说在传参的时候i 可以放到 a0 但是 j 是不能放到 a0 的)
- 但是我有一种想法: 就是我认为还是要把 32 个寄存器全部摆上台面的,如果不能用,我认为可以相应的可以设置为 $\infin$ ,这显然可能会变成一个 稀疏矩阵,然后是不是可以进行 凸优化啥的。如果 i!=j 并且有: $R_i$ ^ $R_j \ne \phi$ 那这可能需要对齐,可能有点麻烦
- 如果 i === j那么可以做一件事情将 $c_{ij}$ 的对角线设置为 负数。对角线意味着: virtual reg $t_i$ 和 $t_j$ 是可接合的,可以分配到 同一个 physical reg 的,负数的 语义 是:鼓励接合(代价总是越小越好)
- $\vec{E(t_i)}$ : $t_i$(virtual reg) 溢出的代价。如果每个 $t_i$ 都选择了 spill ,那么相当于是: $\forall t_i, X_i = (1, 0, ..., 0)$,那么 $\sum_{i=1}^n s_i X_i = \sum_{i=1}^n E(t_i)$
## 启发式 规约求解
### reduce 1
如果只有 $K^2$ 的完全图,有两个节点 X 和 Y
那么上面的约束方程可以写成:
$$
min\{ X^T C Y + X^T \vec{E(x)} + Y^T \vec{E(y)} \}
$$
最终经过一通数学计算可以得到:
(如何求解? 一个关键步骤是: 令 某一串式子 = 0
$$
Y^T ( \vec{E(y)} + ( ... min\{ X + C_{,k} \}_{ 1 \le k \le i } ... )_{i} )
$$
### reduce 2
```
C_yz[i][j] = min{ C_xy(第i列) + C_xz(第j列) + E_x }
```
这里将一个向量 通过 min(reduce) 规约成一个标量
### reduce N
```
for (i = 1; i < len(E_y); i++) {
delta(i) = 0;
for (j = 1; j < len(E_z); j++) {
delta(i) = min(C_xy(i, :) + E_y);
}
}
min_index = get_min_index(delta);
for y : vertex in adj(x) {
E_y += C_xy(min_index, :);
}
```
state i -> 指的是选中 C_xy 的第 i 列( y 是 x 的所有 adj -> delta(i) += C_xy(i, :)。
找到 delta(i) 最低的那一列,然后再更新每一个代价向量
## 伪代码
伪代码 ( from 华保健 ) 如下:
```pseudocode
void reduce_1(vertex x) {
y = adj(x);
for (i = 1; i < len(E_y); i++) {
delta(i) = min(C_xy(i, :) + E_x);
}
E_y += delta;
remote_vertex(x);
}
void reduce_2(vertex x) {
y, z = adj(x);
for (i = 1; i < len(E_y); i++) {
for (j = 1; j < len(E_z); j++) {
delta(i) = min(C_xy(i, :) + C_xz(j, :) + E_x);
}
}
C_yz += delta;
remote_vertex(x);
}
void reduce_N(vertex x) {
for (i = 1; i < len(E_y); i++) {
delta(i) = 0;
for (j = 1; j < len(E_z); j++) {
delta(i) = min(C_xy(i, :) + E_y);
}
}
min_index = get_min_index(delta);
for y : vertex in adj(x) {
E_y += C_xy(min_index, :);
}
remote_vertex(x);
}
void solve_PBQP(graph pbqp_model) {
while (pbqp_model still has edges) {
simplify(pbqp_model);
while (there exists any vertex x of degree 1) {
reduce_1(x);
}
while (there exists any vertex x of degree 2) {
reduce_2(x);
}
while (there exists any vertex x of degree >= 2) {
reduce_N(x);
}
}
}
```
### rust
看 src/main.rs (from gpt)