【问题标题】:Jacobi Iteration in Fortran and MPIFortran 和 MPI 中的 Jacobi 迭代
【发布时间】:2013-02-12 14:41:14
【问题描述】:

我正在尝试使用 jacobi 迭代解决 ax=b,我的串行代码工作正常,但 MPI 版本甚至无法运行。谁能帮帮我?

系列

program jacobis

implicit none

integer, parameter :: n=10
integer :: i,j,k,ni,s,seed
double precision :: tol,t1,t2,sig
double precision, dimension(0:n-1,0:n-1) :: A
double precision, dimension(0:n-1) :: B, x, xb, buff

ni=1000

seed=time()
call srand(seed)

do i=0, n-1
  do j=0, n-1
    A(i,j)=rand(0)
    B(i)=rand(0)
  end do
end do

do i = 0, n-1
 A(i,i) = sum(A(i,:)) + 1
enddo

!do i=0,n-1
 !A(i,i)=4
!end do  

print *, "a", A
print *, "b", B

x=B
call cpu_time(t1)
do k=1,ni
 xb=x
 do i=0,n-1
    s=0
    do j=0,n-1
    if (j/=i) then
         s=s+A(i,j)*xb(j)
        endif
    end do
    x(i)=(B(i)-s)/A(i,i) 

   sig=(x(i)-xb(i))*(x(i)-xb(i))
   tol=tol+sig
   tol=sqrt(tol)
 end do


 print *, "x", x

 !print *, "tol=", tol

 print *, "iter =",k

 if (tol<1.000001) EXIT
 if (k==(ni-1)) then
    print *, "Numero Maximo de Iteracoes" 
    EXIT
 endif
end do

 call cpu_time(t2)
 print *, "t=",t2-t1


end

MPI 版本

program jacobis

use mpi
implicit none

integer, parameter :: n=2
integer :: i_local,i_global,j,k,ni,s,m
double precision :: tol,t,t2,sig
double precision, dimension(:,:), ALLOCATABLE :: A_local
double precision, dimension(:), ALLOCATABLE :: B_local, x_local, x_temp1,x_temp2,x_old,x_new, buff
INTEGER, DIMENSION (MPI_STATUS_SIZE) :: STATUS
integer :: rank,procs,tag,ierror


CALL MPI_INIT(ierror)
CALL MPI_COMM_RANK(MPI_COMM_WORLD,rank,ierror)
CALL MPI_COMM_SIZE(MPI_COMM_WORLD,procs,ierror)

ni=100
m=n/procs

ALLOCATE (A_local(0:n-1,0:n-1))
ALLOCATE (B_local(0:m-1))
ALLOCATE (x_temp1(0:m-1))
ALLOCATE (x_temp2(0:m-1))

A_local=0
B_local=2

do i_global=0,n-1
 A_local(i_global,i_global)=2
end do  

CALL MPI_ALLGATHER(B_local, m, MPI_DOUBLE, x_temp1, m, MPI_DOUBLE, MPI_COMM_WORLD,ierror)

x_new=x_temp1
x_old=x_temp2

print *, "a", A_local
print *, "b", B_local


t=mpi_wtime()
do k=1,ni
 x_old=x_new
 do i_local=0,m-1
    i_global=i_local+rank*m 
    !x_local(i_local)=b_local(i_local)
    s=0
    do j=0,n-1
    if (j/=i_local) then
         s=s+A_local(i_local,j)*x_old(j)
        endif
    end do
    x_local(i_local)=(B_local(i_local)-s)/A_local(i_local,i_global) 

 end do
 CALL MPI_ALLGATHER(x_local,m, MPI_DOUBLE, x_new, m, MPI_DOUBLE, MPI_COMM_WORLD,ierror)

 do i_global=0,n-1
   sig=(x_new(i_global)-x_old(i_global))*(x_new(i_global)-x_old(i_global))
   tol=tol+sig
   tol=sqrt(tol)
 end do

 print *, "x", x_local

 print *, "tol=", tol

 print *, "iter =",k

 if (tol<1.000001) EXIT
 if (k==(ni-1)) then
    print *, "Numero Maximo de Iteracoes" 
    EXIT
 endif
end do

 t2=mpi_wtime()-t;
 print *, "t=",t2

CALL MPI_FINALIZE(ierror)
end

谁能指出我做错了什么?是索引问题吗?请我今天真的需要解决这个问题,否则我会不及格。我在这上面花费了无数个小时,但无法让它发挥作用。

好吧,你是对的!现在我有一个分段错误,但找不到它!已将代码替换为新版本

【问题讨论】:

  • 在赋值表达式的 LHS 上仍有未分配的数组。你用的是什么编译器?使用-O0 -g -C 标志编译以获取错误消息,其中包含有关问题的更多提示。因为这是一个班级作业,我们无法调试您的代码,而只能给出错误以及如何进行的提示。祝你好运。

标签: matrix fortran mpi


【解决方案1】:

