在c++中为MPI使用平坦化3D数组

Flattening a 3D array in c++ for use with MPI

本文关键字:3D 数组 c++ 中为 MPI      更新时间:2023-10-16

谁能帮助使用MPI扁平化3D数组的一般格式?我想我可以通过使用(I +xlength*j+xlength*ylength*k)来获得数组1维,但是我在使用引用数组特定单元格的方程时遇到了麻烦。

我试着根据我有多少个处理器将代码分块,但是当我需要另一个处理器拥有的值时,我遇到了困难。是否有一种方法可以使这更容易(和更有效)使用鬼细胞或指针杂耍?

您至少有两个选择。比较简单的方法是声明一个预处理器宏来隐藏索引计算的复杂性,例如:

#define ARR(A,i,j,k) A[(i)*ylength*zlength+(j)*zlength+(k)]
ARR(myarray,i,j,k) = ARR(myarray,i+1,j,k) + ARR(myarray,i,j+1,k) + ...

这是笨拙的,因为宏只能处理固定前导维的数组,例如x ylength x zlength

更好的方法是使用所谓的掺杂向量。向量基本上是大数组的索引。你分配一个大小为xlength * ylength * zlength的大平面块来保存实际数据,然后创建一个索引向量(实际上是3D情况下的树)。在您的示例中,索引有两个级别:

  • 顶层,由指向
  • xlength指针组成。
  • 第二级,由xlength指针数组组成,每个数组包含指向内存中zlength元素块开始的ylength指针。

我们把顶级指针数组命名为A。然后A[i]是指向指针数组的指针,该指针数组描述i -th数据块。A[i][j]i指针数组的j的第一个元素,它指向data[i][j][0](如果data是一个3D数组)。dope向量的构造类似于这样:

double *data = new double[xlength*ylength*zlength];
double ***A;
A = new double**[xlength];
for (int i = 0; i < xlength; i++)
{
   A[i] = new double*[ylength];
   for (int j = 0; j < ylength; j++)
      A[i][j] = data + i*ylength*zlength + j*zlength;
}

Dope vector和普通数组一样容易使用,只是需要考虑一些特殊的因素。例如,A[i][j][k]将允许您访问data所需的元素。对dope vector的一个警告是,顶层由指向其他指针表的指针组成,而不是指向数据本身的指针,因此A不能用作&A[0][0][0]的快捷方式,A[i]也不能用作&A[i][0][0]的快捷方式。A[i][j]仍然等同于&A[i][j][0]。另一个警告是,这种形式的数组索引比普通的3D数组索引慢,因为它涉及指针跟踪。

有些人倾向于为数据和数据向量分配一个存储块。它们只是将索引放在分配块的开头,实际数据在后面。这种方法的优点是,处理数组就像删除整个内存块一样简单,而处理用上一节的代码创建的向量需要多次调用free操作符。