我正在试图找出一个好的循环展开以乘以两个矩阵。
例如,如果我们想要求和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个矩阵,但目前没有找到。
备注:这不是家庭作业,我今天参加考试,只考虑这个问题,我认为这对考试来说可能是一个很好的问题,不是吗?
我很感激任何帮助
此致
罗恩
答案 0 :(得分:2)
大多数编译器都会为您进行展开(您可能需要打开一个标记,或者将其设置为优化级别 - 我相信-funroll-loops
会为gcc执行此操作。
另外,有了你的问题,它是一个二维矩阵并不重要,因为你要添加所有数字。如果您仅限于一个进程/线程,则按顺序添加数字将是最快的,因为它具有最佳的缓存性能。你可以从SSE或向量指令中获得一些好处;再一次,今天的编译器可以通过这么简单的问题为你做这些。
答案 1 :(得分:0)
看看ATLAS项目有多复杂,它提供了BLAS库的优化版本(主要基于矩阵乘法)。它不仅应考虑线程级并行性,还应考虑内存层次结构(不仅要展开,还要考虑缓存切片和寄存器平铺,软件流水线等等)。它通常由手写或由“自动调谐器”优化,如ATLAS。如果您想要解开线程级并行性,最好使用“平铺算法”并在线程之间传播生成的切片计算。