Temporary arrays when returning arrays from function calls

10 views
Skip to first unread message

ljw

unread,
Sep 29, 2009, 5:30:39 AM9/29/09
to gg95
Hi,

G95 seems to use temporary arrays when returning array objects from
function calls. Consider the following simple function that returns an
array:

FUNCTION vector_function(v1,v2) RESULT(v3)
IMPLICIT NONE
INTEGER, PARAMETER :: ndim = 100
REAL*8, DIMENSION(ndim), INTENT(IN) :: v1, v2
REAL*8, DIMENSION(ndim) :: v3
INTEGER :: i

DO i = 1, ndim
! whatsoever
v3(i) = 0.5D0 * v1(i) + 0.5D0 * v2(i)
END DO

RETURN
END FUNCTION vector_function

If I call it from the following simple program:

PROGRAM vectorsyntax

USE vector_ops

IMPLICIT NONE
INTEGER, PARAMETER :: ndim = 100
REAL*8, DIMENSION(ndim) :: u, v, w
INTEGER :: i, iter

DO i = 1, ndim
CALL random_number( u(i) )
CALL random_number( v(i) )
END DO

iter = 50000000
DO i = 1, iter
w = vector_function( u, v )
END DO

STOP
END PROGRAM

..compiled with -O2 -pg options only - the profiling shows that the
array allocation is going on there:

Flat profile:

Each sample counts as 0.01 seconds.
% cumulative self self total
time seconds seconds calls s/call s/call name
71.50 18.46 18.46 50000000 0.00 0.00
vector_ops_MP_vector_function
13.98 22.07 3.61 1 3.61 22.07 MAIN_
6.60 23.78 1.71 section_size
1.98 24.29 0.51
_g95_array_from_section
1.41 24.65 0.37 get_user_mem
0.77 24.85 0.20 delete_treap
0.76 25.05 0.20
_g95_deallocate_array
0.60 25.20 0.16 _g95_xorshift128
0.60 25.36 0.16 free_user_mem
0.54 25.50 0.14 insert_mem
0.39 25.60 0.10
_g95_init_multipliers
0.37 25.69 0.10 delete_root
0.14 25.73 0.04
_g95_allocate_array
0.12 25.76 0.03
initialize_memory
0.08 25.78 0.02
vector_ops_MP_vector_subroutine
0.06 25.79 0.02 _g95_library_end
0.06 25.81 0.02 compare
0.04 25.82 0.01 rotate_right
0.02 25.82 0.01
_g95_allocate_string

...although there is no explicit allocation in the code at all.
Interenstingly, when I rewrite the same function as a subroutine:

SUBROUTINE vector_subroutine(v1,v2,v3)
IMPLICIT NONE
INTEGER, PARAMETER :: ndim = 100
REAL*8, DIMENSION(ndim), INTENT(IN) :: v1, v2
REAL*8, DIMENSION(ndim), INTENT(OUT) :: v3
INTEGER :: i

DO i = 1, ndim
v3(i) = 0.5D0 * v1(i) + 0.5D0 * v2(i)
END DO

RETURN
END SUBROUTINE vector_subroutine

No allocation is done:

Flat profile:

Each sample counts as 0.01 seconds.
% cumulative self self total
time seconds seconds calls s/call s/call name
99.39 18.45 18.45 50000000 0.00 0.00
vector_ops_MP_vector_subroutine
0.62 18.56 0.12 1 0.12 18.56 MAIN_

This issue is of course crucial from the performance point of view.
Other compilers (e.g. Intel) don't do this via temporary arrays and
are way faster. In general the subroutine design would easily solve
the problem, however I deal with a large code and want to extend the
functionality using INTERFACE, and unfortunately the original design
uses FUNCTIONs...

So my question is: does anyone now how to avoid temporary array
allocation when passing an array object as a function return value in
g95 ? Or maybe there is another option ?

Thanks and regards!
Lukasz

Alvaro Fernandez

