将 MPI 消息从 C++ 代码发送到 Fortran 90 代码
send mpi message from a c++ code to fortran 90 code
我正在尝试查看是否可以将c ++代码中的数组内容发送到fortran 90代码。我使用的是使用英特尔 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 跨语言交流
MPI anr 中通信的类型缓存规则未更改:发送的每个项目的数据类型规范应在类型签名中与用于接收此项目的数据类型规范匹配(除非其中一种类型是
MPI_PACKED
)。此外,消息项的类型应与相应通信缓冲区位置的类型声明匹配,除非类型为MPI_BYTE
或MPI_PACKED
。如果符合这些规则,则允许跨语言交流。
然后,它继续展示一个示例,其中使用相同的构造数据类型从 Fortran 代码发送消息并以一段 C 代码接收它。构造该类型是为了允许 C 代码将数据接收到属于 Fortran 代码的缓冲区中,但与您的问题更相关的是 C 代码使用从 Fortran MPI_REAL
构造的数据类型。如果在 C 函数中使用 Fortran 数据类型,反之亦然,如果有意义,这是完全合法的:
§16.3.6 MPI 不透明对象 - 数据类型
。如果用一种语言定义的数据类型用于另一种语言的通信调用,则发送的消息将与从第一种语言发送的消息相同:访问相同的通信缓冲区,并在需要时执行相同的表示转换。所有预定义的数据类型都可以在任何语言的数据类型构造函数中使用。如果提交数据类型,则可以将其用于任何语言的通信。
(预定义的 MPI 数据类型(如 MPI_REAL
和 MPI_DOUBLE
)已提交)
相反,允许一方面使用 Fortran 数据类型,另一方面使用 C 数据类型,但认为不可移植:
§16.3.10 跨语言交流
。MPI 实现可能会削弱这些类型匹配规则,并允许使用 Fortran 类型发送消息并使用 C 类型接收消息,反之亦然,当这些类型匹配时。也就是说,如果Fortran类型
INTEGER
与C类型int
相同,那么MPI实现可以允许以数据类型MPI_INTEGER
发送数据,并以数据类型MPI_INT
接收数据。但是,此类代码不可移植。
(强调我的)
将REAL(8)
更改为 DOUBLE PRECISION
不会增加代码的可移植性,因为 Fortran 标准不保证DOUBLE PRECISION
类型的表示 - 它只说 DOUBLE PRECISION
是一种REAL
类型的替代说明符,即双精度类型,它应该比默认的 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)
...
是的,你可以这样做;主要问题是在你的C++代码中,你的a
数组是 float
类型,而不是双精度。
你也只发送这些非双精度值中的 1 个,而不是 10 个;MPI_RECV()
仍然有效,但当然其他 9 个值不会被设置。
你应该注意的另一件事是,你应该在 C/C++ 中使用 MPI_DOUBLE
,在 Fortran 中使用MPI_DOUBLE_PRECISION
;它们不需要相同,事实上,我想在 C 中使用 MPI_DOUBLE_PRECISION
是不确定的。
您可能还想在 fortran 程序中使用 double precision
而不是 real(8)
,这很常见,但不是标准的。
原则上,您甚至要担心异构性,担心运行这两个程序的机器上浮点数的编码,但对于我们大多数人来说,这不是问题。
这是 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 Coden");
/**/
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();
}
这是 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
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 代码在main()中运行,但在函数中出现错误
- 重新编译我们的FORTRAN代码并在C++中使用后,我们的system()或C_str()命令无法正常工作
- CPP -D 选项,用于预处理 Fortran 代码
- complex_Bessel_function库的编译——与Fortran代码的链接——mex文件
- 旧版本的Fortran做循环Manova代码
- 在C++和Fortran代码之间传递复数数组
- 当C代码调用Fortran子程序时,子程序顶部会出现分段错误
- 从QTCreator中调用QT的Fortran代码
- 将 MPI 消息从 C++ 代码发送到 Fortran 90 代码
- 混合 C、C++ 和 Fortran 中的代码
- 集成 Fortran 和 C++ 代码的查询
- Cmake配置文件,用于从FORTRAN代码调用的C++函数中调用C++代码
- 使用Visual Studio 2013和Intel Fortran编译c++ /C混合代码
- FORTRAN代码调用c代码时发生错误
- 从FORTRAN代码调用的c++函数调用c++函数
- 用内存中的Fortran数据调用C代码
- 我怎样才能使这个简单的fortran 90代码更快
- 使用C++代码从FORTRAN DLL调用函数
- Fortran 将字符*81 数组传递给 C/C++ 代码