fortran - Abnormal mpi behaviour for large array -
in following code of array summation give me correct answer, when use max_rows=10,100,1000,10000 , when use max_rows=100000 or more, getting abnormal answer , getting negative partial sum 1 of proces.
program sum_vector use mpi implicit none integer,parameter::max_rows=100000 integer::myrank,master=0,ierr,status(mpi_status_size),num_procs integer::i,rank,avg_rows_per_procs,sender integer::num_rows_to_send,num_rows_to_receive,start_row,end_row,partial_sum,total_sum,st1,st2 integer,allocatable::vector(:),vector2(:) allocate(vector(max_rows),stat=st1) allocate(vector2(max_rows),stat=st2) if(st1/=0 .or. st2/=0)then print*,'cannot allocate' stop end if call mpi_init(ierr) call mpi_comm_rank(mpi_comm_world,myrank,ierr) call mpi_comm_size(mpi_comm_world,num_procs,ierr) if (myrank==0)then i=1,max_rows vector(i)=i end avg_rows_per_procs=max_rows/num_procs rank=1,num_procs-1 start_row=rank*avg_rows_per_procs+1 end_row=start_row+avg_rows_per_procs-1 if (rank==num_procs-1)end_row=max_rows num_rows_to_send=end_row-start_row+1 call mpi_send(num_rows_to_send,1,mpi_int,rank,101,mpi_comm_world,ierr) call mpi_send(vector(start_row),num_rows_to_send,mpi_int,rank,102,mpi_comm_world,ierr) end total_sum=0 i=1,avg_rows_per_procs total_sum=total_sum+vector(i) end print*,'partial sum=',total_sum,'from root process' rank=1,num_procs-1 call mpi_recv(partial_sum,1,mpi_int,mpi_any_source,103,mpi_comm_world,status,ierr) sender=status(mpi_source) print*,'partial sum=',partial_sum,'from rank',sender total_sum=total_sum+partial_sum end print*,'total sum=',total_sum else call mpi_recv(num_rows_to_receive,1,mpi_int,master,mpi_any_tag,mpi_comm_world,status,ierr) call mpi_recv(vector2,num_rows_to_receive,mpi_int,master,mpi_any_tag,mpi_comm_world,status,ierr) partial_sum=0 i=1,num_rows_to_receive partial_sum=partial_sum+vector2(i) end call mpi_send(partial_sum,1,mpi_int,master,103,mpi_comm_world,ierr) end if call mpi_finalize(ierr) stop end program sum_vector
it seems integer overflow occurs total_sum
, partial_sum
large max_rows
because former become large ~ max_rows**2
. changing declaration to
use iso_fortran_env, only: int64 integer(int64) :: total_sum, partial_sum
and mpi calls sending/receiving partial_sum
as
call mpi_recv(partial_sum,1,mpi_long_long_int,mpi_any_source,103,mpi_comm_world,status,ierr)
and
call mpi_send(partial_sum,1,mpi_long_long_int,master,103,mpi_comm_world,ierr)
probably gives expected result. example, result obtained max_rows = 100000
, 4 processes (using gfortran 4.7 , openmpi 1.6.5) is
partial sum= 312512500 root process partial sum= 937512500 rank 1 partial sum= 1562512500 rank 2 partial sum= 2187512500 rank 3 total sum= 5000050000
and result max_rows = 100000000
is
partial sum= 312500012500000 root process partial sum= 937500012500000 rank 1 partial sum= 1562500012500000 rank 2 partial sum= 2187500012500000 rank 3 total sum= 5000000050000000
this code works long max_rows
less ~ 2*10^9.
additional notes:
the exact answer
total sum = max_rows * (max_rows + 1) / 2
(simply sum 1max_rows
).the maximum number of
integer
approximately 2*10^9 (please see integer), ifmax_rows
greater 10^5, (10^5)^2 / 2 becomes greater 2*10^9, may exceed limit ofinteger
.
edit: have changed integer(8)
integer(int64)
portable (please see @casey's comment).
Comments
Post a Comment