我试着看看我是否可以将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
在我编译了两个代码后,我运行了
$mpirun -n 1 *c_executable* : -n 1 *fortran_executable* > output
我在fortran方面获得的数字不是10.0.
解决方法:
MPI标准确实具有语言互操作性的规定 – MPI 2.2文档的整个§16.3专用于Fortran和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 isMPI_BYTE
orMPI_PACKED
. Interlanguage communication is allowed if it complies with these rules.
然后继续展示一个示例,其中使用相同的构造数据类型从Fortran代码发送消息并在一段C代码中接收它.构造类型是为了允许C代码将数据接收到属于Fortran代码的缓冲区中,但与您的问题更相关的是C代码使用从Fortran MPI_REAL构造的数据类型.如果有意义的话,在C函数中使用Fortran数据类型(反之亦然)是完全合法的:
§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.
(已提交MPI_REAL和MPI_DOUBLE等预定义的MPI数据类型)
相反,允许一方使用Fortran数据类型,另一方使用C数据类型,但认为不可移植:
§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 typeint
, then an MPI implementation may allow data to be sent with datatypeMPI_INTEGER
and be received with datatypeMPI_INT
. However, such code is not portable.
(强调我的)
将REAL(8)更改为DOUBLE PRECISION不会增加代码的可移植性,因为Fortran标准不保证DOUBLE PRECISION类型的表示 – 它只说DOUBLE PRECISION是一种REAL类型的替代说明符,即双精度类,应该具有比默认实数更大的小数精度.使用MPI_DOUBLE_PRECISION数据类型发送REAL(8)不可移植.相反,可移植程序将使用Fortran的SELECTED_REAL_KIND内部函数和MPI_Type_create_f90_real来注册匹配的MPI数据类型.
恕我直言的最佳选择是依赖C和Fortran之间的语言互操作性,并坚持双方相同的数据类型.由于您的编译器套件足够新,您可以使用Fortran的ISO_C_BINDING机制来获取与C兼容的REAL和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)
...