- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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)
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page