Array valued function and memory 
Author Message
 Array valued function and memory

Hi all,

I just tried to use array valued functions instead of subroutines where
it was possible, but I figured out the code was then slower.

With this code example :

program t
integer, parameter :: n = 500
real*8 tab(n,n), tab2(n,n)
real*8 tab3(2*n,2*n), tab4(2*n,2*n)

tab = 0.D0
tab2 = 0.D0
tab3 = 0.D0
tab4 = 0.D0

print*,'avant'
read(*,*)
tab2 = test(tab)
print*,'entre'
read(*,*)
tab3 = test(tab4)
print*,'apres'
read(*,*)

contains
function test(tab)
real*8, intent(in) :: tab(:,:)
real*8  :: test(size(tab,1),size(tab,2))
print*,'test, avant'
read(*,*)
test = tab
print*,'test, apres'
read(*,*)
end function test

end program t

I can see, with a 'top -pPID' with PID of the process, that the function
allocates some memory (at the 'test=tab' line).
This memory is not freed after the function returned, and, apparently,
not until the program stops.

If I switch 'tab2 = test(tab)' and 'tab3 = test(tab4)' lines, I can see
that no more memory is allocated with the second function call.
It seems the function uses the already allocated memory which is enough
since the array tab is smaller.

Also, I timed a similar example with a do loop and did the same with a
subroutine instead of function : the array valued function code is twice
slower.

My questions are :
1- Is there a way to avoid this drawback with array valued functions ?
2- Why is it so slow, since the function seems to allocate memory once,
until it is not enough ?
3- Is it compiler/platform dependent ?

Thx,
Legu.



Tue, 01 Apr 2008 20:12:49 GMT  
 Array valued function and memory

I don't know for sure what is happening. One possibility is that the
function copies the array when the array is returned. I think it would
almost have to because the function is not passed the address of the array
that serves as the final destination of the values.  The address *is* passed
when the array is included in a subroutine argument list and does not have
to be copied.

Regards,
David


Quote:
> Hi all,

> I just tried to use array valued functions instead of subroutines where it
> was possible, but I figured out the code was then slower.

> With this code example :

> program t
> integer, parameter :: n = 500
> real*8 tab(n,n), tab2(n,n)
> real*8 tab3(2*n,2*n), tab4(2*n,2*n)

> tab = 0.D0
> tab2 = 0.D0
> tab3 = 0.D0
> tab4 = 0.D0

> print*,'avant'
> read(*,*)
> tab2 = test(tab)
> print*,'entre'
> read(*,*)
> tab3 = test(tab4)
> print*,'apres'
> read(*,*)

> contains
> function test(tab)
> real*8, intent(in) :: tab(:,:)
> real*8  :: test(size(tab,1),size(tab,2))
> print*,'test, avant'
> read(*,*)
> test = tab
> print*,'test, apres'
> read(*,*)
> end function test

> end program t

> I can see, with a 'top -pPID' with PID of the process, that the function
> allocates some memory (at the 'test=tab' line).
> This memory is not freed after the function returned, and, apparently, not
> until the program stops.

> If I switch 'tab2 = test(tab)' and 'tab3 = test(tab4)' lines, I can see
> that no more memory is allocated with the second function call.
> It seems the function uses the already allocated memory which is enough
> since the array tab is smaller.

> Also, I timed a similar example with a do loop and did the same with a
> subroutine instead of function : the array valued function code is twice
> slower.

> My questions are :
> 1- Is there a way to avoid this drawback with array valued functions ?
> 2- Why is it so slow, since the function seems to allocate memory once,
> until it is not enough ?
> 3- Is it compiler/platform dependent ?

> Thx,
> Legu.



Wed, 02 Apr 2008 00:30:37 GMT  
 Array valued function and memory

Quote:
> I don't know for sure what is happening. One possibility is that the
> function copies the array when the array is returned. I think it would
> almost have to because the function is not passed the address of the array
> that serves as the final destination of the values.  The address *is*
passed
> when the array is included in a subroutine argument list and does not have
> to be copied.

Many compilers actually do pass the address of the array that serves
as the final destination of the values.  The design of array-valued
functions in the standard is such that the caller can call a prolog
function to resolve the specification statements that lead to the
result shape.  The caller can then allocate memory if the function
is used in an expression or simply pass an address or a descriptor
if the function is the right hand side of an assignment statement.

--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end



Wed, 02 Apr 2008 00:56:39 GMT  
 Array valued function and memory

Quote:



>>I don't know for sure what is happening. One possibility is that the
>>function copies the array when the array is returned. I think it would
>>almost have to because the function is not passed the address of the array
>>that serves as the final destination of the values.  The address *is*

