在具有连续内存的c++中分配动态2D/3D数组

zphenhs4  于 2023-03-05  发布在  其他
关注(0)|答案(2)|浏览(166)

我需要在c中动态分配2D/3D数组。我希望这些数组具有连续的内存,以便使用MPI发送/接收。有没有关于如何动态分配2D/3D矩阵的建议?并且能够有效地访问/变异这些矩阵的元素??我目前使用C模板来管理矩阵。我在下面展示了一个3D案例的小片段。据我所知,这并不是连续分配内存。

template <class Type>
class Matrix
{

  private:

    // size of matrix
    int Nx_ = 0;
    int Ny_ = 0;
    int Nz_ = 0;

    // matrix
    Type*** A3_;

  public:

    // constructor
    Matrix(int Nx, int Ny, int Nz)
    {

      Nx_ = Nx; 
      Ny_ = Ny;
      Nz_ = Nz;

      A3_ = new Type**[Nx];

      for (int i = 0; i < Nx; i++)
      {

        A3_[i] = new Type*[Ny];
        for (int j = 0; j < Ny; j++)
        {
          A3_[i][j] = new Type[Nz];
        }

      }

    }

    // insert value 
    void put(int i, int j, int k, Type a) 
    {
      A3_[i][j][k] = a;
    }

    // get value 
    Type get(int i, int j, int k) 
    {
      return A3_[i][j][k];
    }

};

许多帖子推荐使用1D向量,然后使用索引数学访问元素。

// get value 
Type get(int i, int j, int k) 
{
   int NxNy=Nx_*Ny_;
   return Vec[i + j * Ny_ + k * NxNy];
}

我担心这需要4次手术(2次加法和2次乘法)。这在处理非常大的矩阵时似乎效率很低(~ 10亿个元素)使用三重嵌套的for循环。然而,考虑到我有限的c和c经验,我也想到,也许我上面的原始模板类也需要每个get/put进行多个操作,它们只是隐藏在C管理内存的“引擎盖”下。
总之:对于如何动态分配2D/3D矩阵,使用连续内存,并高效地访问其元素,有什么建议吗?

olmpazwi

olmpazwi1#

你找到的建议是正确的方向:使用平面1D数据结构和索引转换。
只有你的实现是次优的。我将只概述一般的想法,没有生产准备代码。考虑这样一个循环:

for (int k=0; k < K; ++k) {
    for (int j=0; j < J; ++j) {
        for (int i=0; i < I; ++i) {
             auto x = get(i,j,k);
             // ...
        }
    }
}

然后你需要安排你的元素,这样对于固定的KJ,所有的get(i,J,K)在内存中彼此接近。这就是你已经拥有的。现在你只需要一种快速访问它们的方法,这可以通过一个迭代器来实现。迭代器可以简单地是一个指针。你可以沿着这样的路线做一些事情:

for (int k=0; k < K; ++k) {
    for (int j=0; j < J; ++j) {
        for (Type* it = get_iterator(i,j); it != get_iterator(i,j+1); ++it) {
             auto x = *it;
             // ...
        }
    }
}

++it只是增加了一个指针,这和遍历元素一样便宜。

pbgvytdp

pbgvytdp2#

一维分配并使用索引转换。您可以比使用getset方法更优雅:

class Matrix {
private: double* data; int n;
public:
  double& operator()(int i,int j,int k) {
    return data[ i*n*n + j*n + k ];
}

这样就可以同时使用x = mymat(i,j,k)mymat(i,j,k) = x
我还要指出,您可以使用VectorSubarray数据类型来发送矩阵及其部分。

相关问题