3

C++ コードの配列の内容を fortran 90 コードに送信できるかどうかを確認しようとしています。Intel 11.1.072 コンパイラを使用してビルドされた openmpi 1.4.3 を使用しています。これらは、Linux バージョン 2.6.18-108chaos (mockbuild@chaos4builder1) (gcc バージョン 4.1.2 20080704 (Red Hat 4.1.2-48)) にインストールされます。

C++ 側は次のとおりです。

# include <cstdlib>
# include <iostream>
# include <mpi.h>
using namespace std;

void printarray (float arg[], int length) {
   for (int n=0; n<length; n++)
    cout << arg[n] << " ";
  cout << "\n";
}

int main(int argc, char *argv[] ){
   float a[10];
   int myrank,i;
   MPI::Init ( argc, argv );
   myrank=MPI::COMM_WORLD.Get_rank();
   cout << "rank "<<myrank<<" is c++ rank."<<std::endl;
   for (i=0;i<10;i++){
      a[i]=10.0;
   }
   printarray(a,10);
   MPI::COMM_WORLD.Send(&a[0],1,MPI::DOUBLE_PRECISION,1,100);
   MPI::Finalize();
}

f90 側は次のとおりです。

program main
implicit none
include "mpif.h"
integer:: ierr,stat(MPI_STATUS_SIZE)
real(8):: a(10)

call mpi_init(ierr)
a=0
print*,a
call mpi_recv(a(1),10,MPI_DOUBLE_PRECISION,0,100,MPI_COMM_WORLD,stat,ierr)
print*,a
call mpi_finalize(ierr)
end program

2 つのコードをコンパイルした後、次のように実行します。

$mpirun -n 1 *c_executable* : -n 1 *fortran_executable* > output

Fortran 側で取得した数値は 10.0 ではありません。

4

3 に答える 3

4

実際、MPI 標準には言語の相互運用性に関する規定があります。MPI 2.2 ドキュメントの 16.3 節全体が、Fortran と C 間の言語の相互運用性に専念しています。

§16.3.10 言語間コミュニケーション

MPI での通信のタイプ マッチング ルールは変更されていません。送信される各アイテムのデータ型仕様は、型シグネチャで、このアイテムを受信するために使用されるデータ型仕様と一致する必要があります (型の 1 つが である場合を除くMPI_PACKED)。また、型がMPI_BYTEまたはでない限り、メッセージ項目の型は、対応する通信バッファー位置の型宣言と一致する必要がありますMPI_PACKED。これらのルールに準拠している場合、言語間コミュニケーションが許可されます。

次に、Fortran コードからメッセージを送信し、それを C コードで受信するために同じ構造化データ型が使用される例を示します。この型は、C コードが Fortran コードに属するバッファにデータを受信できるように構築されていますが、質問により関連するのは、C コードが Fortran から構築されたデータ型を使用することMPI_REALです。C 関数で Fortran データ型を使用すること、およびその逆は、理にかなっていれば完全に合法です。

§16.3.6 MPI 不透明オブジェクト - データ型

... ある言語で定義されたデータ型が別の言語の通信呼び出しに使用される場合、送信されるメッセージは、最初の言語から送信されるメッセージと同じになります。同じ通信バッファーがアクセスされ、同じ表現が使用されます。必要に応じて変換が実行されます。すべての定義済みデータ型は、どの言語のデータ型コンストラクターでも使用できます。データ型がコミットされている場合は、任意の言語での通信に使用できます。

MPI_REAL(およびのような事前定義された MPI データ型MPI_DOUBLEはコミットされます)

逆に、一方に Fortran データ型を使用し、もう一方に C データ型を使用することは許可されていますが、移植可能ではないと見なされます。

§16.3.10 言語間コミュニケーション

... MPI 実装は、これらの型一致規則を弱め、メッセージを Fortran 型で送信し、C 型で受信し、それらの型が一致する場合はその逆を許可する可能性があります。つまり、Fortran の型INTEGERが C の型と同じであるint場合、MPI 実装では、データを datatype で送信し、datatypeMPI_INTEGERで受信することができますMPI_INTただし、そのようなコードは移植できません。

(私のものを強調)

に変更REAL(8)DOUBLE PRECISIONてもコードの移植性は向上しません。Fortran 標準はDOUBLE PRECISION型の表現について何も保証していないためです。これは、1 種類の型、つまり倍精度の種類DOUBLE PRECISIONの代替指定子であり、10 進精度が高くなければならないことを示しているだけです。REALデフォルトのリアルよりも。REAL(8)のデータ型での送信MPI_DOUBLE_PRECISIONは移植性がありません。代わりに、移植可能なプログラムはSELECTED_REAL_KINDFortran の組み込み関数を一緒に使用しMPI_Type_create_f90_realて、一致する MPI データ型を登録します。

私見の最良の選択肢は、C と Fortran の間の言語の相互運用性に依存し、両側で同じデータ型に固執することです。使用しているコンパイラ スイートは十分に新しいため、ISO_C_BINDINGFortran のメカニズムを使用して、C と互換性のある getREALおよびkind を取得INTEGERし、Fortran 呼び出しで C データ型を使用できます。例えば:

USE, INTRINSIC :: ISO_C_BINDING
REAL(C_DOUBLE), DIMENSION(10) :: darray
INTEGER(C_INT) :: ival
...
CALL MPI_SEND(darray, 10, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, ierr)
CALL MPI_BCAST(ival, 1, MPI_INT, 0, MPI_COMM_WORLD, ierr)
...
于 2012-08-14T11:07:41.563 に答える
1

はい、できます。主な問題は、C++ コードでは、a配列がfloatdouble ではなく type であることです。

また、これらの not-double のうち 10 個ではなく 1 個しか送信していません。これMPI_RECV()は引き続き機能しますが、もちろん、他の 9 つの値は設定されません。

他に注意すべきことはMPI_DOUBLE、C/C++ およびMPI_DOUBLE_PRECISIONFortran で使用する必要があることです。それらは同じである必要はなく、実際MPI_DOUBLE_PRECISION、C での の使用は定義されていないと思います。

また、一般的ではあるが標準的ではないdouble precisionではなく、fortran プログラムで使用することをお勧めします。real(8)

原則として、2 つのプログラムを実行しているマシンでの浮動小数点数のエンコーディングについて、不均一性について心配する必要さえありますが、ほとんどの場合、これは問題ではありません。

于 2012-08-14T01:14:29.640 に答える