user1596782
user1596782

Reputation: 31

send mpi message from a c++ code to fortran 90 code

I am try to see if I can send the contents of an array in a c++ code to a fortran 90 code. I'm using openmpi 1.4.3 built using intel 11.1.072 compilers. They are installed on Linux version 2.6.18-108chaos (mockbuild@chaos4builder1) (gcc version 4.1.2 20080704 (Red Hat 4.1.2-48)).

Here is the c++ side:

# 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();
}

and here is the f90 side:

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

after I've compiled the two codes, I run with

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

The numbers I get on the fortran side are not 10.0.

Upvotes: 3

Views: 1269

Answers (3)

momba
momba

Reputation: 195

Here is a modified working version in C

#include <stdio.h>
#include <mpi.h>

main(int argc, char **argv) 
{
  int i,ierr, num_procs, my_id;
  double a[10];

  for (i=0;i<10;i++)
  {
    a[i]=10.0;
  }

  ierr = MPI_Init(&argc, &argv);

  printf(" Hello C Code\n"); 

  /**/
  ierr = MPI_Comm_rank(MPI_COMM_WORLD, &my_id);
  ierr = MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
  ierr = MPI_Send(&a[0],10,MPI_DOUBLE,1,100, MPI_COMM_WORLD);  


  ierr = MPI_Finalize(); 

}

Here is a modified working version in F

    program main
        use mpi

        implicit none
        integer:: ierr,stat(MPI_STATUS_SIZE)
        double precision:: a(10)

        call mpi_init(ierr)

        write(*,*)"Hello F Code"
        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

Upvotes: 1

Hristo Iliev
Hristo Iliev

Reputation: 74455

The MPI standard indeed has provisions for language interoperability - the whole §16.3 of the MPI 2.2 document is dedicated to language interoperability between Fortran and C.

§16.3.10 Interlanguage Communication

The type maching rules for communications in MPI anr not changed: the datatype specification for each item sent should match, in type signature, the datatype specification used to receive this item (unless one of the types is MPI_PACKED). Also, the type of a message item should match the type declaration for the corresponding communication buffer location, unless the type is MPI_BYTE or MPI_PACKED. Interlanguage communication is allowed if it complies with these rules.

Then it goes on to show an example where the same construced datatype is used to send a message from a Fortran code and to receive it in a piece of C code. The type is constructed so as to allow the C code to receive the data into a buffer that belongs to the Fortran code, but what is more relevant to your question is that the C code uses a datatype that was constructed from the Fortran MPI_REAL. Using Fortran datatypes in C functions and vice versa is perfectly legal if it makes sense:

§16.3.6 MPI Opaque Objects - Datatypes

... If a datatype defined in one language is used for a communication call in another language, then the message sent will be identical to the message that would be sent from the first language: the same communication buffer is accessed, and the same representation conversion is performed, if needed. All predefined datatypes can be used in datatype constructors in any language. If a datatype is committed, it can be used for communication in any language.

(predefined MPI datatypes like MPI_REAL and MPI_DOUBLE are committed)

On the contrary, using Fortran datatypes on the one side and C datatypes on the other is allowed but considered not portable:

§16.3.10 Interlanguage Communication

... MPI implementations may weaken these type matching rules, and allow messages to be sent with Fortran types and received with C types, and vice versa, when those types match. I.e., if the Fortran type INTEGER is identical to the C type int, then an MPI implementation may allow data to be sent with datatype MPI_INTEGER and be received with datatype MPI_INT. However, such code is not portable.

(emphasis mine)

Changing REAL(8) to DOUBLE PRECISION does nothing to increase the portablity of your code as the Fortran standard guarantees nothing about the representation of the DOUBLE PRECISION type - it only says that DOUBLE PRECISION is an alternative specifier for one kind of REAL type, namely the double precision kind, which should have greater decimal precision than the default real. Sending REAL(8) with a datatype of MPI_DOUBLE_PRECISION is not portable. Instead a portable program would use the SELECTED_REAL_KIND intrinsic of Fortran together with MPI_Type_create_f90_real to register a matching MPI datatype.

The best option IMHO is to rely on the language interoperability between C and Fortran and stick to the same datatypes on both sides. Since your compiler suite is recent enough, you can use the ISO_C_BINDING mechanism of Fortran to get REAL and INTEGER kinds, compatible with C, and use the C datatypes in the Fortran calls. For example:

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)
...

Upvotes: 4

Jonathan Dursi
Jonathan Dursi

Reputation: 50937

Yes, you can do this; the main problem is that in your C++ code, your a array is of type float, not double.

You're also only sending 1, not 10, of these not-doubles; the MPI_RECV() would still work, but of course the other 9 values wouldn't be set.

Something else that you should note is that you should use MPI_DOUBLE in C/C++, and MPI_DOUBLE_PRECISION in Fortran; they need not be the same, and in fact I imagine the use of MPI_DOUBLE_PRECISION in C is undefined.

You also probably want to use double precision in the fortran program rather than real(8), which is common but not standard.

In principle, you would even want to worry about heterogeneity, about the encoding of the floating point numbers on the machines running the two programs, but for most of us this isn't an issue.

Upvotes: 1

Related Questions