2016-11-20 245 views
2

这是我第一次使用SO。对不起我的英语,但我会努力尽我所能,并完全为了您的理解,用我的大学任务来描述我的问题。我相信我的问题是更多的代码和数组相关,而不是数学。如何连续(连贯地)在C++内存中存储三维数组?

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

因此一些小的解释和公式来理解问题更好:

  1. 我有在每个轴上的N + 1个点的立方体(与数字从Ñ
  2. 让我小号 = MPI_size的亲总数与行列正如事实从S-1
  3. 我做小号平行区域使切片垂直于Y轴(与固定Ĵ号码)。我的意思是指数对应x轴,j到y和k到z照常。
  4. 所以现在与从0到S-1个等级的每个进程负责P =(N + 1)/ s的在我的Y轴点:从秩* P秩* p + p-1
  5. 现在我遇到了创建三个大小为[N + 1] [p] [N + 1]的阵列的问题。三,因为在每一步的计算我使用的值从前一个时间步和从“双前(先前的前)”(对不起,我不知道怎么说正确的:))

我试图这样做只是想:

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轴的,并且将这些阵列放置在内存中将会是一个大问题

同样我们并不需要全部N + 1点在Y轴上,正如我先做的那样,只是p其中每个过程都可以。由于内存问题是非常实际的(最大N在一些测试将在1536左右。我们给出了测试资源非常少)

于是,他提出了这样做的:(他垂直于X轴做并行片,而不是Y轴从我和记数到N-1和不从到ň作为我来说,这不是什么大问题,但是这个代码是某种魔术对我来说,我不明白它完全反正。)

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 
    } 
} 

请有人试着理解这种方法,并解释什么来代替“???”。或者其他更好的解决方案。

而且我的队友告诉记者,这将是可以简单地写U [i] [j] [k]的代码但是我不知道我是否有ķ指数与这样definiton是否我需要改变我所有的计算语法。

对不起,有这么大的解释和问题。我真的不想自己理解它,并很快解决它。但现在我被卡住了。

同时粘贴一个立方体的小图像和红色的标记图层,用于一些简单的vizualization。

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

+2

http://www.boost.org/doc/libs/1_61_0/libs/multi_array/doc/user。 html –

+0

在你发布的第二个代码中,你没有足够的“层次”(不知道别的怎么说)。它应该是:float ***u; u = new float**[N + 1];等 –

+0

对于访问您的单维数组,假设您的大小是x = 2,y = 2和z = 2。访问变成:[(i * y * z)+(j * y) + k]。 –

回答

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; 
} 
+0

为什么你使用'operator()'进行索引而不是'[...]'?它违背了每个C++约定(和其他语言),看起来像一个正常的函数调用。 –

+0

因为operator []只能带一个参数。我没有想太多,但也许可以使用operator [],但是现在我想到的每个解决方案都比operator()更复杂和/或更慢。 – WPomier

+0

啊 - 好点。我可能只会使用返回'T&'的方法 - 但它基本上与您的操作符重载相同。差异是学术的。 :)感谢您的代码。 –