> passed

>>when the array is included in a subroutine argument list and does not have
>>to be copied.

> Many compilers actually do pass the address of the array that serves
> as the final destination of the values.  The design of array-valued
> functions in the standard is such that the caller can call a prolog
> function to resolve the specification statements that lead to the
> result shape.  The caller can then allocate memory if the function
> is used in an expression or simply pass an address or a descriptor
> if the function is the right hand side of an assignment statement.

So you mean some compilers can avoid creating a temporary array and copy
its content back ?
Which compilers / flags can do that ?

Ah, in reading this newsgroup, I frequently see acronyms like OP, TR and
others, but I don't know what they're standing for ?

Legu.



Fri, 04 Apr 2008 21:38:02 GMT  
 Array valued function and memory
| Ah, in reading this newsgroup, I frequently see acronyms like OP, TR and
| others, but I don't know what they're standing for ?

OP = Original Poster (the one who started the thread)
(Google i.e. "Usenet acronyms"; the most frequently used are YMMV, AFAIK,
AFAICT, IIRC, AIUI, ROTFL)

TR = Technical Report. In this group, it usually refers to "Allocatables TR"
(TR 15581), which is an "official" extension to F95 allowing allocatable
arrays in much more places (dummy arguments, type components).

--
 Jugoslav
___________
www.xeffort.com

Please reply to the newsgroup.
You can find my real e-mail on my home page above.



Fri, 04 Apr 2008 21:57:57 GMT  
 Array valued function and memory

Quote:
> So you mean some compilers can avoid creating a temporary array and copy
> its content back ?
> Which compilers / flags can do that ?

You will just have to examine disassemblies of compiler output
to determine this.  Actually, the behavior may have been more
common in the past than in the future.  Once a compiler has
implemented the TR that incorporates allocatable function
results, it is probably easier to reuse it than to continue
to attempt to make a prolog function fly.  There are certain
potential complexities in prolog functions.  For example,
the specification expression might depend on other specification
expressions in the function whose results would either have
to be saved somehow by the prolog function or recalculated
after the function itself is invoked.  Here is an example:

module funcs
   implicit none
   contains
      function array(string1, string2)
         character(*), intent(in) :: string1, string2
         character array1(f1(string1))
         character array2(f2(string2))
         character array(size(array1), size(array2))
         integer i

         array = achar(mod(reshape((/(i,i=1,size(array))/), &
            shape(array)),32)+64)
      end function array

      pure function f1(string)
         character(*), intent(in) :: string
         integer f1
         real temp

         read(string,*) temp
         f1 = sqrt(temp)
      end function f1

      pure function f2(string)
         character(*), intent(in) :: string
         integer f2
         real temp

         read(string,*) temp
         f2 = log(temp)
      end function f2
end module funcs

program prolog
   use funcs
   implicit none
   character(80) string1, string2
   character(80) fmt

   write(string1,*) 65.0
   write(string2,*) 149.0
   write(fmt,'(a,i0,a)') '((1x,',size(array(string1,string2),2),'(a1)))'
   write(*,fmt) transpose(array(string1,string2))
end program prolog

In function array above, the result variable shape depends on
the shapes of arrays array1 and array2, which in turn require
invoking specification functions f1 and f2 to get their shapes.
If the result shape is obtained via a prolog function, either
the shapes of array1 and array2 have to be saved somehow (and
that would mean that any prolog function would have to manage
to return more than one scalar value, which could start to
trigger compiler bugs) or the f1 and f2 would have to be
invoked an extra time during the execution of function array,
and this would be an inefficiency.  CVF, LF95, and g95 all output:

 AIQYA
 BJRZB
 CKS[C
 DLT\D
 EMU]E
 FNV^F
 GOW_G

--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end



Sat, 05 Apr 2008 01:50:25 GMT  
 Array valued function and memory

Quote:



>>So you mean some compilers can avoid creating a temporary array and copy
>>its content back ?
>>Which compilers / flags can do that ?

> You will just have to examine disassemblies of compiler output
> to determine this.  Actually, the behavior may have been more
> common in the past than in the future.  Once a compiler has
> implemented the TR that incorporates allocatable function
> results, it is probably easier to reuse it than to continue
> to attempt to make a prolog function fly.  There are certain
> potential complexities in prolog functions.  For example,
> the specification expression might depend on other specification
> expressions in the function whose results would either have
> to be saved somehow by the prolog function or recalculated
> after the function itself is invoked.  Here is an example:

> module funcs
>    implicit none
>    contains
>       function array(string1, string2)
>          character(*), intent(in) :: string1, string2
>          character array1(f1(string1))
>          character array2(f2(string2))
>          character array(size(array1), size(array2))
>          integer i

