Fortran Coder

标题: 如何保证写入文件时不覆盖已有的字符串 [打印本页]

作者: 元气蛋    时间: 2023-10-23 20:47
标题: 如何保证写入文件时不覆盖已有的字符串
各位老师好,有一个程序,内部有一个功能是将输出的几个参数写到上一个文件夹中名为array-bmax.txt的文件(107)中,由于这个程序需要并行执行,多个并行计算的结果都需要写入array-bmax.txt文件中,实际执行时发现写入文件时,只能写入最后一个计算出的结果,其他的结果都被覆盖掉了,请问这段代码应该如何修改,才能实现将并行输出的结果都写入文件array-bmax.txt中?
[Fortran] 纯文本查看 复制代码
program main
    use commondata
   
    implicit none
    integer i,style,traj,files,n,j,du
    real*8 xseed
    real bmax,Et,RMAX,RBAR,S
    character*100 ftmp
    character(100) :: cmd
    character(10) :: opinion
    character(80) :: inp_name
   
   
    call ReadInputFile(inp_name,style,traj,files,n,j,Et,bmax,RMAX,RBAR,S)

    open(107,file='../array-bmax.txt',status='old',position='append')

    5 fsbatch='sbatch.sc'
    open(105,file=fsbatch)
   
    ftmp='cp /home/O3/'
    fcpinp='script.cp'
    open(101,file=fcpinp)
    write(101,'(a)')trim(ftmp)//'new/venus-E.e ./'
   
    call init_random_seed()
   
    do i=1,files !nfile
      call random_number(xseed)
      call writeinp(i,xseed,style,traj,files,n,j,Et,bmax,inp_name,RMAX,RBAR,S)
    enddo
   
    write(101,'(a)') 'cp ./sbatch.sc ./'//trim(inp_name)//'-inpark'
    write(101,'(a)') 'cd '//trim(inp_name)//'-inpark'
    write(101,'(a)') 'chmod +x sbatch.sc'
    write(101,'(a)') "sed -i 's/^.\{19\}/scancel /g' scancel.x"
    write(101,'(a)') 'chmod +x scancel.x'
   
    close(101)
   
    call execute_command_line("chmod +x script.cp")
    call execute_command_line("./script.cp")
    call execute_command_line('sleep 1s')
    call execute_command_line("rm -r inp0* run0*")
   
    if (style == 1) then
       open(106,file=trim(inp_name)//'-inpark/test-bmax')
       write(106,'(a,f3.1)') "(*.*)zzz---wait---",bmax
       call execute_command_line('sleep 90s')
   
       call testbmax(inp_name,traj,du)
       if (du == 0) then
            call execute_command_line("rm -r sbatch.sc script.cp")
            bmax=bmax+0.1d0
            goto 5
        elseif (du == 1) then
            write(107,'(f5.1,I3,I4,f5.1)') Et,n,j,bmax
            close(107)
        endif
    elseif (style == 0) then
        stop
    endif
    end program main


作者: li913    时间: 2023-10-24 10:58
不能在并行写同一个文本文件。如果是多次调用写文件的语句,可以在第一次调用之前open,最后close。如果是每次调用都open,需要 open(...... , position='append')
作者: fcode    时间: 2023-10-24 11:24
li913 发表于 2023-10-24 10:58
不能在并行写同一个文本文件。如果是多次调用写文件的语句,可以在第一次调用之前open,最后close。如果是 ...

他就是用的 append,我感觉楼主这种情况,应该是程序执行时间比较长,导致例程A尚未结束,尚未close。例程B,C,D就试图打开文件,失败。
作者: zoziha    时间: 2023-10-24 14:32
试着将输出的内容转换为字符串,多个核心的字符串进行拼接,最后由一个线程写入文件?数据竞争是常态,这里一个写入状态的文件,竞争少不了的。

> 如何向同一个文件并行写入?而不发生数据竞争?
< 在向同一个文件并行写入时,需要确保多个写入操作之间的数据竞争得到正确处理。以下是一些可以采取的步骤:

文件锁定:使用文件锁定机制可以确保在任何给定时间只有一个进程可以写入文件。有多种文件锁定机制可用,包括劝告性锁(advisory lock)和强制锁(mandatory lock)。劝告性锁需要进程之间的合作,而强制锁则由操作系统强制执行。在Python中,您可以使用fcntl模块来实现文件锁定。
使用队列:将写入操作放入队列中,并使用单独的线程或进程来处理队列中的写入操作。这样可以将写入操作串行化,避免同时写入的问题。在Python中,可以使用queue模块来实现队列。
使用文件句柄:每个进程都有自己的文件句柄,通过使用不同的文件句柄来写入文件,可以避免数据竞争的问题。在Python中,您可以使用os模块来创建文件句柄。
使用日志文件系统:日志文件系统是一种特殊的文件系统,可以确保在并行写入时数据的一致性和完整性。它通过将写入操作记录到日志中,并在适当的时候将数据应用到文件系统中来实现这一点。在Python中,您可以使用logging模块来实现日志记录。
需要注意的是,在并行写入同一个文件时,需要谨慎处理数据竞争的问题。为了避免数据竞争,通常需要使用某种形式的同步机制来确保同时对文件进行写入的进程之间能够正确地协调操作。
作者: 元气蛋    时间: 2023-10-24 19:38
谢谢楼上各位老师的建议和帮助,这个程序昨天测试时,我把open107文件的命令改到写入命令前,就可以实现输出都写到107文件里了:
[Fortran] 纯文本查看 复制代码
elseif (du == 1) then
  open(107,file='../array-bmax.txt',position='append')
  write(107,'(f5.1,I3,I4,f5.1)') Et,n,j,bmax
  close(107)
endif
这样这个程序暂且可以运行了,就是其中逻辑我还没想明白,我再好好想想。





欢迎光临 Fortran Coder (http://bbs.fcode.cn/) Powered by Discuz! X3.2