unread,
Oct 27, 2009, 12:25:40 PM10/27/09
to gg...@googlegroups.com
One possibility is to have the function return a pointer to a globally visible array. That's the short version of what you need to do. :-) The long version is you put the array in a module, and the functions you are working on point at appropriate array sections. Depending on the details of what you're trying to do, you may need to keep additional info in the module for bookkeeping purposes, e.g. integer counters for where the next free section of your work array is.
 
There are also other considerations, such as modifying the attributes of the dummy arguments in your existing functions so they accept pointers as arguments. But this is the general approach I would follow.
 
Alvaro
 

From: ljw <Lukasz....@ruhr-uni-bochum.de>
To: gg95 <gg...@googlegroups.com>
Sent: Tuesday, September 29, 2009 4:30:39 AM
Subject: Temporary arrays when returning arrays from function calls

Kaleb Duplessis

unread,
Oct 27, 2009, 1:23:38 PM10/27/09
to gg...@googlegroups.com
I wish I knew what you were talking about. I am completely new to C# and have no idea what that means. I am struggling pretty bad though in this class.

Kaleb Duplessis

Alvaro Fernandez

unread,
Oct 27, 2009, 1:57:15 PM10/27/09
to gg...@googlegroups.com
Um, C#?
 
You mean new to Fortran, right?
Alvaro

 

From: Kaleb Duplessis <kcdup...@aol.com>
To: gg...@googlegroups.com
Sent: Tuesday, October 27, 2009 12:23:38 PM

Kaleb Duplessis

unread,
Oct 27, 2009, 2:48:26 PM10/27/09
to gg...@googlegroups.com
Haha yeah Fortran sorry I have a lot going on. I know fortran is really old school but for some reason I just cannot grasp it. If I send you the text file I have do you think you can help me decipher some of it?

Alvaro Fernandez

unread,
Oct 27, 2009, 3:10:43 PM10/27/09
to gg...@googlegroups.com
OK, I guess I can help you with your homework. :-) I do suggest you get a book by Metcalf & Reid, Fortran 95/2003 Explained.
 
Really, BASIC is just dumbed-down Fortran. Shouldn't be too hard.
 
Alvaro Fernandez

 


From: Kaleb Duplessis <kcdup...@aol.com>
To: gg...@googlegroups.com
Sent: Tuesday, October 27, 2009 1:48:26 PM

Łukasz Walewski

unread,
Oct 27, 2009, 4:22:50 PM10/27/09
to gg...@googlegroups.com
Alvaro,

Thanks for the answer. To shed some light on what I am doing: I am
operating on small arrays of three elements (that correspond to 3D
Cartesian vectors). The function I mentioned transforms the elements of
the vector according to some simple scheme and returns the new vector.

Your suggestion to use a global array could be one way around my
problem. The other, that I already implemented, is to redesign the
function into a subroutine, so that it modifies the argument it gets:

SUBROUTINE vector_subroutine(v)
IMPLICIT NONE
REAL*8, DIMENSION(3), INTENT(INOUT) :: v

v(:) = ...

RETURN
END

With such an arrangement the temp arrays are not created. Moreover this
is probably more standard-compliant way of doing things. Isn't it ?

Best regards,
Lukasz


Dnia 2009-10-27, wto o godzinie 09:25 -0700, Alvaro Fernandez pisze:
> One possibility is to have the function return a pointer to a globally
> visible array. That's the short version of what you need to do. :-)
> The long version is you put the array in a module, and the functions
> you are working on point at appropriate array sections. Depending on
> the details of what you're trying to do, you may need to keep
> additional info in the module for bookkeeping purposes, e.g. integer
> counters for where the next free section of your work array is.
>
> There are also other considerations, such as modifying the attributes
> of the dummy arguments in your existing functions so they accept
> pointers as arguments. But this is the general approach I would
> follow.
>
> Alvaro
>
>
> ______________________________________________________________________

Alvaro Fernandez

unread,
Oct 27, 2009, 5:23:58 PM10/27/09
to gg...@googlegroups.com
I once had to do the global array approach because I was overloading operators and so the routines had to be functions. But certainly, if you want to avoid copy in-copy out issues changing to a subroutine does indeed work too.
 
