1

次のようなループがあります。

do j=1,100
    do i=1,1000 
      combined_array(i,j)=combined_array(i,j-1)
      call foo(combined_array(i,j))
    enddo
enddo

subroutine foo(x)
    x= somefunction(x)
end subroutine foo

計算を分割したいのですが、列に依存関係があります。そこにない場合は、タスクを列に分割し、allgather を使用できます ( 2D 配列を列ごとに分割し、allgather を使用します)。このループでは、タスクを行に分割できますが、allgather を使用して結果を結合するにはどうすればよいですか? 各ランクが取得するチャンクがメモリ内で連続していない

4

1 に答える 1

2

MPI は、このような種類の問題に対してストライド ベクトル型を提供します。このような型は、列の高さの合計に等しいストライドと、サブブロック内の行数に等しいブロック サイズを使用して作成します。また、この型には、行の列数と等しい数を指定します。具体的な例を次に示します。行と列REALを含む行列があり、各プロセスが行を含むサブブロックを保持しているとします。次に、次のようにします。nrncnr1

integer :: rowtype

call MPI_TYPE_VECTOR(nc, nr1, nr, MPI_REAL, rowtype, ierr)
call MPI_TYPE_COMMIT(rowtype, ierr)

row で始まるサブブロックにデータを受け取りたいとしましょうmyrow。この新しいタイプを使用すると、次のことが簡単にできます。

call MPI_RECV(array(myrow,1), 1, rowtype, src, tag, &
              MPI_COMM_WORLD, status, ierr)

それはそのように動作します-サブブロックのトップレフ要素の提供されたアドレス(つまり、array(myrow,1))から開始nr1して、受信したメッセージから要素を配置し、次にnr - nr1の要素をスキップし、さらに要素を配置し、再び要素をスキップするなど、時間を繰り返します.arraynr1nr - nr1nc

しかし、ここで問題があります。rowtype型の範囲はnc*nr要素になります。MPI_(ALL)GATHERV()タイプ エクステントの倍数、つまりnc*nr、この制限を克服するために、MPI では を使用して型の範囲を人為的に変更できますMPI_TYPE_CREATE_RESIZED。型を取り、同じ型マップを持つ新しい型を構築します (たとえば、古い型と同じ「レシピ」を使用してメモリ内の要素をレイアウトします) が、型の範囲に依存するオフセットやその他のものを計算する場合、MPI は実際の値の代わりにユーザーが提供した値を使用します。あなたがする必要があるのは、型の要素のmyrow範囲と等しくなるように範囲を変更することですnr1MPI_REAL. これは次のように行われます。

integer(kind = MPI_ADDRESS_KIND) :: lb, extent
integer :: rowtype_resized

call MPI_TYPE_GET_EXTENT(MPI_REAL, lb, extent, ierr)
extent = extent * nr1
call MPI_TYPE_CREATE_RESIZED(rowtype, 0, extent, rowtype_resized, ierr)
call MPI_TYPE_COMMIT(rowtype_resized, ierr)

行と列rowtype_resizedのサブブロックを受け取るために を使用できるようになりましたが、 の合計サイズの倍数だけでなく、複数の大きな任意の行から開始するようにそれらを配置できます。その後、次のように続行できます。nr1ncarraynr1array

call MPI_ALLGATHER(smallarray, nr1*nc, MPI_REAL, &
                   array, 1, rowtype_resized, MPI_COMM_WORLD, ierr)

smallarrayこれにより、小さな配列(nr1行とnc列のそれぞれ) の内容が大きな配列array(nr1 * #processes行と列のそれぞれ)に集められncます。

さらに柔軟に、 の代わりに 1 のブロック長で vector 型を登録することもできますnr1。これにより、単一の行を送信できます。次に、1 つのMPI_REAL要素の範囲でサイズ変更された型を作成し、MPI_(ALL)GATHERV異なるサイズのサブブロックを収集するために使用できます。

少しトリッキーであることはわかっていますが、いずれ MPI の型システムを習得する方法を学ぶことができます。

于 2012-07-20T20:40:23.140 に答える