可能是最明智的方式做到這一點是有過程的一個統計文件總數事前,播出,然後讓每個人都做「自己」的文件:
program processfiles
use mpi
implicit none
integer :: rank, comsize, ierr
integer :: nfiles
character(len=6) :: prefix="result"
character(len=4) :: suffix=".bin"
character(len=50) :: filename
integer :: i
integer :: locnumfiles, startnum, endnum
logical :: exists
call MPI_Init(ierr)
call MPI_Comm_size(MPI_COMM_WORLD, comsize, ierr)
call MPI_Comm_rank(MPI_COMM_WORLD, rank, ierr)
! rank zero finds number of files
if (rank == 0) then
nfiles = 0
do
write(filename,FMT='(A,I0,A)'), prefix, nfiles+1, suffix
inquire(file=trim(filename),exist=exists)
if (not(exists)) exit
nfiles = nfiles + 1
enddo
endif
! make sure everyone knows
call MPI_Bcast(nfiles, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, ierr)
if (nfiles /= 0) then
! calculate who gets what file
locnumfiles = nfiles/comsize
if (locnumfiles * comsize /= nfiles) locnumfiles = locnumfiles + 1
startnum = locnumfiles * rank + 1
endnum = startnum + locnumfiles - 1
if (rank == comsize-1) endnum = nfiles
do i=startnum, endnum
write(filename,FMT='(A,I0,A)'), prefix, i, suffix
call processfile(rank,filename)
enddo
else
if (rank == 0) then
print *,'No files found; exiting.'
endif
endif
call MPI_Finalize(ierr)
contains
subroutine processfile(rank,filename)
implicit none
integer, intent(in) :: rank
character(len=*), intent(in) :: filename
integer :: unitno
open(newunit=unitno, file=trim(filename))
print '(I4,A,A)',rank,': Processing file ', filename
close(unitno)
end subroutine processfile
end program processfiles
然後一個簡單的測試:
$ seq 1 33 | xargs -I num touch "result"num".bin"
$ mpirun -np 2 ./processfiles
0: Processing file result1.bin
0: Processing file result2.bin
0: Processing file result3.bin
0: Processing file result4.bin
0: Processing file result5.bin
0: Processing file result6.bin
1: Processing file result18.bin
0: Processing file result7.bin
0: Processing file result8.bin
1: Processing file result19.bin
0: Processing file result9.bin
1: Processing file result20.bin
0: Processing file result10.bin
1: Processing file result21.bin
1: Processing file result22.bin
0: Processing file result11.bin
1: Processing file result23.bin
0: Processing file result12.bin
1: Processing file result24.bin
1: Processing file result25.bin
0: Processing file result13.bin
0: Processing file result14.bin
1: Processing file result26.bin
1: Processing file result27.bin
0: Processing file result15.bin
0: Processing file result16.bin
1: Processing file result28.bin
1: Processing file result29.bin
1: Processing file result30.bin
0: Processing file result17.bin
1: Processing file result31.bin
1: Processing file result32.bin
1: Processing file result33.bin
更新添加補充OpenMP的問題:
爲:F IRST循環是,在其中計算的文件數,文件開始的並行處理之前。該文件的那計數需要做之前的文件的並行處理可能發生的,因爲否則它不可能瓜分處理器之間的工作;您需要知道在分配工作之前將會有多少「工作單位」。(這不是絕對唯一的辦法,但它是最直接的)。
同樣,OMP DO
循環需要相當結構化的循環 - 需要有一個簡單的循環,如do i=1,n
,然後可以很容易地在線程之間分解。 n
不需要編譯,增量甚至不需要是一個,但它必須是在實際執行循環之前可以確定的那種事情。因此,例如,由於某些外部原因(如不存在文件),您無法退出循環。
因此,您想要對OpenMP執行的操作是執行相同的文件計數,然後單獨離開,但在處理循環中,使用並行do結構。所以,在剝離MPI的東西之後,你會看到如下所示的東西:
do
write(filename,FMT='(A,I0,A)'), prefix, nfiles+1, suffix
inquire(file=trim(filename),exist=exists)
if (.not.exists) exit
nfiles = nfiles + 1
enddo
if (nfiles /= 0) then
!$OMP PARALLEL SHARED(nfiles,prefix,suffix) PRIVATE(i,thread,filename)
thread = omp_get_thread_num()
!$OMP DO
do i=1, nfiles
write(filename,FMT='(A,I0,A)'), prefix, i, suffix
call processfile(thread,filename)
enddo
!$OMP END DO
!$OMP END PARALLEL
else
print *,'No files found; exiting.'
endif
但是其他的東西都是一樣的。再次,如果你想處理文件「inline」(例如,不在sburoutine中),你可以將文件處理代碼放在'call processfile()'行的位置。
編輯用mpi替換openmpi;這不是openmpi特有的。 – 2011-04-10 17:26:21