快速矩阵乘法的算法实现

矩阵乘法

对于两个矩阵的相乘,只有在第一个矩阵的列数和第二个矩阵的行数相同的时候,其乘积才有意义。

最早出现的就是一般的矩阵乘法,并且在很长的一段时间内人们都认为该算法无法继续改进,直到1969年,Strassen发明了一个算法,首次降低了矩阵乘法的时间复杂度,并且该算法也以他的名字命名——Strassen算法。

在后续的几十年里,人们在Strassen算法的基础上不断改进算法,并且在逐步降低矩阵乘法的时间复杂度。比较有里程碑意义的是在1990年,Coppersmith和Winograd两个人对算法进行的改进,其算法也被称为算法。

一般矩阵乘法

一般矩阵乘法,将第一个矩阵一行中的元素与第二个矩阵中一列对应位置上元素的乘积之和,作为第三个矩阵这一行一列对应位置的结果。

在这里插入图片描述
在这里插入图片描述
对于n*n的矩阵乘法其时间复杂度为O(n3)

/*
 * Generate Algorithm
 * matA a M*K matrix
 * matB a K*N matrix
 * matC a M*N matrix
 * matC = matA * matB
 */
static void mm_generate(float* matA, float* matB, float* matC, const int M, const int N, const int K)
{
	for (int i = 0; i < M;i++)
	{
		for (int j = 0; j < N;j++)
		{
			float sum = 0.0f;
			for (int k = 0; k < K;k++)
			{
				sum += matA[i*K + k] * matB[k*N + j];
			}
			matC[i*N + j] = sum;
		}
	}
}

分块算法

将矩阵分割成四块来计算

在这里插入图片描述
在这里插入图片描述
这里需要8个乘法和4个加法
其时间复杂度依然是 O(n3)

Strassen 算法

Strassen在分块的基础上进行改进
在这里插入图片描述
在这里插入图片描述
这里用了7个乘法和18个加/减法
对于每一个 n * n 矩阵,可以看成有 2 * 2 的小矩阵拼接而来,因此会有 n/2 * n/2 个小矩阵
T(n) = 7 * T(n/2) + O(n2)
T(n) = O(nlg7) + O(n2.81)
其算法的时间复杂度为O(n2.81)
Github:Straseen算法的代码实现

相较与一般算法来说,只有在n很大的时候才会体现出性能上的优势,并且在实现是采用递归调用,每次调用会产生中间7个矩阵,所占用的空间要比一般的算法多。

Coppersmith-Winograd算法

后来Coppersmith Winograd 两个人对算法进行了改进
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这里总共用了7个乘法,15个加/减法
其时间复杂度为O(n2.376)
Github:Coppersmith-Winograd算法的代码实现

该算法具体的介绍可以在以下论文中找到
论文链接:
The Coppersmith-Winograd Matrix Multiplication Algorithm
On the Arithmetic Complexity of Strassen-Like Matrix Multiplications

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值