1

尝试递归地实现块矩阵乘法。它适用于 2x2 的矩阵,但增加到 4x4 等大小时,答案差别很大

3 for 循环的结果

1.53 0.89 0.53 1.33 
1.75 1.09 0.72 1.17 
1.78 1.43 0.57 1.69 
1.73 1.04 0.62 1.51 

递归结果

1.34 1.49 0.30 1.45 
2.02 1.93 0.79 1.30 
2.70 2.75 0.87 2.21 
1.81 1.84 0.59 1.47

如果矩阵中的块数量大于 4,我将块分成四个较大的块并取平方根以获得新维度,然后进行 8 次递归调用。

void myRecMat(float** MatrixA, float** MatrixB, float** MatrixC, int srA, int scA, int srB, int scB, int srC, int scC, int blocks,int dim){
 if(blocks > 4) 
{ blocks=blocks/4;
      int newDim = dim/2;

        myRecMat(MatrixA,MatrixB,MatrixC, srA,scA,srB,scB,srC,scC,blocks,newDim);
        myRecMat(MatrixA,MatrixB,MatrixC, srA,scA+newDim,srB+newDim,scB,srC,scC,blocks,newDim);
        myRecMat(MatrixA,MatrixB,MatrixC, srA,scA,srB,scB+newDim,srC,scC+newDim,blocks,newDim);
        myRecMat(MatrixA,MatrixB,MatrixC, srA,scA+newDim,srB+newDim,scB,srC+newDim,scC,blocks,newDim);
        myRecMat(MatrixA,MatrixB,MatrixC, srA+newDim,scA,srB,scB,srC+newDim,scC,blocks,newDim);
        myRecMat(MatrixA,MatrixB,MatrixC, srA+newDim,scA+newDim,srB+newDim,scB,srC+newDim,scC,blocks,newDim);
        myRecMat(MatrixA,MatrixB,MatrixC, srA+newDim,scA+newDim,srB,scB+newDim,srC+newDim,scC+newDim,blocks,newDim);
        myRecMat(MatrixA,MatrixB,MatrixC, srA+newDim,scA+newDim,srB+newDim,scB+newDim,srC+newDim,scC+newDim,blocks,newDim); }                   
else
{
 int i,j,k,endR,endC;
 endR=srC+dim;
 endC=scC+dim;


 for(i=srC; i< endR; i++)
        for(j=scC;j< endC;j++)
            for(k=0; k<newDim; k++) 
                    c[i][j] += a[i][k]*b[k][j];

}
}

sr 和 sc 用于起始行和列。间距应该是正确的,所以老实说我在这里没有线索。先谢谢了。

4

2 回答 2

1

我已经编译并仔细调试了您的代码。如果您只打算在2^k*2^k 的矩阵上使用此函数,那么这 2 个修改将有所帮助。

第一的:

for(i=srC; i< endR; i++) {
    for(j=scC;j< endC;j++) {
        for(k=0; k<newDim; k++) 
            /*c[i][j] += a[i][k]*b[k][j];*/
            c[i][j] += a[i][scA+k] * b[srB+k][j];
    }
}

第二:

myRecMat(MatrixA,MatrixB,MatrixC,srA,scA,srB,scB,srC,scC,blocks,newDim);
myRecMat(MatrixA,MatrixB,MatrixC,srA,scA+newDim,srB+newDim,scB,srC,scC,blocks,newDim);
myRecMat(MatrixA,MatrixB,MatrixC,srA,scA,srB,scB+newDim,srC,scC+newDim,blocks,newDim); 
/*myRecMat(MatrixA,MatrixB,MatrixC,srA,scA+newDim,srB+newDim,scB,srC+newDim, scC,blocks,newDim);*/
myRecMat(MatrixA,MatrixB,MatrixC,srA,scA+newDim,srB+newDim,scB+newDim,srC, scC+newDim,blocks,newDim);
myRecMat(MatrixA,MatrixB,MatrixC,srA+newDim,scA,srB,scB,srC+newDim,scC,blocks,newDim);
myRecMat(MatrixA,MatrixB,MatrixC,srA+newDim,scA+newDim,srB+newDim,scB,srC+newDim,scC,blocks,newDim);
/*myRecMat(MatrixA,MatrixB,MatrixC,srA+newDim,scA+newDim,srB,scB+newDim,srC+newDim,scC+newDim,blocks,newDim);*/
myRecMat(MatrixA,MatrixB,MatrixC,srA+newDim,scA,srB,scB+newDim,srC+newDim,scC+newDim,blocks,newDim);
myRecMat(MatrixA,MatrixB,MatrixC,srA+newDim,scA+newDim,srB+newDim,scB+newDim,srC+newDim,scC+newDim,blocks,newDim);
于 2013-07-01T11:21:56.413 回答
0

我相信您的问题不在于您的方法的实现,而在于浮点运算的精度损失。有时人们可能会认为这种不精确性可以忽略不计,但是当我们对浮点变量进行密集运算时,例如您的三重嵌套循环,这些不精确性变得很重要。

解决此问题的一种方法是缩放浮点数,使它们“丢失”小数部分。也就是说,例如,如果你知道你的矩阵不会有超过两位小数的数字,那么将它们全部乘以 100 并得到它们的整数表示。然后对整数进行算术运算(这是精确的),最后得到结果的浮点表示并将其除以 100。

希望这可以帮助。

于 2013-07-01T09:16:46.020 回答