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

stunning write speed difference between ifort and gfortran

may_ka
Beginner
1,638 Views

Hi,

the small program below yields a stunning writing speed difference when compiled with ifort and gfortran

program test
  implicit none
  real :: t1,t2
  integer(8) :: j
  !!integer(8), allocatable :: r(:)
  !!allocate(r(10000000),source=int(0,kind=8))
  real(8), allocatable :: r(:)
  allocate(r(10000000),source=0.0D0)
  open(100,file="out.csv",action="write",status="replace",form="formatted")
  call cpu_time(t1)
  do j=1,size(r)
    write(100,*) r(j)
  end do
  call cpu_time(t2); write(*,*) t2-t1
  close(100)
end program test

gfortran wrote the integer version in about 1.1 seconds, the real version in about 4.5 seconds. Ifort versions 17.08, 19.05 and 19.1.1 needed 11 seconds and 12 seconds, respectively. Is just what it is or is there a bug somewhere.

thanks

0 Kudos
1 Solution
Scott_L_
New Contributor I
1,638 Views
my experience is intel fortran by default uses unbuffered IO (I think does a flush after each write statement). Adding buffer options to the open statement speeds up writing data significantly. thanks scott

View solution in original post

0 Kudos
9 Replies
mecej4
Honored Contributor III
1,638 Views

Your WRITE is list-directed, so the format as well the length of the output file are implement-dependent. Ifort write 10 million lines with

  0.000000000000000E+000

whereas Gfortran writes

   0.0000000000000000

As you probably are already aware, it would be much faster to write the whole array with a single WRITE statement instead of WRITE in a DO loop.

0 Kudos
may_ka
Beginner
1,638 Views

Hi,

thank for your explanation ...... if that's what it is that's a bit poor. Note that biggest speed differences are for integer, not for real.

The speed differences of factor 10 for integer write remain even without a do loop

Further, no do-look will cause gfortran to write a single line of output, ifort to write 3Mio lines. Differences in file format

due to compiler change are not exceptable when the programs are part of a pipeline. So the do loop is a must.

cheers

 

 

0 Kudos
mecej4
Honored Contributor III
1,638 Views

If you wish to drill down into the causes, you may try specifying the format yourself, look at differences in buffer sizes, compare internal to decimal conversion algorithms in the RTL, etc. For using the timings as a metric, it would be better to use, say, 1.234567890123456d0, instead of the special number 0.0d0.

In a real application in which I/O is not so dominant as in this tiny example, even a factor of 10 variation in I/O time may not be significant in comparison to, say, FEA computations that precede the I/O.

0 Kudos
may_ka
Beginner
1,638 Views

Hi

just figured out how to induce the line break in the no-doloop one-liner via format. Unfortunately that increased the speed difference between gfortran and ifort to factor 20 (as in ifort no do-loop and do-loop are the same)!! However, thank for you comments but I won't drill any further. Maybe intel pics this up for future improvements.

cheers

0 Kudos
John_Campbell
New Contributor II
1,638 Views

Can you confirm which version of gFortran you used, as there has been a history of improvement for gFortran text write speed.

I can not reproduce your "gfortran wrote the integer version in about 1.1 seconds", although it can depend on both compiler and disk type.

I achieved 8.3 seconds for 8-byte integers on i7-8700K with gFortran 8.3.0

0 Kudos
may_ka
Beginner
1,638 Views

Hi,

I used gfortran 10.1.0 on an Arch Linux System with kernel version 5.2.7. The disk is a Samsung 970 EVO Plus 2TB M.2 PCIe SSD.

cheers

0 Kudos
JohnNichols
Valued Contributor III
1,638 Views
program test
  implicit none
  real :: t1,t2
  integer(8) :: j
  !!integer(8), allocatable :: r(:)
  !!allocate(r(10000000),source=int(0,kind=8))
  real(8), allocatable :: r(:)
  allocate(r(10000000),source=0.0D0)
  open(100,file="out.csv",action="write",status="unknown")
  call cpu_time(t1)
  write(*,*) t1
  do j=1,size(r)
    write(100,*) r(j)
  end do
  call cpu_time(t2); write(*,*) t2-t1
  close(100)
end program test

 

I amended your program slightly and ran it on a corei5 with a SAMSUMG EVO drive -- you create a file that is 247 MB,

1. you cannot open a file this big in EXCEL

2. It took 233 seconds to write reals to a SAMSUNG EVO 960 -- I think 

3. I copied it between a SAMSUNG EVO and an M2 and that only moved at 859MB/s 

 

0 Kudos
Scott_L_
New Contributor I
1,639 Views
my experience is intel fortran by default uses unbuffered IO (I think does a flush after each write statement). Adding buffer options to the open statement speeds up writing data significantly. thanks scott
0 Kudos
may_ka
Beginner
1,638 Views

@Scott L.

awesome hint. That did the trick. Thanks a lot.

cheers

0 Kudos
Reply