Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在大矩阵中复制分片的高效算法_C++_Algorithm_Matrix_Linear Algebra - Fatal编程技术网

C++ 在大矩阵中复制分片的高效算法

C++ 在大矩阵中复制分片的高效算法,c++,algorithm,matrix,linear-algebra,C++,Algorithm,Matrix,Linear Algebra,我有N个方阵,所有这些方阵的大小都是MxM,它们必须复制到一个包含NxN矩阵的矩阵中,以对称的方式排列。上下两部分包含相同矩阵的转置版本,如本方案中所示 N=4 生成数据的算法最初只填充上一行和第一列,其余为空 m1 m2 m3 m4 m2'0 0 0 m3'0 0 0 m4'0 0 0 我想找到一个有效的索引方案,从已经填充的行元素开始填充所有大矩阵。记住m1…mn是大小为MxM的方阵,矩阵按列大顺序排列。矩阵不是那么大,所以不需要利用太多的局部性和缓存相关的东西 平凡算法

我有N个方阵,所有这些方阵的大小都是MxM,它们必须复制到一个包含NxN矩阵的矩阵中,以对称的方式排列。上下两部分包含相同矩阵的转置版本,如本方案中所示

N=4

生成数据的算法最初只填充上一行和第一列,其余为空

m1 m2 m3 m4
m2'0  0  0 
m3'0  0  0 
m4'0  0  0 
我想找到一个有效的索引方案,从已经填充的行元素开始填充所有大矩阵。记住m1…mn是大小为MxM的方阵,矩阵按列大顺序排列。矩阵不是那么大,所以不需要利用太多的局部性和缓存相关的东西

平凡算法如下所示,其中X是矩阵

  int toX = 0, fromX = 0, toY = 0, fromY = 0; 
  for (int i = 1; i < N; ++i) {
    for (int j = 1; j < N; ++j) {
      for (int ii = 0; ii < M; ++ii) {
        for (int jj = 0; jj < M; ++jj) {
          fromX = (i - 1) * dim + ii;
          fromY = (j - 1) * dim + jj;
          toX = i * dim + ii;
          toY = j * dim + jj;
          X(toX, toY) = X(fromX, fromY);
        } 
      }
    }
  }
inttox=0,fromX=0,toY=0,fromY=0;
对于(int i=1;i

您能找到更好的方法吗?

根据您的应用程序,可能不需要存储所有这些转置矩阵。如果m1是对称的,你甚至可以剔除m1矩阵的下半部分

事实上,把所有这些矩阵都放在一边,按块进行矩阵运算甚至是可行的(用标量进行加法和乘法比较简单,用向量进行乘法则要复杂一些)

如果您真的需要整个矩阵,您可以通过对角填充矩阵来获得略低的运算计数,即通过执行以下操作:

int toX = 0, fromX = 0, toY = 0, fromY = 0;

// m1 (note that this part can be sped up further if m1 is symmetric)

for (int ii = 0; ii<M; ii++){        
    for (int jj = 0; jj<M; jj++){
        fromX = ii;
        fromY = jj;
        toX = fromX;
        toY = fromY;
        for (int k=1; k<N; k++){            
            toX += dim;
            toY += dim;
            X(toX, toY) = X(fromX, fromY);
        }            
    }        
}    


// m2 to m(N-1)

for (int i = 2; i < N; i++){    
    for (int ii = 0; ii<M; ii++){        
        for (int jj = 0; jj<M; jj++){
            fromX = i*dim+ii;
            fromY = jj;
            toX = fromX;
            toY = fromY;
            for (int k=i; k<N; k++){            
                toX += dim;
                toY += dim;
                X(toX, toY) = X(fromX, fromY);
                X(toY, toX) = X(fromX, fromY);
            }            
        }        
    }    
}
inttox=0,fromX=0,toY=0,fromY=0;
//m1(注意,如果m1是对称的,这部分可以进一步加速)

对于(int ii=0;ii)大矩阵将填充从较小矩阵中提取的元素,其中前几列将包含第一个矩阵的所有元素,按行的主要顺序排列,我的理解正确吗?你没有说你的问题是什么。你当前的算法太慢了吗?我不明白你如何避免这样做(N-1)(N-1)(M)(M)另外,我认为你有一个输入错误:没有++ii或++jj。
int toX = 0, fromX = 0, toY = 0, fromY = 0;

// m1 (note that this part can be sped up further if m1 is symmetric)

for (int ii = 0; ii<M; ii++){        
    for (int jj = 0; jj<M; jj++){
        fromX = ii;
        fromY = jj;
        toX = fromX;
        toY = fromY;
        for (int k=1; k<N; k++){            
            toX += dim;
            toY += dim;
            X(toX, toY) = X(fromX, fromY);
        }            
    }        
}    


// m2 to m(N-1)

for (int i = 2; i < N; i++){    
    for (int ii = 0; ii<M; ii++){        
        for (int jj = 0; jj<M; jj++){
            fromX = i*dim+ii;
            fromY = jj;
            toX = fromX;
            toY = fromY;
            for (int k=i; k<N; k++){            
                toX += dim;
                toY += dim;
                X(toX, toY) = X(fromX, fromY);
                X(toY, toX) = X(fromX, fromY);
            }            
        }        
    }    
}