循环展开以乘以两个矩阵NxN?

时间:2012-04-19 06:41:44

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

我正在试图找出一个好的循环展开以乘以两个矩阵。

例如,如果我们想要求和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;        
}

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

备注:这不是家庭作业,我今天参加考试,只考虑这个问题,我认为这对考试来说可能是一个很好的问题,不是吗?

我很感激任何帮助

此致

罗恩

2 个答案:

答案 0 :(得分:2)

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

另外,有了你的问题,它是一个二维矩阵并不重要,因为你要添加所有数字。如果您仅限于一个进程/线程,则按顺序添加数字将是最快的,因为它具有最佳的缓存性能。你可以从SSE或向量指令中获得一些好处;再一次,今天的编译器可以通过这么简单的问题为你做这些。

答案 1 :(得分:0)

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