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

Stream I/O with advance=no

Ben3
Beginner
768 Views

Hi,

It looks like if you do a read with advance='no' without a variable list on a file opened with access='stream', the advance specified gets applied to the following read as well. Consider this test program:

program advance_test

  implicit none

  integer :: unit = 10
  integer :: i

  open(access='stream', action='write', form='formatted', file='testfile', unit=unit)
  do i = 1, 10
     write(fmt='(i0)', unit=unit) i
  end do
  close(unit=unit)

  open(access='stream', action='read', form='formatted', file='testfile', unit=unit)
  read(fmt='(i1)', advance='no', unit=unit)
  read(fmt=*, unit=unit) i
  write(*, *) i
  read(fmt=*, unit=unit) i
  write(*, *) i
  read(fmt=*, unit=unit) i
  write(*, *) i
  close(unit=unit)

end program advance_test

I would expect the first (advance='no') read to do nothing, the second read to get 1, the third to get 2, and so on. And indeed, using gfortran, this is what I get:

13:13 bjm900@raijin5 noadvance > gfortran file.f90
13:13 bjm900@raijin5 noadvance > ./a.out 
           1
           2
           3

Using ifort, however, I get this:

13:12 bjm900@raijin5 noadvance > ifort file.f90
13:13 bjm900@raijin5 noadvance > ./a.out 
           1
           1
           2

At a guess, the advance='no' with no variables is inadvertently setting some internal flag that's not being reset before the following read. In the case I'm investigating, this structure is used to reposition the file pointer in a formatted file, i.e.:

read(unit, "(I1)", pos=position, advance="no")

The version of ifort I'm using is

13:23 bjm900@raijin5 noadvance > ifort --version
ifort (IFORT) 15.0.0 20140723
Copyright (C) 1985-2014 Intel Corporation.  All rights reserved.

but it is also like this for at least this earlier version

13:23 bjm900@raijin5 noadvance > ifort --version
ifort (IFORT) 14.0.3 20140422
Copyright (C) 1985-2014 Intel Corporation.  All rights reserved.

Cheers,
Ben

0 Kudos
9 Replies
pbkenned1
Employee
768 Views

I can reproduce your complaint, and it could be an ifort bug.  Let me investigate a little bit and I'll get back to you.

Patrick

0 Kudos
pbkenned1
Employee
768 Views

This does look like an ifort bug.  I'll report this to the developers shortly.

Considering the first two reads:

  read(fmt='(i1)', advance='no', unit=unit)
  read(fmt=*, unit=unit) I

Apparently the non-advancing read without an iolist confuses ifort such that it doesn't advance the file pointer after the second read, causing the first record of the file to be read twice.

Note that if the non-advancing read DOES use an iolist, ie:

read(fmt='(i1)', advance='no', unit=unit) I
the file pointer is handled correctly, and the second read will read the second record, as expected.  ifort and gfortran agree for that case:

[U534662]$ ./U534662-mod-read-non-adv-ifort.x
           1
           2
           3
           4
[U534662]$ ./U534662-mod-read-non-adv-gfortran.x
           1
           2
           3
           4

 

Of course you just wanted to reposition the file pointer, and not read anything with the non-advancing read, so I assume that's not a workaround for you

Patrick
 

 

0 Kudos
pbkenned1
Employee
768 Views

Reported to the developers, internal tracking # DPD200362669.  I'll keep this thread updated with developments.

Also worth nothing that if you change the access mode to sequential, ifort works correctly.  That's probably a better workaround.

Patrick

0 Kudos
Ben3
Beginner
768 Views

Patrick Kennedy (Intel) wrote:

Reported to the developers, internal tracking # DPD200362669.  I'll keep this thread updated with developments.

Also worth nothing that if you change the access mode to sequential, ifort works correctly.  That's probably a better workaround.

Patrick

Thanks for that Patrick. Unfortunately, if you use access='sequential', you can't use a pos specified on the read statement, which is the reason these files are being opened as access='stream', I think. Our workaround was to just add a single character read after the advance='no' read, guarded by an ifdef for ifort.

Cheers,
Ben

0 Kudos
pbkenned1
Employee
768 Views

This issue is now fixed in a future version of the compiler.

Patrick

0 Kudos
JVanB
Valued Contributor II
768 Views

I tried to comment about this issue in another thread, but my post went in the queue for moderation and never made it out. Since the reason for that may be a link (to this thread) I decided to repost here, so no link would be necessary.

The issue is about Quote #3 where it is asserted that an empty read is required for the bug to bite, but the bug is clearly active in the snippet there because the first (nonempty this time) read must be reading the '1' in line 1, column 1 of the input file (nothing there would be an error, right?) so the file pointer must be positioned after that point. Then, however, the first READ(FMT=*) backs up over the first record and reads it again to get the output displayed, and this is exactly the bug!

Here is an example that perhaps more clearly demonstrates my point. The input file, rf1.txt:

 -1
  1  2  3
  4  5  6
  7  8  9
 10 11 12

The test program:

program P
   implicit none
   integer i
   integer pos
   integer sentinel
   integer, parameter :: N = 4
   integer posmat(N)
   integer V(3,N)
   character c

   open(10, file = 'rf1.txt', access = 'stream', form = 'formatted', status = 'old')
   read(10, *) sentinel
   inquire(10, pos = pos)
   do i = 1, N
      read(10, *) sentinel
   end do
   read(10, '(a)', pos = pos, advance = 'no') c
   do i = 1, N
      inquire(10, pos = posmat(i))
      read(10, *) V(:,i)
   end do
   do i = 1, N
      write(*, *) posmat(i)
      write(*, *) V(:,i)
   end do
end program P

Output with gfortran:

           7
           1           2           3
          17
           4           5           6
          28
           7           8           9
          39
          10          11          12

Output with ifort:

           7
           1           2           3
           7
           1           2           3
          17
           4           5           6
          28
           7           8           9

So hopefully the fix will be tested against code with a nonempty READ because empty READs are not required for bug activation.

 

0 Kudos
pbkenned1
Employee
768 Views

This is fixed in Composer XE 2015 update 2, so I am closing this ticket now.

C:\ISN_Forums\U534662>ifort U534662.f90
Intel(R) Visual Fortran Intel(R) 64 Compiler XE for applications running on Intel(R) 64, Version 15.0.2.179 Build 20150121
Copyright (C) 1985-2015 Intel Corporation.  All rights reserved.

Microsoft (R) Incremental Linker Version 12.00.21005.1
Copyright (C) Microsoft Corporation.  All rights reserved.

-out:U534662.exe
-subsystem:console
U534662.obj

C:\ISN_Forums\U534662>
C:\ISN_Forums\U534662>U534662.exe
           1
           2
           3

C:\ISN_Forums\U534662>

 

Patrick

 

P.S.> Sorry Repeat Offender, I never tested your program.  Please reply here if you still find this bug not fully squashed.

0 Kudos
JVanB
Valued Contributor II
768 Views

Testing shows that Build 2015121 now matches gfortran, which I consider to be correct.

 

0 Kudos
pbkenned1
Employee
768 Views

Excellent, thanks for the feedback!

Patrick

0 Kudos
Reply