块矩阵乘法

7
我想执行一个分块矩阵乘法(将矩阵分成多个sxs矩阵并相应地乘以各个块)。我已经按照Hennesy架构书中的示例代码编写了以下代码:
for(int jj=0;jj<=(n/s);jj += s){
            for(int kk=1;kk<=(n/s);kk += s){
                    for(int i=1;i<=(n/s);i++){
                            for(int j = jj; j<=((jj+s-1)>(n/s)?(n/s):(jj+s-1)); j++){
                                    temp = 0;
                                    for(int k = kk; k<=((kk+s-1)>(n/s)?(n/s):(kk+s-1)); k++){
                                            temp += b[i][k]*a[k][j];
                                    }
                                    c[j][i] += temp;
                            }
                    }
            }
    }  

在这里,nxn是原始矩阵的大小。a、b矩阵的大小相同。我将a、b矩阵分成大小为sxs的块。在我的程序中,我将块大小设置为4。我将a、b的所有元素都设置为5,一个常量,n=1000。然而,我的结果值不正确。我在过去的两个小时里一直卡在这里。如果可能的话,请你帮我看看。书中的参考代码如下:

for (jj = 0; jj <= size; jj += N) {
    for (kk = 1; kk <= size; kk += N) {
        for (i = 1; i <= size; i++) {
            for (j = jj; j <= findMin(jj+N-1, size); j++) {
                temp = 0;
                for (k = kk; k <= findMin(kk+N-1, size); k++) {
                    temp += B[i][k] * A[j][k];
                }
                C[j][i] += temp;
            }
        }
     }
}  

在这里,s=N,size=n/s。

1
你能否将此简化为一个小样本代码,包含产生问题的输入,并解释你期望得到的答案是什么? - Shafik Yaghmour
投票关闭,因为这段代码为什么不起作用。 - Ciro Santilli OurBigBook.com
3个回答

7
for(int jj=0;jj<N;jj+= s){
        for(int kk=0;kk<N;kk+= s){
                for(int i=0;i<N;i++){
                        for(int j = jj; j<((jj+s)>N?N:(jj+s)); j++){
                                temp = 0;
                                for(int k = kk; k<((kk+s)>N?N:(kk+s)); k++){
                                        temp += a[i][k]*b[k][j];
                                }
                                c[i][j] += temp;
                        }
                }
        }
}

AxB 大小为 N


2
错误出现在这一行。您有:
 temp += b[i][k]*a[k][j];

您应该拥有:
 temp += b[i][k]*a[j][k];

相反,应该将其放在一个函数中,而不是这一行代码中:

如果您能够实现这一点,那将更好。

((jj+s-1)>(n/s)?(n/s):(jj+s-1));

谢谢。我把它放在那里是因为频繁调用函数对性能不利。还要感谢你指出了错误。 - Justin Carrey
2
@JustinCarrey “调用函数太多次对性能不利”这并不是正确的。应该先考虑可读性,只有在明显存在问题时才考虑性能。 - Andrei
完全同意@Andrei的观点。如果你真的很关心这个问题,可以使用关键字“inline”。顺便说一下,在这种情况下,编译器会自动为您进行内联处理,因此您甚至不需要做任何事情。 - Wilmer E. Henao

1
乍一看,我很惊讶看到0和1都作为起始索引,以及小于或等于的for循环终止测试。Fortran或Matlab代码的书籍有时会假定基于1的索引,而C/C++使用基于0的索引。
您也可以分别实现和/或测试内部的两个for循环,因为它们将用于单块矩阵乘法。
我建议保持findMin函数单独,而不是将其内联在循环测试中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接