使用Intel Fortran+Intel MPI调用MPI_Bcast时为何报警告/错误?
问题现象
使用Intel Fortran + Intel MPI编译以下MPI广播示例代码时:
program mpi_broadcast_example use mpi implicit none integer :: ierr, rank, size, root integer :: a call MPI_Init(ierr) call MPI_Comm_rank(MPI_COMM_WORLD, rank, ierr) call MPI_Comm_size(MPI_COMM_WORLD, size, ierr) root = 0 if (rank == root) then ! Initialize the value of variable a on the root process a = 42 endif ! Broadcast the value of variable a from the root process to all other processes call MPI_Bcast(a, 1, MPI_INTEGER, root, MPI_COMM_WORLD, ierr) ! Output the received value of variable a on all processes write(*,*) 'Process', rank, ': Received a =', a call MPI_Finalize(ierr) end program mpi_broadcast_example
执行编译命令:
mpiifx test.f90 -o test -warn all
会出现警告:
test.f90(21): warning #8889: Explicit interface or EXTERNAL declaration is required. [MPI_BCAST]
call MPI_Bcast(a, 1, MPI_INTEGER, root, MPI_COMM_WORLD, ierr)
---------^
若将implicit none改为implicit none(type, external),则直接触发编译错误并终止编译。其他MPI子程序(如MPI_Init、MPI_Comm_rank)无此类警告/错误。
原因解释
这并非编译器Bug,而是Intel MPI的mpi模块中MPI_Bcast的接口特性导致的:
MPI_Bcast是通用(generic)子程序,对应MPI标准中不同数据类型的重载版本;- 当使用
implicit none(尤其是严格模式implicit none(type, external))时,Intel Fortran编译器要求所有外部子程序必须有显式接口或被声明为EXTERNAL; - 普通MPI子程序(如
MPI_Init)的显式接口在mpi模块中定义清晰,编译器可直接识别;但MPI_Bcast作为通用子程序,编译器在部分场景下无法自动匹配到对应具体接口,因此触发警告/错误。
解决方案
可以通过以下几种方式解决:
1. 使用mpi_f08模块替代mpi模块
mpi_f08是符合Fortran 2008标准的MPI接口,提供了更规范、完整的显式接口定义,能完美兼容Intel Fortran的严格检查:
program mpi_broadcast_example use mpi_f08 ! 替换为mpi_f08模块 implicit none(type, external) integer :: ierr, rank, size, root integer :: a call MPI_Init(ierr) call MPI_Comm_rank(MPI_COMM_WORLD, rank, ierr) call MPI_Comm_size(MPI_COMM_WORLD, size, ierr) root = 0 if (rank == root) then a = 42 endif call MPI_Bcast(a, 1, MPI_INTEGER, root, MPI_COMM_WORLD, ierr) write(*,*) 'Process', rank, ': Received a =', a call MPI_Finalize(ierr) end program mpi_broadcast_example
2. 显式声明MPI_Bcast为EXTERNAL
在代码中添加external MPI_Bcast声明,告知编译器该子程序为外部程序,跳过显式接口检查:
program mpi_broadcast_example use mpi implicit none(type, external) external :: MPI_Bcast ! 添加这一行 integer :: ierr, rank, size, root integer :: a ! 后续代码不变 call MPI_Init(ierr) call MPI_Comm_rank(MPI_COMM_WORLD, rank, ierr) call MPI_Comm_size(MPI_COMM_WORLD, size, ierr) root = 0 if (rank == root) then a = 42 endif call MPI_Bcast(a, 1, MPI_INTEGER, root, MPI_COMM_WORLD, ierr) write(*,*) 'Process', rank, ': Received a =', a call MPI_Finalize(ierr) end program mpi_broadcast_example
3. 指定具体的MPI_Bcast版本(不推荐)
如果不需要通用接口,可以直接调用针对整数类型的具体子程序MPI_Bcast_INTEGER(命名需参考Intel MPI文档),但这种方式灵活性差,仅适用于固定数据类型的场景。
总结
该问题不属于编译错误,是Intel MPI旧版mpi模块与Intel Fortran严格类型检查的兼容性问题,优先推荐使用mpi_f08模块来彻底解决。
内容的提问来源于stack exchange,提问作者yaguang liu

