【发布时间】:2017-09-12 09:32:04
【问题描述】:
我尝试实现 Cannon 的矩阵乘法算法。 我阅读了关于提供下一个伪代码的wikipedia 的描述:
row i of matrix a is circularly shifted by i elements to the left.
col j of matrix b is circularly shifted by j elements up.
Repeat n times:
p[i][j] multiplies its two entries and adds to running total.
circular shift each row of a 1 element left
circular shift each col of b 1 element up
接下来我在 C# 上实现了它:
public static void ShiftLeft(int[][] matrix, int i, int count)
{
int ind = 0;
while (ind < count)
{
int temp = matrix[i][0];
int indl = matrix[i].Length - 1;
for (int j = 0; j < indl; j++)
matrix[i][j] = matrix[i][j + 1];
matrix[i][indl] = temp;
ind++;
}
}
public static void ShiftUp(int[][] matrix, int j, int count)
{
int ind = 0;
while (ind < count)
{
int temp = matrix[0][j];
int indl = matrix.Length - 1;
for (int i = 0; i < indl; i++)
matrix[i][j] = matrix[i + 1][j];
matrix[indl][j] = temp;
ind++;
}
}
public static int[][] Cannon(int[][] A, int[][] B)
{
int[][] C = new int[A.Length][];
for (int i = 0; i < C.Length; i++)
C[i] = new int[A.Length];
for (int i = 0; i < A.Length; i++)
ShiftLeft(A, i, i);
for (int i = 0; i < B.Length; i++)
ShiftUp(B, i, i);
for (int k = 0; k < A.Length; k++)
{
for (int i = 0; i < A.Length; i++)
{
for (int j = 0; j < B.Length; j++)
{
var m = (i + j + k) % A.Length;
C[i][j] += A[i][m] * B[m][j];
ShiftLeft(A, i, 1);
ShiftUp(B, j, 1);
}
}
};
return C;
}
此代码返回正确的结果,但执行速度很慢。甚至比简单的矩阵乘法算法慢得多。
对于矩阵 200x200,我得到了结果:
00:00:00.0490432 //naive algorithm
00:00:07.1397479 //Cannon's algorithm
我做错了什么?
编辑
感谢 SergeySlepov,平行进行是不好的尝试。当我回到顺序实现时,我得到了下一个结果:
Count Naive Cannon's
200 00:00:00.0492098 00:00:08.0465076
250 00:00:00.0908136 00:00:22.3891375
300 00:00:00.1477764 00:00:58.0640621
350 00:00:00.2639114 00:01:51.5545524
400 00:00:00.4323984 00:04:50.7260942
好的,这不是并行实现,但我怎样才能正确地做到这一点?
【问题讨论】:
-
您不需要实际上移动元素。像
A[(i + shift) % len]这样的东西可以解决问题。 -
这个算法是一个分布式算法。除非您有(很多)机器将其应用于比 200x200 大得多的矩阵,否则您不太可能看到改进。
-
@SergeySlepov 谢谢,我想过,但没能得到它(似乎很难正确地做到)
-
@IVlad 谢谢,我知道,但在我看来,差异很大。是不是太大了?
-
@SergeySlepov,是的,速度下降了两倍。所以,数组数组获胜:)
标签: c# algorithm matrix parallel-processing matrix-multiplication