计算矩阵A
和B
的乘法,其基本代码是
1 | for(i=0; i<n; i++) |
但这样的代码却存在以下的问题:
1、局部性较差
由于B
是按列访问的,所以其局部性较差
2、 不能保证A[i]
始终在缓存中
内层循环的执行可能导致A[i]
被缓存置换策略淘汰。
在单CPU上进行优化
在GPU上进行优化
并行算法
分块矩阵
很多并行算法都和分块矩阵有关,这是因为分块矩阵有非常好的性质。
简单地说,我们可以把分块矩阵当成矩阵中的元素一样相乘,然后把原矩阵带回即可。
信息传输
在节点间传输信息的时间可以使用下面的式子描述
$$
T_{msg} = t_s + t_w L
$$
其中$t_s$是startup time或者latency,也就是传输一条长度为0的信息所需要的时间。$t_w$是每多发送一个单词所额外需要的时间那么$1/t_w$就是单位时间的带宽(按单词计算),$L$是消息中的所有单词。对于大多数分布式系统来说,$t_s$是相当大的。
Cannon算法
Cannon算法是一个经典的2D算法。
Cannon算法是对方阵而言的,我们将矩阵A
和B
分为p
个方块,则每个方块的边长是n / sqrt(p)
。这个值必须要是能整除的,因而存在不少限制。
对应的,我们有p
个处理器来计算这p
个分块,处理器P[i, j]
计算分块C[i]=A[i]*B[i]
。在计算时,Cannon主要采用了称为”Shift and multiply”的思想。
以下图为例,在计算C[0, 0]
时,可以不停地将A
的框往左移动,B
的框往上移动,然后原位相加。
1 | C[0,0] = A[0,0]*B[0,0] + A[0,1]*B[1,0] + A[0,2]*B[2,0] |
那么对于其他的位置比如C[0, 1]
,我们就不能刚好地找到对应了。
Reference
- https://fzuo.github.io/2015/09/26/matrix-cannon.html
- https://zh.wikipedia.org/wiki/%E5%88%86%E5%A1%8A%E7%9F%A9%E9%99%A3
- Understanding the Efficiency of GPU Algorithms for Matrix-Matrix Multiplication
- http://cseweb.ucsd.edu/classes/fa12/cse260-b/Lectures/Lec13.pdf
- https://www3.nd.edu/~zxu2/acms60212-40212-S12/Lec-07-3.pdf
- http://read.pudn.com/downloads500/sourcecode/mpi/2079312/summa/summa-2010.pdf
- SUMMA: Scalable Universal Matrix Multiplication Algorithm
- https://courses.engr.illinois.edu/cs554/fa2015/notes/01_overview_8up.pdf
- http://www.inf.ed.ac.uk/teaching/courses/dapa/overheads.pdf