为什么Strassen矩阵乘法比标准矩阵乘法慢得多?

时间:2012-07-15 21:25:04

标签: c++ performance matrix multiplication strassen

我用C ++,Python和Java编写了用于矩阵乘法的程序,并测试了它们乘以两个2000 x 2000矩阵的速度(参见post)。标准的ikj-implementntation - 位于enter image description here - 采用:

现在我已经实现了Strassen algorithm for matrix multiplication - 位于enter image description here - 在Python和C ++中,就像它在维基百科上一样。这些是我的时代:

  • C ++ :45分钟(Source
  • Python :10小时后被杀死(Source

为什么Strassen矩阵乘法比标准矩阵乘法慢得多?

<小时/> 思路:

  • 一些缓存效果
  • 实现:
    • 错误(生成的2000 x 2000矩阵是正确的)
    • null-multiplication(对2000 x 2000来说不应该那么重要 - &gt; 2048 x 2048)

这尤其令人惊讶,因为它似乎与其他人的经历相矛盾:


编辑:在我的案例中,Strassen矩阵乘法较慢的原因是:

  • 我完全递归(见tam)
  • 我有两个函数strassenstrassenRecursive。第一个将矩阵的大小调整为2的幂,如果需要,称为第二个。但是strassenRecursive没有递归地调用自己,而是strassen

4 个答案:

答案 0 :(得分:16)

基本问题是您使用strassen实现递归到叶子大小为1。 Strassen的算法具有更好的Big O复杂度,但常量实际上很重要,这意味着实际上对于较小的问题大小,使用标准的n ^ 3矩阵乘法会更好。

所以要大大改进你的程序而不是做:

if (tam == 1) {
        C[0][0] = A[0][0] * B[0][0];
        return;
    }

使用if (tam == LEAF_SIZE) // iterative solution hereLEAF_SIZE应该是一个常数,您必须通过实验确定您的给定体系结构。根据架构,它可能更大或更小 - 有一些架构,其中strassen的常数因子如此之大,以至于它基本上总是比简单的n ^ 3实现更合理的矩阵大小。这一切都取决于。

答案 1 :(得分:6)

嗯,“算术运算”并不是唯一重要的事情。这并不像其他一切都是免费的。

我天真的猜测是,所有这些内存分配和复制都会因减少算术运算而获得收益......

特别是内存访问,当它从缓存中移出时可能非常昂贵。相比之下,arihmetic操作可以被认为是免费的: - )

答案 2 :(得分:0)

尽管Strassen算法的Big O表示法较小,但为了充分利用这一点,您需要在大多数标准机器甚至超级计算机上使用太大而无法解决的物质。

以这种方式思考

一个问题是x ^ 3,另一个是X ^ 1.6734 + 8x ^(1/2)+ x .....

答案 3 :(得分:0)

我记得我在大学时也做过同样的事情。 我的实现是用 Java 实现的。我还写了一个脚本来测试代码,我有超过 10000 个测试用例,其中包含不同大小的随机矩阵 (22) ~ (81928192)。我没有让递归达到标量级别,我使用所有 2 的幂作为停止点。 我发现了一个范围,其中 Strassen 的效率更高,而一个范围比朴素算法更差。

我没有调查缓存、内存或 JVM(垃圾收集)。

当我在全班同学面前展示时,我将这些发现归因于一个事实,即 Strassen 的算法渐近复数是根据乘法的次数来衡量的。它是在计算机加法比乘法快的时代设计的。

如今,CPU 的倍增与添加(周期数)一样快。 如果检查这两种算法,你会发现只有当大小小于 2^10 时,Strassen 的算术运算比朴素算法少(如果我没记错的话)