Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
28158 Discussions

create unique file within multi-thread fortran program



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)


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

! 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)

end subroutine generate_temp_name



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
Black Belt

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