【问题标题】:Loop unrolling for multiplying two matrices NxN?循环展开以将两个矩阵相乘 NxN?
【发布时间】:2012-04-30 15:50:30
【问题描述】:

我正在尝试找出一个很好的循环展开来将两个矩阵相乘。

例如,如果我们想对 NxN 矩阵求和:

void SumMatrix(int *M, int n, int *result) 
{ 
  int  i,j; 

  *result = 0; 
  for (i=0; i<n; i++) 
    for (j=0; j<n; j++) 
      *result += M[j][i]; 
}

我们可以这样做:

void SumMatrix(int *M, int n, int *result) 
{ 
    int  i; 
    int  size = n*n; 
    int  last = size%8; 
    int  acc1 = 0; 
    int  acc2 = 0; 
    int  *pEnd = M+size-last; 

    for (; M<pEnd; M+=8) 
    { 
      acc1 += (*M + *(M+1)) + (*(M+2) + *(M+3));
      acc2 += (*(M+4) + *(M+5)) + (*(M+6) + *(M+7));
    } 

    /* adding the last entries */ 
    while (last--)  
        acc1 += *(M++); 

    *result = acc1+acc2;        
}

但我试图找到一种(好的)方法来乘以 2 个矩阵,但目前没有找到。

备注:这不是家庭作业,我今天要考试,只是想到了这个问题,我认为这可能是一个很好的考试问题,不是吗?

我会很感激任何帮助

问候

罗恩

【问题讨论】:

  • 取决于考试的性质。如果专门针对低级性能优化(前提是已通过测量证明a)第一个代码版本是一个重要的性能瓶颈,并且b)第二个版本在实际生产环境中的运行速度明显快于第一个),然后就好了。如果是关于一般的 C 编程,绝对不是。第一段代码比第二段更简洁、易于阅读、验证和维护。
  • @PéterTörök:不,使用 3 个 FOR 循环对两个矩阵进行通常的乘法运算。我试图让 if 更快,并且使用 SUM ,就像上面的代码一样。
  • 我明白你想做什么。你明白我的评论吗?你有什么考试?

标签: c optimization loops for-loop compiler-optimization


【解决方案1】:

大多数编译器都会为您完成展开(您可能需要打开一个标志,或将其设置为优化级别 - 我相信 -funroll-loops 会为 gcc 执行此操作)。

此外,对于您的问题,它是 2D 矩阵这一事实并不重要,因为您将所有数字相加。如果您仅限于单个进程/线程,则按顺序将数字相加将是最快的,因为这具有最佳的缓存性能。您可能会从 SSE 或向量指令中获得一些好处;同样,今天的编译器可以为您解决如此简单的问题。

【讨论】:

  • 谢谢,你有一段代码我可以看看吗?
  • 要使用 gcc 进行矢量化,请使用 -ftree-vectorize 运行简单的单循环求和代码以对其进行矢量化;使用-ftree-vectorize-verbose=2,它会在编译它矢量化的循环时告诉你。
【解决方案2】:

看看 ATLAS 项目有多复杂,它提供了 BLAS 库的优化版本(主要基于矩阵乘法)。它不仅应该考虑线程级并行性,还应该考虑内存层次结构(不仅是展开,还应该考虑缓存平铺和寄存器平铺、软件流水线等)。它通常由手写或由“自动调谐器”优化,如 ATLAS。如果您想解开线程级并行性,您最好使用“平铺算法”并在您的线程之间传播生成的平铺计算。

【讨论】:

    猜你喜欢
    • 2020-07-18
    • 1970-01-01
    • 2015-04-01
    • 1970-01-01
    • 2018-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多