优化我们的程序(数据篇):依赖关系与并行化

依赖关系与并行化

我们需要把有依赖关系的数据都交给同一个CPU处理,这样其他数据都可以交给其他CPU并行处理,并行的加速比公式Amdahl定律:

1/( (1 - f) + (f / p)  )

笔者个人认为,这个公式的主要精髓在于并行流受限于串行流,加速比其实主要取决于并行化最低的数据,也就是依赖性最严重的数据,这部分数据必须串行执行。

数据依赖有三种类型:

真依赖:写运算后面接一个读运算

反依赖:读运算后面接一个写运算

输出依赖:两个针对同一个位置的写运算

依赖性产生的条件:

1.必须有一个操作是写操作

2.存在不同的迭代访问了同一个内存位置

举例:

for(i = 0; i <= 10; i++){
	for(j = 0; j <= 10; j++){
		Z[i][j] = Z[j+10][i+11];
	}
}

只考虑整数解的方程被称为丢番图方程。

我们考虑有两次访问,列出不等式和依赖条件:

0<=i1,j1,i2,j2<=10
i1 = j2 + 10
j1 = i2 + 11

gcd测试就是最大公约数测试,我们可以把方程写成gcd(1,1,10),然后确定是否有解,如果gcd无解,那么该方程也无解。

理由是:对于整数乘法,相等的两边必定存在公约数。

举例:

2i = 2j +1

这个丢番图方程显然是没有解的。

观察两个方程,可以确定都存在整数解,我们求解的结果是不等式,因此求解的技巧就是将等式带入不等式,

重新整理不等式可以得到:

10 <= i1 <= 10
11 <= i2 <= 10

那么数据依赖并不存在,因为该不等式无法满足。

在求解不等式时,我们也可以观察上下界,并将上下界替换为某些最小的常量,这被称之为无环测试。

不等式与有向图

任何数据,只要它能够体现出方向性,那么它就可以被转换为有向图。

我们可以使用循环残数测试不等式的有向图是否合理,具体规则就是:如果有环的值是负数,那么这些约束肯定不成立。

有向图边长的权重的实际意义就是:将不等式消去中间项,转化为上界和下界,如果上下界发生矛盾,那么该解就不成立。

具体做法如下:

v <= c替换成v <= v0 + c
c <= v替换成v0 <= v - c

举例:

1 <= v1,v2 <= 10
0 <= v3 <= 4
v2 <= v1
2v1 <= 2v3 - 7

我们可以先从最后一个入手,由于我们求解的对象是丢番图方程,也就是说,我们只用考虑整数解,最后一个方程化为:

v1 <= v3 - 7/2 
也就是:
v1 <= v3 -4 <= v3 - 7/2

现在应用上面的做法:

v0 <= v1 - 1, v1 <= v0 + 10
v0 <= v2 - 1, v2 <= v0 + 10
v0 <= v3, v3 <= v0 + 4
v2 <= v1,
v1 <= v3 - 4

画出约束图:

0
负4
+4
0
+10
+10
+10
负1
v2
v1
v3
v0

我们观察到,在v0–>v1–>v3–>v0这条环中,权重是负数,也就是说这些约束条件无解。

可能使用图直接应用不够直观,让我们从不等式进行推导:

v1-->v0,对应图的-4 + +4 ,也就是0,对应不等式变换:
v1 + 4 <= v3 <= v0 + 4,
剩下的同理

我们发现,各边权重相加的过程,其实就是不等式消除中间变量导向两边关系的过程。

最终,如果环的权重小于0,那么说明两边出现了矛盾性,我们可以推断出:

v < v

这样的关系明显是不可能存在的,所以这些约束关系无解。

记忆模式

记忆模式就是查表记录,对图问题的求解是一个NPC问题,就是可以看见求解集合的范围,也可以进行穷举,但是很难找到一个多项式算法来描述它,不过也有人给出了各种条件下的NPC问题求解算法,所以有人开玩笑说:证明NPC问题本身就是一个NPC问题。

记忆模式,其实就是计算结果后,保存到表中,这样处理后,每次算法都可以查询这个表。

其实既然涉及到了记忆模式,那么可以考虑使用自动机了,我们可以保留某些结果的特征,作为NFA(有穷自动机)中的状态转换的部分,不然每一次都要遍历全部结果,这样的算法是得不偿失的。

使用Fourier-Motzkin算法

在前面的文章中提到过这个算法,它是一个多面体约束常用的算法,我们也可以用它对不等式进行运算处理,这里就不过多赘述了。

你可能感兴趣的:(编译器,程序优化,计算机科学与技术,并行化)