0

MPI を使用して 3D 配列を平坦化するための一般的な形式を手伝ってくれる人はいますか? (i+xlength*j+xlength*ylength*k) を使用するだけで 1 次元の配列を取得できると思いますが、配列の特定のセルを参照する数式を使用すると問題が発生します。

所有しているプロセッサの数に基づいてコードをチャンクに分割しようとしましたが、別のプロセッサが持っている値が必要になったときに苦労しました。ゴーストセルまたはポインタージャグリングを使用して、これをより簡単に (そしてより効率的に) する方法はありますか?

4

1 に答える 1

2

少なくとも 2 つのオプションがあります。より簡単な方法は、インデックス計算の複雑さを隠すプリプロセッサ マクロを宣言することです。次に例を示します。

#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 ylengthxなど) でしか機能しないからzlengthです。

それを行うためのより良い方法は、いわゆるドープベクターを使用することです。ドープ ベクトルは基本的に大きな配列へのインデックスです。実際のデータを保持するために 1 つの大きなフラット チャンクを割り当てxlength * ylength * zlengthてから、インデックス ベクトル (実際には 3D の場合はツリー) を作成します。あなたの場合、インデックスには2つのレベルがあります:

  • xlengthへのポインタで構成されるトップレベル
  • 第 2 レベル。xlengthポインターの配列で構成され、それぞれがメモリ内の要素ylengthのブロックの先頭へのポインターを含みます。zlength

最上位のポインター配列を呼び出しましょうA。次に、データの - 番目のスラブA[i]を記述するポインター配列へのポインターです。は( 3D 配列の場合)を指す - 番目のポインター配列の - 番目の要素です。ドープ ベクトルの構築は、次のように機能します。iA[i][j]jidata[i][j][0]data

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

ドープ ベクトルは、通常の配列と同じくらい簡単に使用できますが、いくつかの特別な考慮事項があります。たとえばA[i][j][k]、 の目的の要素にアクセスできますdata。ドープ ベクトルの 1 つの注意点は、トップ レベルが他のポインター テーブルへのポインターで構成され、データ自体へのポインターではないため、 のショートカットとして使用したり、Aのショートカットとして使用したりできないことです。Stillは と同等です。もう 1 つの注意点は、この形式の配列のインデックス付けは、ポインターの追跡を伴うため、通常の 3D 配列のインデックス付けよりも遅いということです。&A[0][0][0]A[i]&A[i][0][0]A[i][j]&A[i][j][0]

一部の人々は、データとドープ ベクトルの両方に 1 つのストレージ ブロックを割り当てる傾向があります。割り当てられたブロックの先頭にインデックスを配置するだけで、実際のデータはその後に続きます。この方法の利点は、配列の破棄がメモリ ブロック全体を削除するのと同じくらい簡単であることです。一方、前のセクションのコードで作成されたドープ ベクトルを破棄するには、freeオペレーターを複数回呼び出す必要があります。

于 2013-04-29T23:11:24.767 に答える