您的程序有几个我可以看到的问题。您包含的错误消息表明此调用中有一个未分配的接收缓冲区:

CALL MPI_ALLGATHER(B_local, m, MPI_DOUBLE, x_temp1, m, MPI_DOUBLE, MPI_COMM_WORLD)

数组x_temp1,接收缓冲区,在此上下文中使用前需要分配。

解决这个问题只会让你走得更远,而且你会得到一个信息量较少的分段错误。在 MPI 实现中查找 MPI_AllGather 的正确用法会很有用。大多数 MPI 例程的末尾都有一个整数错误状态参数:

MPI_ALLGATHER(SENDBUF, SENDCOUNT, SENDTYPE, RECVBUF, RECVCOUNT,
        RECVTYPE, COMM, IERROR)
    <type>    SENDBUF (*), RECVBUF (*)
    INTEGER    SENDCOUNT, SENDTYPE, RECVCOUNT, RECVTYPE, COMM,
    INTEGER    IERROR

这应该可以帮助您完成任务。确保分配您使用的所有 allocatable 数组,并为您的 MPI 实现和编译器手册使用适当的文档。

【讨论】:

    【解决方案2】:

    我已经解决了这个问题,现在它可以正确计算迭代,串行程序使用相同的矩阵证明了这一点。这是一个分配和索引问题。感谢之前的回答,很有帮助。

    program jacobis
    
    use mpi
    implicit none
    
    integer, parameter :: n=1000
    integer :: i_local,i_global,j,k,ni,s,m,seed
    double precision :: tol,t,t2,sig
    double precision, dimension(:,:), ALLOCATABLE :: A_local
    double precision, dimension(:), ALLOCATABLE :: B_local, x_local, x_temp1,x_old,x_new, buff
    INTEGER, DIMENSION (MPI_STATUS_SIZE) :: STATUS
    integer :: rank,procs,tag,ierror
    
    
    CALL MPI_INIT(ierror)
    CALL MPI_COMM_RANK(MPI_COMM_WORLD,rank,ierror)
    CALL MPI_COMM_SIZE(MPI_COMM_WORLD,procs,ierror)
    
    ni=1000
    m=n/procs
    
    ALLOCATE (A_local(0:n-1,0:n-1))
    ALLOCATE (B_local(0:n-1))
    ALLOCATE (x_local(0:n-1))
    ALLOCATE (x_temp1(0:n-1))
    ALLOCATE (x_new(0:n-1))
    
    !A_local=23
    !B_local=47
    
    seed=time()
    call srand(seed)
    
    do k=0, n-1
     do j=0, n-1
        A_local(k,j)=rand(0)
        B_local(k)=rand(0)
     end do
    end do
    
    do i_global = 0, m-1
     A_local(i_global,i_global) = sum(A_local(i_global,:)) + n
    enddo
    
    CALL MPI_ALLGATHER(B_local, m, MPI_DOUBLE, x_temp1, m, MPI_DOUBLE, MPI_COMM_WORLD,ierror)
    
    x_new=x_temp1
    
    print *, "a", A_local
    print *, "b", B_local
    
    
    t=mpi_wtime()
    do k=1,ni
     x_old=x_new
     do i_local=0,m-1
        i_global=i_local+rank*m 
        !x_local(i_local)=b_local(i_local)
        s=0
        do j=0,n-1
        if (j/=i_local) then
             s=s+A_local(i_local,j)*x_old(j)
            endif
        end do
        x_local(i_local)=(B_local(i_local)-s)/A_local(i_local,i_global) 
     end do
     CALL MPI_ALLGATHER(x_local,m, MPI_DOUBLE, x_new, m, MPI_DOUBLE, MPI_COMM_WORLD,ierror)
     do j=0,n-1
       sig=(x_new(j)-x_old(j))*(x_new(j)-x_old(j))
       tol=tol+sig
       tol=sqrt(tol)
     end do
    
     print *, "x", x_local
    
     print *, "tol=", tol
    
     print *, "iter =",k
    
     if (tol<1.01) EXIT
     if (k==(ni-1)) then
        print *, "Numero Maximo de Iteracoes" 
        EXIT
     endif
    end do
    
     t2=mpi_wtime()-t;
     print *, "t=",t2
    
    CALL MPI_FINALIZE(ierror)
    end
    

    【讨论】:

    • 很高兴您解决了问题。请注意,您可以单击复选标记以接受任一正确答案。
    • 考虑在@IRO-bot 的答案上单击复选标记,这可以帮助您解决问题(不是您自己根据他的建议提出的解决方案)。
    【解决方案3】:

    您的程序存在严重问题,您可能会得到错误的结果。变量 s 被声明为整数,而它被分配了非整数值。将其重新声明为双精度以获得正确的结果。 (为曾经复制此代码的人发布)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-08
      • 2018-10-13
      • 2014-03-07
      • 2012-01-24
      • 2011-01-16
      • 1970-01-01
      • 2020-07-16
      • 2020-09-07
      相关资源
      最近更新 更多