矩阵乘法与C和OpenMP

时间:2012-05-24 10:28:02

标签: c performance matrix matrix-multiplication

我正在尝试创建一种有效的算法,可以将具有双精度的大值矩阵相乘。我已经创建了算法并首先在小矩阵上测试它;在尝试了A {4096x4096},B {4096x4096}后,循环将永远结束;以这两个矩阵为例,生产AB让我的电脑完成了30多分钟。

我的电脑不是一个古老的懒散......它是一个六核i7,我猜对于台式机工作站它并没有那么糟糕。在尺寸高达1024x1024的小矩阵上,相对较快,即30-40秒,2048x2048约5分钟......对于16384x16384,它在15分钟内没有完成,我停止执行...

我做错了什么或者这是预期的? :)

提前致谢!

代码如下:

/* calculate */
for(travx = 0; travx < m; travx++) {
    for(travy = 0; travy < n; travy++) {
        /* we only need to calculate it ourside of Z loop */
        tIndex = (travy)+(travx*n); 
        for(travz = 0; travz < p; travz++)
            {
                if(n==1)
                    {bIndex = ((n-1)*travy)+travz;
                     aIndex = ((p)*travx)+travz;} 
                else
                    {bIndex = ((n)*travz)+travy;
                     aIndex = ((p)*travx)+travz;}

                temp = atab_ptr[aIndex]*btab_ptr[bIndex];
                outtab_ptr[tIndex] =  outtab_ptr[tIndex] + temp;
            }
    }
}

它真的很简单...并且在小矩阵上给出了很好的结果...不知道如何在10秒内将双倍乘以特别是在p4上...听起来有点腥...特别是如果你考虑到O (3)问题的复杂性。

更新...基于反馈我已经调整了代码和...好吧主要是我做了它的简化和小矩阵完成得更快,即1024x1024在3秒内完成,但4096x4096在6完成分钟...修改后的代码是:

for(travx = 0; travx < m; travx++) {
    for(travy = 0; travy < n; travy++) {
      for(travz = 0; travz < p; travz++)
        {outtab_ptr[travy+travx*n] = outtab_ptr[travy+travx*n] + atab_ptr[travy+p*travz] *  btab_ptr[travz+travx*p];}
    }
  }

3 个答案:

答案 0 :(得分:4)

如果可以的话,BLAS是最好的方式。

话虽如此,从根本上说,矩阵乘法受到复杂性的限制,因此您必须更加智能地大幅减少时间。矩阵是否以任何方式构成?他们是tridiagonal还是banded?他们是triangular还是symmetric

答案 1 :(得分:1)

您的“高效”算法实际上效率很低。看看n不是1时会发生什么:

bIndex = ((n)*travz)+travy;
aIndex = ((p)*travx)+travz;
temp = atab_ptr[aIndex]*btab_ptr[bIndex];

最里面的循环超过travz,因此aIndex会在travz的每个增量上随着步骤1而增加。另一方面,bIndexn的步长增加。因此,您正在访问内存中不相邻的btab_ptr元素,因此不在同一缓存行中。

更不用说最内层循环中的条件对可能的矢量化有什么影响。

因此,如果所有矩阵的数据都适合Core i7的L3缓存,那么您的算法的工作速度可以接受,但只要不是这种情况,您的性能就会急剧下降。然后将其进一步乘以O(N ^ 3)复杂度。

答案 2 :(得分:0)

嗯,矩阵乘法的天真方法是O(n ^ 3)。这意味着乘以两个矩阵所需的时间随着输入的大小以立方方式增长。有更有效的方法。在这里你可以看看:

http://en.wikipedia.org/wiki/Computational_complexity_of_mathematical_operations#Matrix_algebra

这些方法仍然没有低于O(n ^ 2)。因此,当你增加矩阵的大小时,完成的时间越来越多地以超线性方式增长是正常的。

话虽如此,无论您观察的时间是否过多,都取决于许多因素(您的机器,代码等)。

顺便说一下,您可以查看此thread,其中提出了一个非常相似的问题。而且,除非你是出于教育目的,否则你最好使用ATLAS这样的优化库。

在这里,您还有一个关于如何优化应用程序以获得更好内存使用的经典document。在该文档中,作者使用了几种技术,如对齐和预取,以优化矩阵乘法的性能。