Hello,
I am trying to figure out how to read & write unformatted files in Fortran, where different processes may read&write different records, and hopefully can do so asynchronously.
The first program below, containing the first piece of a pi estimator, seems to work with the parallel I/O.
This program writes to the same file, same [fixed] unit number, but to different records based on the image number. The compilation command is ifx -debug -threads -coarray=shared -coarray-num-images=8 -o my_caf_prog ./basic_newunit.f90
. (threads is not necessary as I do not have the asynchronous specifier anywhere yet; also, coarray=distributed yields the same behavior)
The code is below:
program main
implicit none
integer, parameter :: blocks_per_image = 2**16
integer, parameter :: block_size = 2**10
real, dimension(block_size) :: x, y
integer :: in_circle[*], unit[*] ! an integer but each image has a different local copy
integer :: i, n_circle, n_total, rec_len
real :: step, xfrom
n_total = blocks_per_image * block_size * num_images()
step = 1./real(num_images())
xfrom = (this_image() - 1) * step
inquire(iolength=rec_len) in_circle, n_total
open(100,file='output.txt',form='UNFORMATTED',access='DIRECT',recl=rec_len)
in_circle = 0
do i=1, blocks_per_image
call random_number(x)
call random_number(y)
in_circle = in_circle + count((xfrom + step * x)** 2 + y**2 < 1.)
end do
write(100,rec=this_image()) in_circle, n_total
sync all
close(100)
! Reset in_circle, n_total to make sure we read values
in_circle = 10
n_total = 10
! read from file we wrote to earlier
open(100,file='output.txt',form='UNFORMATTED',access='DIRECT', action='READ', recl=rec_len, status='OLD')
read(100,rec=this_image()) in_circle, n_total
write(*,*), this_image(), " reads in_circle and n_total: ", in_circle, n_total
sync all
close(100)
end program main
with expected output
./my_caf_prog
2 reads in_circle and n_total: 65871670 536870912
3 reads in_circle and n_total: 63695869 536870912
4 reads in_circle and n_total: 60285902 536870912
5 reads in_circle and n_total: 55407149 536870912
6 reads in_circle and n_total: 48613368 536870912
7 reads in_circle and n_total: 38896892 536870912
8 reads in_circle and n_total: 21944055 536870912
1 reads in_circle and n_total: 66933288 536870912
EDIT: I have figured out my first question.
I can also not hardcode the unit, by specifying newunit=unit, and it works so long as I make a new unit whenever I reopen a closed file.
My second question is: Does this approach write to the file unit asynchronously with respect to the different processes? (i.e. each file read/write doesnāt force a sync all?) If not, is there a way to do this? (I know there is an āasynchronousā specifier, but I think that refers only to the read/write happening w.r.t. the rest of that imageās execution. In theory I can do this asynchronously alongside parallel I/O, right?)
My goal is to have fast (parallelizable) I/O, at least on a single computer w/ multiple processors. I know thereās HDF5 and netCDF and whatnot, but Iād like to know how to make this work within Fortran, without the need of external libraries.