我正在尝试使用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
谁能指出我做错了什么?这是指数问题吗?请我今天真的需要解决这个问题,否则我将不及格。我花了无数个小时才完成这项工作。
好的你是对的!现在我有一个分段错误,但找不到它!用新版本取代了代码
答案 0 :(得分:2)
您的程序有几个我可以看到的问题。您包含的错误消息表示此调用中未分配的接收缓冲区:
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实现和编译器手册使用适当的文档。
答案 1 :(得分:0)
我已经解决了这个问题,现在它正确地计算了迭代次数,使用相同的矩阵证明了串行程序。这是一个分配和索引问题。感谢前面的回答,非常有帮助。
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
答案 2 :(得分:0)
您的程序存在严重问题,您可能会收到错误的结果。变量s声明为整数,而它被赋予非整数值。将其重新声明为双精度以获得正确的结果。 (发布给那些复制此代码的人)