2017-05-26 74 views
1

我正在尝试将可分配数组传递给子例程。当我使用How to pass allocatable arrays to subroutines in Fortran中提到的串行版本时,它工作正常。以下是我的代码串行版本。将可分配数组传递给Fortran中的MPI子程序

module test 
contains 
subroutine func(a,sqa,n) 
    implicit none 
    integer, intent(in) :: n 
    integer, intent(in), dimension(:,:) :: a 
    integer, intent(out), dimension(:,:):: sqa 
    !local variables 
    integer :: i,j 
    do i= 1,n 
     do j = 1,2 
      sqa(i,j) = a(i,j)*a(i,j) 
      print *, 'i',i, 'j', j,'sqa(i,j)',sqa(i,j) 
     end do 
    end do 
end subroutine func 
end module test 

program main 
use test 
implicit none 
integer :: n,i,j 
integer, dimension(:,:), allocatable :: a, sqa 
print *, 'enter no of rows' 
read *, n 

allocate(a(1:n,2)) 
allocate(sqa(1:n,2)) 
do i = 1,n 
    do j = 1, 2 
     a(i,j) = i +j 
     print *, 'i =',i,'j =',j, a(i,j) 
    end do 
end do 
call func(a, sqa,n) 
deallocate(a,sqa) 
end program main 

当我开始使用MPI实现,我的代码的并行版本是

module test 
contains 
subroutine func(a,sqa,istart,iend) 
    implicit none 
    integer, intent(in) :: istart, iend 
    integer, intent(in), dimension(:,:) :: a 
    integer, intent(out),dimension(:,:) :: sqa 
    !local variables 
    integer :: i,j 
    do i= istart, iend 
     do j = 1,2 
      sqa(i,j) = a(i,j)*a(i,j) 
      print *, 'i',i, 'j', j,'sqa(i,j)',sqa(i,j) 
     end do 
    end do 
end subroutine func 
end module test 

program main 
use test 
use mpi 
implicit none 
integer :: istart, iend, ierr,nproc, procnum, n,& 
points_per_thread, i,j 
integer, dimension(:,:), allocatable :: a, sqa 
integer,dimension(mpi_status_size) :: status 
call mpi_init(ierr) 
call mpi_comm_size(mpi_comm_world, nproc, ierr) 
call mpi_comm_rank(mpi_comm_world,procnum, ierr) 
if(procnum == 0)then 
    print *, 'enter no of rows' 
    read *, n 
end if 
call mpi_bcast(n,1,mpi_integer,0,mpi_comm_world, ierr) 
points_per_thread = (n + nproc - 1)/nproc 
istart = procnum*points_per_thread + 1 
iend = min((procnum + 1)*points_per_thread,n) 
print *, 'istart ', istart, 'iend', iend, 'procnum', procnum 
call mpi_barrier(mpi_comm_world, ierr) 
allocate(a(istart:iend,2)) 
allocate(sqa(istart:iend,2)) 
do i = istart,iend 
    do j = 1, 2 
     a(i,j) = i +j 
     print *, 'i =',i,'j =',j, a(i,j) 
    end do 
end do 
call mpi_barrier(mpi_comm_world, ierr) 
call func(a(istart:iend,:), sqa(istart:iend,:),istart,iend) 
deallocate(a,sqa) 
call mpi_finalize(ierr) 
end program main 

上面的代码给出了分段错误。我不明白这个原因。

接下来,当我在子程序FUNC我改变阵列和SQA的声明

integer,intent(in):: a(istart:iend,2) 
integer, intent(out)::sqa(istart:iend,2) 

现在它工作正常。我请求帮助我理解错误的原因。

+0

欢迎。对于apl Fortran问题,使用标签[tag:fortran]。 –

+0

在哪一行会崩溃?它打印什么?学习编译器的调试功能(例如gfortran中的'-g -fbacktrace -fcheck = all'和ifort中的'-g -traceback -check')。 –

+0

默认情况下,假定形状数组的下限为1。如果你希望它是istart,你需要声明它为'array(istart:)'。查看更多的重复链接。或者只是将环路更改为'i = 1,尺寸(a,1)' –

回答

1

假定的形状虚拟数组使得函数内部的实际参数的扩展可用,但不是它们的边界。如果函数内部需要实际边界,则必须使用显式形状的虚拟数组。

+0

我不明白你在说什么。 –

+0

现在我明白了,但不是很清楚。我们应该有一个副本。 –

+0

确实必须使用显式形状数组使绑定信息可用。 – francescalus

相关问题