So instead of declaring a global array and pointing to it, you declare the array locally and pass it in. I wouldn't necessarily call it more standard compliant though.
 
Alvaro Fernandez

 


From: Łukasz Walewski <Lukasz....@ruhr-uni-bochum.de>
To: gg...@googlegroups.com
Sent: Tuesday, October 27, 2009 3:22:50 PM
Subject: Re: Temporary arrays when returning arrays from function calls

Kaleb Duplessis

unread,
Oct 28, 2009, 1:22:40 PM10/28/09
to gg...@googlegroups.com
Thanks for the info I will take a look around for that book. Ok so I attached the text file he gave me and the first and only advice he gave me was to think of some requirements for software testing. I would do that but I don't even know what to do with the text file.
gndrls_CSP_constant_95.txt

Alvaro Fernandez

unread,
Oct 28, 2009, 6:42:30 PM10/28/09
to gg...@googlegroups.com
The file looks a bit like a namelist, which is a Fortran way to read in and out named data. It's kinda neat. But I only say a bit like a namelist; it's missing the end character. (You can google 'Fortran namelist' if you want.) 
 
There is no Fortran source code here though, so I'm at a bit of a loss.
 
Alvaro

 


From: Kaleb Duplessis <kcdup...@aol.com>
To: gg...@googlegroups.com
Sent: Wednesday, October 28, 2009 12:22:40 PM

Kaleb Duplessis

unread,
Nov 2, 2009, 1:27:20 PM11/2/09
to gg...@googlegroups.com
So I finally got a little more light shed on my assignment. Turns out I misunderstood what he wanted about Fortran. He actually wants us to create a program in C# that reads the .txt file and puts it into a GUI that allows me to change the contents. And when I save it, it must be saved as a .txt file. Don't know if you have any background in C# but I would assume you do. Any advice?

ep...@juno.com

unread,
Nov 2, 2009, 2:14:59 PM11/2/09
to gg95


On Nov 2, 1:27 pm, Kaleb Duplessis <kcduples...@aol.com> wrote:
> So I finally got a little more light shed on my assignment. Turns out I misunderstood what he wanted about Fortran. He actually wants us to create a program in C# that reads the .txt file and puts it into a GUI that allows me to change the contents. And when I save it, it must be saved as a .txt file. Don't know if you have any background in C# but I would assume you do. Any advice?
>
> Kaleb Duplessis
>

This is not really a Fortran or G95 question, but here it goes anyway.
The process is similar in any of the Microsoft languages. In one of
the older languages (pre-dot net) you create a form and add a control
(text exit or rich text) to a form. Then pass the input file to the
control. On the output side, you invoke one of the common dialogs for
"save" or "save as" with appropriate arguments. I could explain the
process in VBA (Visual Basic for Application, but it would not do you
much good.). The dot net framework allows you to skip a number of
steps in creating an application, opening a form, etc.

In any case, the hard part is finding the object, properties, methods
you want. Then change what needs to be changed to account for your
choices of MS language.

HTH

-- elliot



ep...@juno.com

unread,
Nov 2, 2009, 3:22:48 PM11/2/09
to gg95
Excuse reply to self. The data file that you attached looks somewhat
like a Fortran Namelist, but IMO it's just a dump of variable name /
value.
While it does look like the type of fixed column format input that
Fortran handles easily with its FORMAT statements (or FORMAT
specifiers), this could just as easily have come from "screen scaping"
a green screen display.

While you might be able to use C#'s version of sscanf (whatever that
is). you also should look at the substring and type conversion
facilities inherited from Visual Basic. [IMO this is really where the
dot net languages came from.]

--- e


Alvaro Fernandez

unread,
Nov 3, 2009, 10:06:54 AM11/3/09
to gg...@googlegroups.com
This is a little out of this list's scope then. :-) I do know a little C#, but there are plentiful examples out there. I suggest you Google "reading from files in C#". You'll get plenty of info that way.

Alvaro

 


From: Kaleb Duplessis <kcdup...@aol.com>
To: gg...@googlegroups.com
Sent: Mon, November 2, 2009 12:27:20 PM
Reply all
Reply to author
Forward
0 new messages