>          array = achar(mod(reshape((/(i,i=1,size(array))/), &
>             shape(array)),32)+64)
>       end function array

>       pure function f1(string)
>          character(*), intent(in) :: string
>          integer f1
>          real temp

>          read(string,*) temp
>          f1 = sqrt(temp)
>       end function f1

>       pure function f2(string)
>          character(*), intent(in) :: string
>          integer f2
>          real temp

>          read(string,*) temp
>          f2 = log(temp)
>       end function f2
> end module funcs

> program prolog
>    use funcs
>    implicit none
>    character(80) string1, string2
>    character(80) fmt

>    write(string1,*) 65.0
>    write(string2,*) 149.0
>    write(fmt,'(a,i0,a)') '((1x,',size(array(string1,string2),2),'(a1)))'
>    write(*,fmt) transpose(array(string1,string2))
> end program prolog

> In function array above, the result variable shape depends on
> the shapes of arrays array1 and array2, which in turn require
> invoking specification functions f1 and f2 to get their shapes.
> If the result shape is obtained via a prolog function, either
> the shapes of array1 and array2 have to be saved somehow (and
> that would mean that any prolog function would have to manage
> to return more than one scalar value, which could start to
> trigger compiler bugs) or the f1 and f2 would have to be
> invoked an extra time during the execution of function array,
> and this would be an inefficiency.  CVF, LF95, and g95 all output:

>  AIQYA
>  BJRZB
>  CKS[C
>  DLT\D
>  EMU]E
>  FNV^F
>  GOW_G


Thx for your explanations, but, unfortunately, I don't understand your
point with respect to my question !

Legu



Sun, 06 Apr 2008 17:38:37 GMT  
 Array valued function and memory

Quote:
> Thx for your explanations, but, unfortunately, I don't understand your
> point with respect to my question !

I think James answered a very interesting question, and showed one of the
code samples with unexpected uses of F90 features that we have come to ex-
pect of him...but perhaps that question he answered wasn't the question you
had asked.

If I understand you correctly, you are concerned with compilers creating
copies of actual arguments when passing them to a called subroutine - i.e.,
doing argument passing by copy-in/copy-out instead of by-value or by-refe-
rence. There are two places where this can occur, in the caller prior to
the call, and in the callee's prologue/epilogue. The latter would always
be an additional optimization, but I don't know any documented cases of this.
James's example might be considered to be in this category.

For the other place, I would say there are three cases to distinguish.
The first case is where you would not expect a copy to occur, for example
when passing a whole array to an array dummy argument. The second case
is when copy-in/copy-out _must_ occur: For instance, when an array slice
that is known to be discontiguous is passed to a routine with an F77-
compliant interface. The third case really concerns us here: When the
fact of whether this is a contiguous array cannot be determined at compile-
time, for instance, or when the compiler can make a decision to actually
do a copy-in/copy-out as an optimization (e.g., to make the data contiguous
because this will allow the called routine to execute faster). It appears
that compilers have substantially improved in the past years with regard
to the first sub-case, and at least CVF et al. offer you a switch that will
give a report, at run time, when such copies occur. The second sub-case I
have performed manually (and this can of course always be done), but have
yet to see a case where this is done automatically (e.g., driven by profile
feedback).

        Jan



Sun, 06 Apr 2008 18:16:35 GMT  
 Array valued function and memory

Quote:

>> Thx for your explanations, but, unfortunately, I don't understand your
>> point with respect to my question !

> I think James answered a very interesting question, and showed one of the
> code samples with unexpected uses of F90 features that we have come to ex-
> pect of him...but perhaps that question he answered wasn't the question you
> had asked.

> If I understand you correctly, you are concerned with compilers creating
> copies of actual arguments when passing them to a called subroutine - i.e.,
> doing argument passing by copy-in/copy-out instead of by-value or by-refe-
> rence. There are two places where this can occur, in the caller prior to
> the call, and in the callee's prologue/epilogue. The latter would always
> be an additional optimization, but I don't know any documented cases of
> this.
> James's example might be considered to be in this category.

> For the other place, I would say there are three cases to distinguish.
> The first case is where you would not expect a copy to occur, for example
> when passing a whole array to an array dummy argument. The second case
> is when copy-in/copy-out _must_ occur: For instance, when an array slice
> that is known to be discontiguous is passed to a routine with an F77-
> compliant interface. The third case really concerns us here: When the
> fact of whether this is a contiguous array cannot be determined at compile-
> time, for instance, or when the compiler can make a decision to actually
> do a copy-in/copy-out as an optimization (e.g., to make the data contiguous
> because this will allow the called routine to execute faster). It appears
> that compilers have substantially improved in the past years with regard
> to the first sub-case, and at least CVF et al. offer you a switch that will
> give a report, at run time, when such copies occur. The second sub-case I
> have performed manually (and this can of course always be done), but have
> yet to see a case where this is done automatically (e.g., driven by profile
> feedback).

