我有一个大小约为60GB的未格式化的流二进制文件,在我的串行代码中,其内容如下:
parameter(nsea=120445)
real*4 p(nsea,nsea)
open(10,file='my_file.grd' &
& ,status='old',access='stream',form='unformatted')
read(10)((p(ibk,jbk),jbk=1,nsea),ibk=1,nsea)
close(10)
由于读取该文件需要花费大量时间,因此我想使用MPI I / O并行化这部分代码。我正在尝试使用mpi_file_set_view
和mpi_file_read
选项。有人可以指导我有效地做到这一点吗?
读取并存储参数p(nsea,nsea)
后,我想在代码的其余部分中将整个数组传递给一些矩阵算术。
答案 0 :(得分:0)
我在PC上尝试了一个示例代码的简单再现器,该示例代码具有32 GB的内存,可存储27 Gb的测试文件。使用“ gFortran stream.f90 -o stream.exe”进行编译,它在320秒内运行,因此单线程是否太慢? (由于磁盘缓冲,这种测试方法可能会出现问题,但是当文件大小+内存需求超过已安装的内存时应该不会出现问题) 您可能希望通过包括更多错误测试(stat =,iostat =)来扩展下面列出的方法。
! Program to test stream I/O for large file
!
integer*8 :: nsea = 85000 ! 40000 > 6gb ! 85000 > 27gb ! 120445 > 54 gb
real*4, allocatable :: p(:,:)
!
integer*8 :: ibk,jbk, nij
integer*4 :: i,j, stat
real*4 :: err, gb
real*8 :: sec, start
!
! Create file
call Elapse_Time (start)
call Delta_Time (sec)
allocate ( p(nsea,nsea), stat=stat )
nij = size( p, kind=8 )
gb = nij ; gb = gb * 4. / (1024.**3)
write (*,21) 'size p = ',size( p, kind=8 ), gb,' Gb : stat= ',stat
!
forall (i=1:nsea,j=1:nsea) P(i,j) = i+j
call Delta_Time (sec)
write (*,22) sec,' initialised'
!
open (unit=11, file='test_file.grd', iostat=stat, &
status='unknown', access='stream', form='unformatted')
call Delta_Time (sec)
write (*,22) sec, ' open : iostat= ',stat
!
write (11,iostat=stat) (( p(ibk,jbk), ibk=1,nsea), jbk=1,nsea)
close (11)
deallocate (p)
call Delta_Time (sec)
write (*,22) sec, ' written : iostat= ',stat
!
! Read file
allocate ( p(nsea,nsea), stat=stat )
write (*,21) 'size p = ',size( p, kind=8 ), gb,' Gb : stat= ',stat
!
open (unit=12, file='test_file.grd', iostat=stat, &
status='unknown', access='stream', form='unformatted')
call Delta_Time (sec)
write (*,22) sec, ' open : iostat= ',stat
!
read (12,iostat=stat) (( p(ibk,jbk), ibk=1,nsea), jbk=1,nsea)
close (12)
call Delta_Time (sec)
write (*,22) sec,' read : iostat= ',stat
!
err = 0
do j=1,nsea
do i=1,nsea
err = max ( err, P(i,j)-i-j )
end do
end do
deallocate (p)
call Delta_Time (sec)
write (*,23) sec, ' err= ', err
!
call Elapse_Time (sec)
write (*,22) sec-start, ' Completed '
!
21 format (a,i0,' : ',f0.2,a,i0)
22 format (f9.3,a,i0)
23 format (f9.3,a,es10.2)
end
!
subroutine Elapse_Time (sec)
real*8 sec
integer*8 clock, rate
!
call System_Clock ( clock, rate )
sec = dble (clock) / dble (rate)
end subroutine Elapse_Time
!
subroutine Delta_Time (dt)
real*8 :: dt, sec
real*8 :: last = 0
!
call Elapse_Time (sec)
dt = sec - last
last = sec
end subroutine Delta_Time
我在3台PC,2台SSD上测试了此代码。 i5具有Win 7 8Gb内存,而i7具有Win 10 32Gb内存。下表列出了我获得的性能。文件大小为〜85%的内存,因此磁盘缓冲应该不会很大。结果可以是可变的。我对SSD的性能低于预期感到惊讶,而i7 HDD的性能却优于预期吗?
Disk File Gb write sec read sec write Mb/s read Mb/s
i5-2300 C:HDD 4.6 42.1 58.9 108.3 77.5
i7-4790K E:HDD 26.9 175.0 168.7 153.8 159.6
i7-4790K C:SSD 26.9 154.7 106.4 174.0 252.9
i7-8700K E:HDD 26.9 141.8 132.7 189.8 202.8
i7-8700K C:SSD 26.9 116.9 97.5 230.2 276.0
我希望这些结果能说明串行流I / O可以实现什么。不确定在这种情况下可以预期的MPI I / O速率是多少?