Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Beginner
43 Views

create unique file within multi-thread fortran program

Hi

I want create lot of unique named files in my multi-thread (openmp) Fortran program, both for write and read,  the work flow is that fortran creates a file, write some codes into it, then call an external program, which will generate an output file, and fortran will read this output file. 

There was a post by Steve Lionel:

character(255) filename

call generate_temp_name('TMP', filename)
print *, trim(filename)


contains

subroutine generate_temp_name (prefix, outname)
implicit none
character(*), intent(in) :: prefix
character(*), intent(out) :: outname

real mrand
integer irand
logical ex
logical, save :: init = .false.
! Initialize random number generator
if (.not. init) then
  call random_seed
  init = .true.
  end if

do
! Get a random number
call random_number(mrand)
! Get the low 24 bits
irand = transfer(mrand, irand)
irand = iand(irand,Z'FFFFFF')
write (outname,101) trim(prefix),irand
101 format (A,Z6.6,'.tmp')
inquire (file=trim(outname),exist=ex)
if (.not.ex) exit
end do

! We have a name that does not exist (at least right now)
return

end subroutine generate_temp_name

end

 

which was based on random numbers, I am not sure whether it is thread safe, or there may be other better solutions, such as call the system `mkstemp` (don't how to call it from fortran)

0 Kudos
1 Reply
Highlighted
43 Views

Two potential issues that I see:

1) the outname must be in storage local to the thread calling the subroutine. For example: a) On stack of the parallel region of the caller, allocated by .AND. descriptor on stack of the parallel region of the caller, c) in  threadlocal storage.

2) While the file doesn't exist at the point of the inquire on line 32, the code does not protect against multiple threads performing the inquire on the same name before any one of them performs the OPEN.

I suggest you use something like this

integer, save :: fileSequenceNumber = 0
integer :: my_fileSequenceNumber

...
!$omp critical(critical_generate_temp_name)
 my_fileSequenceNumber = fileSequenceNumber
 fileSequenceNumber = fileSequenceNumber + 1
!$omp end critical(critical_generate_temp_name)
...

You may want to modify this such that the starting fileSequenceNumber is initialize at program start to avoid conflicts with prior run created files.

You can also obtain the thread ID (call pthread_self()) and name mangle that with the fileSequenceNumber. You still would have old filenames laying around to deal with, but this would reduce the frequency of name collisions as well as avoid two threads from creating a same name file (within a program run).

Jim Dempsey

 

0 Kudos