>     Jan

I am not concerned with subroutines, but with array valued functions.
I would like to know if it is possible to, and how to, use such
functions instead of subroutines, without performance drawback.
What I think I understood is that array valued functions need to :
1-create a temporary array to store the result and 2-copy this temporary
array back to the expected array. (right ?)
And this is 2- which slows down things. (right ?)
This could be avoided if the result was put directly in the expected
array, which means that "arguments" need to be passed by reference or by
address. (right ?)

Moreover, I'm not bothered, for my application, with discontiguous array
beeing passed.

James said "many compilers actually do pass the address of the array
that serves as the final destination of the values", this seems to me to
be what I'm looking for, hence my question :
Which compilers / flags can do that ?

Legu



Sun, 06 Apr 2008 19:22:58 GMT  
 Array valued function and memory

Quote:

> I am not concerned with subroutines, but with array valued functions.
> I would like to know if it is possible to, and how to, use such
> functions instead of subroutines, without performance drawback.

The obvious answer is that you have less risk of performance
drawback if you use subroutines rather than functions. So what is
your reason for wanting to use functions ?

Quote:
> What I think I understood is that array valued functions need to :
> 1-create a temporary array to store the result and 2-copy this temporary
> array back to the expected array. (right ?)
> And this is 2- which slows down things. (right ?)
> This could be avoided if the result was put directly in the expected
> array, which means that "arguments" need to be passed by reference or by
> address. (right ?)

> Moreover, I'm not bothered, for my application, with discontiguous array
> beeing passed.

> James said "many compilers actually do pass the address of the array
> that serves as the final destination of the values", this seems to me to
> be what I'm looking for, hence my question :
> Which compilers / flags can do that ?

There is no definite answer. Some compilers may be very bad at it, others
may be sometimes good, sometimes bad. I doubt that it would make sense
to have a special compiler flag: either the compiler can do it, and then
it will be included in the standard optimisation procedures, or it can't
recognize when it can from when it shall not, and there is no flag to make
it break the standard then...

Yet, you may have a look at http://www.fortran-2000.com/MichelList/index.html#2.4



Sun, 06 Apr 2008 19:36:27 GMT  
 Array valued function and memory

Quote:

> The obvious answer is that you have less risk of performance
> drawback if you use subroutines rather than functions. So what is
> your reason for wanting to use functions ?

The only reason is that the code looks to me simpler, more "natural".
I admit this is a rather poor reason ^^

Quote:
> There is no definite answer. Some compilers may be very bad at it, others
> may be sometimes good, sometimes bad. I doubt that it would make sense
> to have a special compiler flag: either the compiler can do it, and then
> it will be included in the standard optimisation procedures, or it can't
> recognize when it can from when it shall not, and there is no flag to make
> it break the standard then...

> Yet, you may have a look at
> http://www.fortran-2000.com/MichelList/index.html#2.4

Ok, thx all, I think I will give up with array valued function.

Besides, why does F90 has this feature ?

Legu.



Sun, 06 Apr 2008 21:09:21 GMT  
 Array valued function and memory

Quote:
> Besides, why does F90 has this feature ?

IMO, array-valued functions are particularly interesting if the returned
value can be dynmic or if they can be used in an expression more complicated
than just a simple assignment. Achieving the latter without memory leaks
quite likely is only possible when the compiler supports the ALLOCATABLE
TR. Doing the former creates the problem that the caller doesn't know,
before the function call, what the size of the returned result will be.
If the LHS isn't a pointer (which can receive an arbitrarily-sized result)
then the calling routine is forced to take the anonymous temporary as
returned by the function and copy it to the actual argument - which could
be a statically-declared array, for instance. F03 allows allocatable
arrays to be dynamically resized in this context, which makes life much
easier all around for all of us.

        Jan



Sun, 06 Apr 2008 21:38:13 GMT  
 
 [ 12 post ] 

 Relevant Pages 

1. Memory leaks with array-valued functions

2. Passing array valued functions as argument to function.

3. Copying one array value into subsequent array values

4. Pointer valued functions and memory leaks

5. array valued functions

6. array valued functions

7. array valued functions

8. rank-reduced array-valued function (like SUM)

9. Allocatable array as return value in function

10. Array-valued functions possible?

11. Array-valued function

12. using a c function to set the array values of a python instance

 

 
Powered by phpBB® Forum Software