繁体   English   中英

矩阵乘法作为列主要

[英]matrix multiplication as column major

我试图成为列专业,我似乎无法找到正确的公式! 我希望矩阵为1D。

假设我有这些矩阵:

A =

1 3

2 4

和B =

5 2 1

6 3 7

假设上述矩阵已经按列主要顺序存储。

我在尝试:

int main(int argc, const char* argv[]) {
  int rows=2;
  int cols=3;


  int A[rows*rows];
  int B[rows*cols];
  int res[rows*cols];

  A[0]=1;
  A[1]=3;
  A[2]=2;
  A[3]=4;


  B[0]=5;
  B[1]=2;
  B[2]=1;
  B[3]=6;
  B[4]=3;
  B[5]=7;

  /*A[0]=1;
  A[1]=2;
  A[2]=3;
  A[3]=4;


  B[0]=5;
  B[1]=6;
  B[2]=2;
  B[3]=3;
  B[4]=1;
  B[5]=7;
  */


  //multiplication as column major
 for (int i=0;i<rows;i++){
   for (int j=0;j<cols;j++){
     res[i+j*rows]=0;
     for (int k=0;k<rows;k++){
    res[i+j*rows]+=A[i+k*rows]*B[k+j*cols];


   }

   }
}



  for (int i=0;i<rows*cols;i++){
     printf("\n\nB[%d]=%d\t",i,res[i]);

  }

  return 0; 

 }

我没有得到正确的结果。

另外,我无法理解(在矩阵已经存储在列专业中的情况下),如何索引矩阵A和B.

 A[0]=1;

 A[1]=3;

...

要么

  A[0]=1;

  A[1]=2;
...

我不想转置矩阵然后使用行专业。

我想将数据作为专栏处理。

因为索引(如果作为列主要存储)将是不同的(因此,为了进行乘法将很重要)。

有两件事会导致你的困惑。

首先,您所连续的一维向量中的数据不是按照主要顺序排列,而是按行主顺序排列 ,就像C中二维连续数组的常规布局一样。线性一维指数在具有M行和N列( M × N )的矩阵中的行i和列j是:

A[i*N + j]      // row major
A[i + M*j]      // column major

“major”指的是使用两个嵌套循环顺序遍历数组时外部循环的维度:

n = 0;
for (i = 0; i < M; i++) {
    for (j = 0; j < N; j++) {
        printf("%8d", A[n++]);
    }
    printf("\n");
}

其次,使用两个维度的rowscolumns ,它们是结果矩阵的维度,这是令人困惑的,因为A的列数是rows

实际上,当将M × L矩阵AL × N矩阵B相乘以得到M × N矩阵C时,矩阵乘法中涉及三个不同的维度。 在你的情况下, ML碰巧都是2:

           L (k)   |     N (j)
                   |
                   |   5   2   1
   L (k)           |
                   |   6   3   7
                   |
  -----------------+-------------
                   |
            1   3  |  23  11  22
   M (i)           |
            2   4  |  34  16  30
                   |

括号中的字母是下面的代码用于迭代相应维度的变量。

现在,您可以以行主格式乘以矩阵:

    #define M 2
    #define N 3
    #define L 2

    int A[M * L] = {1, 3, 2, 4};
    int B[L * N] = {5, 2, 1, 6, 3, 7};
    int res[M * N];

    int i, j, k;

    for (i = 0; i < M; i++) {
        for (j = 0; j < N; j++) {
            res[j + i * N] = 0;

            for (k = 0; k < L; k++) {
                res[j + i * N] += A[k + i * L] * B[j + k * N];
            }
        }
    }

    for (i = 0; i < M * N; i++) printf("[%d] = %d\n", i, res[i]);

或以列主格式:

    #define M 2
    #define N 3
    #define L 2

    int A[M * L] = {1, 2, 3, 4};
    int B[L * N] = {5, 6, 2, 3, 1, 7};
    int res[M * N];

    int i, j, k;

    for (i = 0; i < M; i++) {
        for (j = 0; j < N; j++) {
            res[j * M + i] = 0;

            for (k = 0; k < L; k++) {
                res[j * M + i] += A[k * M + i] * B[j * L + k];
            }
        }
    }

    for (i = 0; i < M * N; i++) printf("[%d] = %d\n", i, res[i]);

输入和输出都在各自的矩阵表示中,当然在两种情况下不同。

你有什么想法

res[i+j*rows]+=A[i+k*rows]*B[k+j*cols];  

它会做什么?

ik变为1并且j变为2时,它将访问数组res, AB res, A

res[1+2*2]+=A[1+1*2]*B[1+2*3] = res[5]+=A[4]*B[7];  

这将调用未定义的行为,您可能会得到预期或意外的结果。

我想你需要这个:

res[i*rows+j] += A[i*rows + k] * B[j + k*cols]; 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM