[patch, libfortran] [4.7/4.8/4.9 Regression] PR38199 missed optimization: I/O performance

Jerry DeLisle jvdelisle@charter.net
Sun Mar 9 00:55:00 GMT 2014


On 03/08/2014 02:37 PM, Manfred Schwarb wrote:
---snip---

> 
> This is great.
> 
> However, this is still 10 times slower than the LEN_TRIM variant:
>         character buffer(1)*100000
>         integer i,j
>  
>         j = 1234
>         write(buffer(1),'(i4)') j
>  
>         DO j=1,9999
>  !        write(*,*) buffer(1)(1:4)
>           read(buffer(1)(1:LEN_TRIM(buffer(1))),*) i
>  !        write(*,*) i
>         ENDDO
>         end
> 

Lets clarify some things.  We have two different test cases here

case 1: read(buffer(1:LEN_TRIM(buffer(1))),*) i

Before patch:

real	0m24.286s
user	0m24.172s
sys	0m0.013s

After patch:

real	0m2.847s
user	0m2.835s
sys	0m0.000s


case 2: read(buffer(1)(1:LEN_TRIM(buffer(1))),*) i

Before patch:

real	0m0.233s
user	0m0.229s
sys	0m0.002s

After patch

real	0m0.231s
user	0m0.229s
sys	0m0.000s


case 1 is treated as a character array unit and -fdump-tree-original gives:

  D.2323 = (integer(kind=8)) _gfortran_string_len_trim (100000, &buffer[0]);
  parm.2.dtype = 6400049;
  parm.2.dim[0].lbound = 1;
  parm.2.dim[0].ubound = D.2323;
  parm.2.dim[0].stride = 1;
  parm.2.data = (void *) &buffer[0];
  parm.2.offset = -1;
  dt_parm.1.internal_unit = (character(kind=1) *) parm.2.data;
  dt_parm.1.internal_unit_len = 100000;
  dt_parm.1.internal_unit_desc = (character(kind=1) *) &parm.2;
  dt_parm.1.common.unit = 0;
  dt_parm.1.common.flags = 16512;
  _gfortran_st_read (&dt_parm.1);
  _gfortran_transfer_integer (&dt_parm.1, &i, 4);
  _gfortran_st_read_done (&dt_parm.1);

case 2 is treated as a scalar unit and -fdump-tree-original gives:

  D.2323 = _gfortran_string_len_trim (100000, &buffer[0]);
  dt_parm.1.internal_unit = (character(kind=1) *) &buffer[0];
  dt_parm.1.internal_unit_len = MAX_EXPR <NON_LVALUE_EXPR <D.2323>, 0>;
  dt_parm.1.internal_unit_desc = 0B;
  dt_parm.1.common.unit = 0;
  dt_parm.1.common.flags = 16512;
  _gfortran_st_read (&dt_parm.1);
  _gfortran_transfer_integer (&dt_parm.1, &i, 4);
  _gfortran_st_read_done (&dt_parm.1);

Both cases are compiling in the LEN_TRIM.  The slow case has to deal with the
array descriptor and looping through from lbound to ubound.  We probably could
do some additional front end magic, but for now I will commit the runtime patch

Regards,

Jerry



More information about the Fortran mailing list