我编写了一个运行良好的网格应用程序,除了一件事: 在将结果写入磁盘时,程序有时挂起。它有效地仍在运行,我可以看到它产生100%的CPU负载并使用top占用内存。但是没有新的数据写入文件,这种状态可能会无限期地持续下去。 这项工作甚至无法杀死,我到目前为止唯一的选择是重新启动机器以摆脱这项工作。
但是,大多数情况下完全相同的作业一直执行到最后没有任何问题。应该注意的是,这仅适用于最终文件大小超过50GB的大型作业。到目前为止,我还没有采取较小的工作来应对这种行为。结果文件每次都写入不同的点。有时它的45GB,有时是60GB或者完全不同的东西。 我使用的工作站运行OpenSuse 13.1,有足够的RAM和磁盘空间可用。然而,在不同的机器上可以观察到相同的行为。
到目前为止我尝试过(除了通常的调试之外)使用Gfortran和英特尔Fortran编译器无济于事。我搞砸了-mcmodel = large编译器选项,但据我所知,这与程序编写的文件大小无关,也没有任何帮助。
我不知道要提供什么信息,因为我真的没有想法可能导致问题。我附加了在这里写入ASCII结果文件的例程,因为它产生了最大的文件大小,但是在编写具有类似例程的未格式化文件时我遇到了同样的问题。 ANY 暗示可能导致此行为的原因值得高度赞赏。
SUBROUTINE write_legacymesh
use types
use parameters
use data
implicit none
INTEGER :: l, n, i, j, k, number, c, neighbor
REAL(DP), DIMENSION(3) :: pos_d
CHARACTER(LEN=100) :: dummy_char
INTEGER(I4B), DIMENSION(26) :: neighborbuffer
LOGICAL :: file_exists
call write_header
call system ('sync')
! create the mesh file
dummy_char = folder_mesh // '/' // file_mesh
write(*,'(A,A)') ' writing mesh: ', trim(adjustl(dummy_char))
open(unit=20, file=trim(adjustl(dummy_char)), status='replace', action='write')
! write the mesh file
write(20,'(A)') ' LB database'
l = level_max
! write the header for this mesh size
write(20,'(A)') ' number of collision centers'
write(20,'(I16)') nf(l)
write(20,'(A)') ' number of cut links'
write(20,'(I16)') ncut(l)
write(20,'(A)') ' number of boundary collision centers'
write(20,'(I16)') nb(l)
write(20,'(A)') ' dummy value'
write(20,'(I16)') 0
write(20,'(A)') ' number of inflow boundary collision centers'
write(20,'(I16)') nb1(l)
write(20,'(A)') ' number of pressure boundary collision centers'
write(20,'(I16)') nb2(l)
write(20,'(A)') ' number of slip boundary collision centers'
write(20,'(I16)') nb3(l)
write(20,'(A)') ' number of noslip boundary collision centers'
write(20,'(I16)') nb4(l)
write(20,'(A)') ' lattice spacing'
write(20,'(E16.8)') dx(l)*scaling
! write the coordinates
write(20,'(A)') ' cc RBT value cc coordinates'
do n=1, nf(l)
number = order_level(l)%order(n)
i = levels(l)%blocks(number)%pos(1)
j = levels(l)%blocks(number)%pos(2)
k = levels(l)%blocks(number)%pos(3)
! rescale and move the geometry to get the original size and position
pos_d(1) = (real(i,kind=dp) - 0.5_dp) * dx(l) + corner_ibc(1)
pos_d(2) = (real(j,kind=dp) - 0.5_dp) * dx(l) + corner_ibc(2)
pos_d(3) = (real(k,kind=dp) - 0.5_dp) * dx(l) + corner_ibc(3)
write(20,'(2I16,3E20.7)') n, levels(l)%blocks(number)%state, pos_d*scaling
end do
! write the link info
write(20,'(A)') ' link information'
do n=1, nf(l)
number = order_level(l)%order(n)
do c=1, nlinks
neighbor = levels(l)%blocks(number)%neighbors(c)
if(neighbor .GT. 0) then
neighborbuffer(c) = levels(l)%blocks(neighbor)%number
else
neighborbuffer(c) = neighbor
end if
end do
write(20,'(7I16)') n, neighborbuffer(1:6)
write(20,'(A,6I16)') ' ', neighborbuffer(7:12)
write(20,'(A,6I16)') ' ', neighborbuffer(13:18)
end do
! write the q-values
write(20,'(A)') ' q-values'
do n=1, ncut(l)
write(20,'(I16,E20.7)') n, max(qmin, min(qmax, aux_level(l)%q_values(n)))
end do
write(20,'(A)') ' end of data'
close(unit=20)
END SUBROUTINE write_legacymesh
Edit1:遵循刷新写入缓冲区的建议,我将其添加到每个写入数据的循环中:
if(mod(n,10000000) .EQ. 0) then
call flush(20)
close(unit=20)
call system('sync')
open(unit=20, file=trim(adjustl(dummy_char)), status='old', position='append', action='write')
end if
这没有改变任何东西,例程仍然在一个随机点挂起,这次是在第一个循环中写入18.5GB数据或211• 016写入事件之后。
Edit2:使用英特尔Fortran编译器(不使用-assume buffered_io标志)取消激活缓冲I / O类型"已解决"问题。但是当然这让我对大文件的缓慢无缓冲写入,这是一种特别令人不快的组合。
Edit3:感谢您提出添加手动写入缓冲区的建议。文件格式不适合有效地使用它们,但它仍然比没有好。无论如何,这是一种遗留的文件格式,我很肯定我可以说服我的同事,不同的文件格式甚至是无格式文件是更好的选择。 虽然我仍然不知道导致错误的原因,但至少我现在有一种可以容忍的方法来避免错误。感谢所有宝贵的建议。