ninjacowgirl
ninjacowgirl

Reputation: 83

Writing to file in Fortran do loop

I am just starting to learn fortran and I have made a simple program, implementing Eulers method. I noticed that the time used by the do loop is fairly similar to, for example, the same program in Matlab.

In my Fortran program, I had a write to a file inside this do loop. When I removed it the speed drastically improved, as expected. Then I added a second do loop, where I place the writing and measured the time required by both loops combined:

open(unit=1, file='data.dat')
write(1,*) t(1),' ', y(1)
! Calculating
call cpu_time(start)
do i = 2,n
    t(i) = t(i-1) + dt
    y(i) = y(i-1) + dt*(t(i-1)*(y(i-1)))
    !write(1,*) t(i),' ', y(i)
end do
call cpu_time(finish)
print  '("Time = ",f7.5," seconds.")',finish-start
call cpu_time(start)
do i = 2,n
    write(1,*) t(i),' ',y(i)
end do
 call cpu_time(finish)
print  '("Time = ",f7.5," seconds.")',finish-start

The time for a given n would take approximately 10-15 times longer on the last do loop compared to the first one.

So, my question is, is there a better way to write my data to a file?

Upvotes: 1

Views: 2087

Answers (2)

agentp
agentp

Reputation: 6989

for completeness I'll post the 2d array copy approach:

integer,dimension(10)::x,y
integer,allocatable::tmp(:,:)
integer i
x=[(i, i=0,9)]
y=x+42
allocate(tmp(2,size(x)))
tmp(1,:)=x
tmp(2,:)=y
write(*,'(i0,'','',i0)')tmp
deallocate(tmp)
end
0,42
1,43
2,44
3,45
4,46
5,47
6,48
7,49
8,50
9,51

If performance is really critical I'd try both.

Note the best approach of all may be to simply use a 2d array (or a derived type) in the first place.

Upvotes: 1

Ian Bush
Ian Bush

Reputation: 7433

Assuming t and y are real and depending on the quality of implementation by the compiler, the size of the arrays, the phase of the moon and the local neutron flux something akin to the following might be quicker

ian-standard@barleybarber ~
$ cat t.f90
Program test

  ! Corrected program

  Implicit None

  Real, Dimension( 1:10 ) :: t, y

  Integer :: i

  Call Random_number( t )
  Call Random_number( y )

  Do i = 1, 3
     Write( *, * ) t( i ), y( i )
  End Do
  Write( *, * )

  Write( *, '( f0.9, 1x, f0.9 )' ) ( t( i ), y( i ), i = 1, 3 )

  Open( 1, file = 'stuff.dat' )
  Write( 1, '( f0.9, 1x, f0.9 )' ) ( t( i ), y( i ), i = 1, &
       Min( Size( t ), Size( y ) ) )

End Program test

ian-standard@barleybarber ~
$ gfortran -O -Wall -Wextra -pedantic -std=f95 t.f90 -o test

ian-standard@barleybarber ~
$ ./test
  0.997559547      0.217951715    
  0.566824675      0.133160353    
  0.965915322      0.900524497    

.997559547 .217951715
.566824675 .133160353
.965915322 .900524497

ian-standard@barleybarber ~
$ head stuff.dat 
.997559547 .217951715
.566824675 .133160353
.965915322 .900524497
.747927666 .386765957
.367390871 .445482254
.480636895 .661932170
.073754251 .016108274
.005355179 .650854826
.347081244 .646408796
.342243791 .322987258

as the compiler might be clever enough to turn this all into one I/O transaction instead of many. But you can't be sure. Also to give it a better chance if you don't need all those decimal places adjust the format appropriately.

Upvotes: 2

Related Questions