如何在C ++的内存中连续(连贯地)存储三维数组?

时间:2016-11-20 11:10:19

标签: c++ arrays

这是我第一次使用SO的经历。对不起我的英语,但我会尽力而为,以便更好地理解我的大学课程中的问题。我确信我的问题是更多的代码和数组相关而不是数学。

我使用MPI,OpenMP以及大尺寸和网格尺寸来解决立方体中的数字3D波问题。现在我正在编写一个代码来在我们的大学超级计算机上执行它。

更好地理解问题的一些小解释和公式:

  1. 我的立方体在每个轴上有N + 1个点(数字从 0 N
  2. 让我拥有 = MPI_size 排名为 的流程总数0 s-1
  3. 我正在做 s 平行区域,使切片垂直于Y轴(具有固定的 j 数字)。我的意思是索引 i 像往常一样对应x轴,j到Y和k到Z.
  4. 所以现在每个进程的等级从0到s-1负责Y轴上的 p =(N + 1)/ s 点:来自 排名* p 排名* p + p-1
  5. 现在我在创建三个大小 [N + 1] [p] [N + 1] 的数组时遇到问题。三,因为在计算的每个步骤中,我使用来自前一时间步骤的值和来自"双前一个(以前的preios)" (对不起,我不知道怎么说:))
  6. 我试着这样做:

        for(int i = 0; i < N_p+1; i++) {
          u[i] = new double*[N_p+1];
          u_prev[i] = new double*[N_p+1];
          u_prev_prev[i] = new double*[N_p+1];
    
          for(int j = 0; j < N_p+1; j++) {
              u[i][j] = new double[N_p+1];
              u_prev[i][j] = new double[N_p+1];
              u_prev_prev[i][j] = new double[N_p+1];
    
              for(int k = 0; k < N_p+1; k++) { 
                  u[i][j][k] = 0.0;
                  u_prev[i][j][k] = 0.0;
                  u_prev_prev[i][j][k] = 0.0;
              }
          }
    }
    

    但我的朋友已经完成了这项任务,当我需要向其他进程发送消息或从其他进程接收消息时,我会遇到问题(因为我需要发送大小为(N + 1)^ 2的完整图层,与Y轴垂直。如果在内存中放置数组,这将是一个很大的问题。

    此外,我们首先不需要Y轴上的所有 N + 1 点,只需 p ,每个进程都可以。因为内存问题非常实际(在某些测试中,最大 N 将在1536左右。而且我们获得的测试资源非常少)

    所以他建议这样做:(他做了垂直于X轴的平行切片,而不是像我这样的Y轴和从 0 N-1 的数字而不是从 0 N 作为我,这不是一个大问题。但这段代码对我来说是一种魔力,我不明白它完全无论如何。)

    float* buffer = new float[N * N * (N/s) * 3];
    float ***u;
    
    for (int i = left; i < right; ++i) { 
      u[i] = new float*[N]; 
      for (int j = 0; j < N; ++j) { 
        u[i][j] = buffer + (i - left)*N*N + j*N; 
      } 
    }
    

    因此,当我的大脑着火并且很快就会爆炸时,我会尝试做类似的事情:

    float* buffer = new float[(N+1) * p * (N+1) * 3];
    float ***u;
    
    for (int i = 0; i <= N; ++i) {
    u[i] = new float*[p];
    //p = right-left+1
      for (int j = left; j <= right; ++j) {
        u[i][j] = buffer + ???; //SOS
      }
     }
    

    可以请某人尝试理解这种方法并解释要放置什么而不是&#34; ???&#34;。或者任何其他更好的解决方案。

    我的队友也告诉我可以在代码中简单地写一下 u [i] [j] [k] 但是我不确定我是否会 k 具有这种定义的索引以及是否需要更改所有计算语法。

    抱歉这么大的解释和问题。我真的不想自己理解它并尽快解决它。但是现在我被卡住了。

    还粘贴了一个立方体的小图像和带有红色的标记图层,用于简单的视觉化。

    the cube with 2 pictured layers that i will need to send just for example

1 个答案:

答案 0 :(得分:0)

我更喜欢在类中封装这类问题(OOP对吧?)。它更容易理解,可重用并且开销很小。任何类型的3D矩阵都是:

template<typename T>
class Matrix {
private:
    int _dimX, _dimY, _dimZ;
    T *_storage;
public:
    inline Matrix(int dimX, int dimY, int dimZ) {
        _dimX = dimX; _dimY = dimY; _dimZ = dimZ;
        _storage = new T[_dimX * _dimY * _dimZ];
    }
    inline ~Matrix() { delete _storage; }
    inline T* getStorage() const { return _storage; }
    inline T &operator()(int x, int y, int z) {
        return _storage[x * _dimX * _dimY + y * _dimY + z];
    }
};

使用它:

#include <iostream>
using std::cout;
using std::endl;

int main() {
    int xlen = 10, ylen = 5, zlen = 2;
    // Creating matrix of doubles
    Matrix<double> matrix(xlen, ylen, zlen);

    // Filling using contiguous memory array (to export)
    double *d = matrix.getStorage();
    int count = 0;
    for (int i = 0; i < xlen * ylen * zlen; i++)
        *d++ = ++count; // same as d[i] = ++count;

    // Using with indexes
    cout << "matrix(1,0,0) = " << matrix(1, 0, 0) << endl; // prints 51
    matrix(1, 0, 0) = 34;
    cout << "matrix(1,0,0) = " << matrix(1, 0, 0) << endl; // prints 34
    matrix(1, 0, 0)++;
    cout << "matrix(1,0,0) = " << matrix(1, 0, 0) << endl; // prints 35

    return 0;
}