注:此篇较水,=。=
矩阵的划分一般分为带状划分和棋盘划分,在此基础上又有循环划分的变体:
一般情况下,棋盘划分的划分方法能够开发出更高并行度的算法
注:下面讨论算法中的划分均是没有循环版本的划分
矩阵转置串行执行时间是
我们分析一下算法时间复杂度时都必须考虑第一篇第二章中的通信时间(通信时间和选路方式以及并行集群网络拓扑结构有关),若不考虑通信时间,比如这个矩阵转置,使用
考虑
若不考虑节点延迟时间
在
子矩阵内部用串行转置算法,时间复杂度为
超立方中可以采用递归转置的算法,每次四分块矩阵,p个处理器一直递归转置到矩阵为
不管什么网络拓扑,p个处理棋盘划分矩阵递归转置递归层数为
由于超立方连接拓扑特殊性质,每次存储转发需要
下面讨论
行带状划分,处理器
1.网孔
把上述情况推广到
2.超立方
超立方只有通信时间不一样,查表可得总时间为:
棋盘划分来完成这个问题并不直观且效果也不是很好(没有改进),直接给出棋盘划分在二维网孔上用SF选路的总执行时间:
矩阵乘法串行执行时间是
对于求两个
p个处理器按
考虑计算子矩阵乘法时间为:
1.二维环绕网孔简单并行分块算法运行总时间为:
2.超立方简单并行分块算法运行总时间为:
注意到通信结束时每个处理器有
Cannon算法是一个存储有效的并行矩阵分块乘法算法,它通过一系列巧妙的子矩阵循环移动来避免简单并行分块乘法算法中多到多播送所需要的高存储容量要求
Cannon算法分为两步:
具体的循环移动做法是
Cannon算法十分巧妙也很直观,伪代码就不给出了,直接分析时间复杂度:
在超立方使用CT选路,初始对准循环移位时间为
同理可推知二维网孔上时间为:
Fox算法和Cannon算法的思想一致,都是通过有效的循环移位来降低总存储空间,不过Fox算法采用行一到多播送,列循环单步上移的方法,算法如下:
手工推演可以证明Fox的正确性,并且可以推得在超立方上用CT选路的运行时间为:
求解大规模线性方程组在很多科学领域有十分广泛需求,数值计算方法课程中介绍了许多串行化且可编程的线性方程组求解方法,用并行集群去求解大规模线性方程组需要将这些算法并行化
for i = n downto 1 do
x[i] = b[i]/a[i][i]
for j = 1 to i - 1 do
b[j] = a[j][i] * x[i]
a[j][i] = 0
endfor
endfor
观察串行算法,第二重循环完全可以并行化,下面给出SIMD-CREW上的并行回代算法(p个处理器行循环带状划分)
for i = n downto 1 do
x[i] = b[i]/a[i][i]
for all Pk par-do
for j = k to i - 1 step p do
b[j] = a[j][i] * x[i]
a[j][i] = 0
endfor
endfor
endfor
处理器足够多(p(n)=n)的话,复杂度降到
算法略,
Gauss-Seidel迭代法是利用上一轮迭代结果和本轮迭代已产生结果来进行线性方程组迭代的求解方法(详见《数值计算方法》),其迭代公式为:
Gauss-Seidel迭代法需要利用本轮迭代已产生的值,因此无法同步并行化,下面是MIMD上一步并行算法:
![p2](./data/p2.png =480x)
(没弄懂怎么异步开启进程)
稀疏线性方程组Gauss-Seidel迭代法的并行化两种算法:
(也没搞懂,这部分就弃疗了吧)
n个点
其中
FFT是一种O(nlogn)时间内计算序列DFT的快速算法,FFT主要利用了单位n次元根的对称性,即不需要计算出所有
SISD上FFT递归算法伪代码如下:
Procedure RFFT(a,b) {
if n == 1 {
b[0] = a[0]
} else {
RFFT({a[0], a[2], ..., a[n-2]}, {u[0], u[1], ..., u[n/2-1]})
RFFT({a[1], a[3], ..., a[n-1]}, {v[0], v[1], ..., v[n/2-1]})
z = 1
for j = 0 to n-1 {
b[j] = u[j mod n/2] + z * v[j mod n/2]
z = z * w
}
}
}
递归需要较大的栈开销,一旦数据量较大容易爆栈且函数调用会减慢运算时间,一般计算FFT采用迭代的蝶式FFT算法计算,并行计算书上的迭代版本如下:
for k = 0 to n-1 {
c[k] = a[k]
}
for h = logn - 1 to 0 {
p = 2^h
q = n/p
z = w^(q/2)
for k = 0 to n-1 {
if k mod p == k mod 2p {
c[k] = c[k] + c[k+p]
c[k+p] = (c[k] - c[k+p]) * z^(k mod p)
}
}
for k = 1 to n-1 {
b[r(k)] = c[k]
}
}
SIMD-BF上的FFT算法伪代码如下:
for i = 0 to n-1 par-do
d[0][i] = a[i]
endfor
for r = 1 to log(n) do
//j = exp(r,i)表示第r行第i列的w的指数部分
//i二进制表示为t1t2...tr-1tr...tk则j的二进制表示为trtr-1...t1 0...0
for 所有仅第r位不同且i的第r位取0的每对(i,j) par-do
d[r][i] = d[r-1][i] + w^exp(r,i)*d[r-1][j]
d[r][j] = d[r-1][i] + w^exp(r,j)*d[r-1][j]
endfor
for i = 0 to n-1 par-do
计算exp(k,i) = j
c[j] = d[k][i]
b[i] = c[r(j)]
endfor
endfor
PS:我并没有搞懂这个算法
蝶形网络连接无须考虑选录时间(why?),因为除了层次的for其他均是并行,时间复杂度为O(logn)
原文地址:http://blog.csdn.net/u014030117/article/details/46454613