public inbox for fortran@gcc.gnu.org
 help / color / mirror / Atom feed
* Dealing with default recursive procedures in Fortran
@ 2018-04-12 21:50 Thomas König
  2018-04-13 10:11 ` N.M. Maclaren
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Thomas König @ 2018-04-12 21:50 UTC (permalink / raw)
  To: fortran, gcc mailing list

Hello world,

with Fortran 2018, recursive is becoming the default. This will likely
have a serious impact on many user codes, which often declare large
arrays which could then overflow stacks, leading to segfaults without
further explanation.

What could we do? A few options, not all mutally exclusive.

We could extend -fmax-stack-var-size so it allocates memory
from the heap in recursive procedures, too, and set this to
some default value.  Of course, it would also have to free them
afterwards, but we manage that for allocatable arrays already.

We could warn when large arrays with sizes known at compile time
are translated.

We could use -fsplit-stack by default. How reliable is that
option? Can it be used, for example, with -fopenmp?
Is it available on all (relevant) platforms?
One drawback would be that this would allow for infinite
recursions to go on for much longer.

A -fcheck=stack option could be added (implemented similar to
-fsplit-stack), to be included in -fcheck=all, which would abort
with a sensible error message instead of a segfault.

Other ideas / options?

Regards

	Thomas

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Dealing with default recursive procedures in Fortran
  2018-04-12 21:50 Dealing with default recursive procedures in Fortran Thomas König
@ 2018-04-13 10:11 ` N.M. Maclaren
  2018-04-13 11:08 ` Ramana Radhakrishnan
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: N.M. Maclaren @ 2018-04-13 10:11 UTC (permalink / raw)
  To: Thomas König; +Cc: fortran, gcc mailing list

On Apr 12 2018, Thomas König wrote:
>
>with Fortran 2018, recursive is becoming the default. This will likely
>have a serious impact on many user codes, which often declare large
>arrays which could then overflow stacks, leading to segfaults without
>further explanation.

Yes.  Been there - seen that :-)  What's worse, segfaults because of
stack overflow very often confuse debuggers, so you can't even get a
traceback of where it failed!

>We could extend -fmax-stack-var-size so it allocates memory
>from the heap in recursive procedures, too, and set this to
>some default value.  Of course, it would also have to free them
>afterwards, but we manage that for allocatable arrays already.

Yes, but I think it's a horrible idea.  See below for a better one.

>We could warn when large arrays with sizes known at compile time
>are translated.

Yes, but I think that's the wrong criterion.  It should be above a
certain size, probably aggregate per procedure - and controllable,
of course.  Who cares about a couple of 3x3 matrices?

>We could use -fsplit-stack by default. How reliable is that
>option? Can it be used, for example, with -fopenmp?
>Is it available on all (relevant) platforms?
>One drawback would be that this would allow for infinite
>recursions to go on for much longer.

Yes.  And I don't think it's the right mechanism, anyway, except for
OpenMP.  Again, see below.

>A -fcheck=stack option could be added (implemented similar to
>-fsplit-stack), to be included in -fcheck=all, which would abort
>with a sensible error message instead of a segfault.

Absolutely.  Or simply always check!  I haven't studied the actual code
generated by gfortran recently, but my experience of performing stack
checking is that its cost is negligible.  It got a bad name because of
the utter incompetence of the way it was usually implemented.  There is
also a very simple optimisation that often avoids it:

Leave a fixed amount of space beyond the check point and omit the check
for any leaf procedure that uses no more than that.  And, obviously,
that can be extended to non-leaf procedures with known stack use, such
as most of the intrinsics.

There is another option, which I was thinking of experimenting with in
my retirement, but probably won't, is a double stack (as in GNU Ada, and
the better Algol 68 systems).  Small, fixed objects go on the primary
stack, as usual, and large or variable-sized ones go on the secondary
stack.  Allocatable objects should go there if and only if they are not
reallocated.  My experience (a long time back) was that the improved
locality of the primary stack (often needed to control branching) by
removing large arrays from it speeded up most calls with such arrays by
several tens of percent.

Now, there is an interesting interaction with split stacks.  The only
reason to have a contiguous stack is for fast procedure call for simple
procedures.  But that doesn't apply to the secondary stack, so it can
always be split - hence there is no need for a configuration or run-time
option.  That doesn't stop it being checked against a maximum size,
either, because accumulating, decrementing and checking a count isn't a
major overhead for the use the secondary stack gets.


Regards,
Nick Maclaren.


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Dealing with default recursive procedures in Fortran
  2018-04-12 21:50 Dealing with default recursive procedures in Fortran Thomas König
  2018-04-13 10:11 ` N.M. Maclaren
@ 2018-04-13 11:08 ` Ramana Radhakrishnan
  2018-04-13 12:34 ` Janne Blomqvist
  2018-04-16 17:26 ` Michael Matz
  3 siblings, 0 replies; 5+ messages in thread
From: Ramana Radhakrishnan @ 2018-04-13 11:08 UTC (permalink / raw)
  To: Thomas König; +Cc: fortran, gcc mailing list

On Thu, Apr 12, 2018 at 10:50 PM, Thomas König <tk@tkoenig.net> wrote:
> Hello world,
>
> with Fortran 2018, recursive is becoming the default. This will likely
> have a serious impact on many user codes, which often declare large
> arrays which could then overflow stacks, leading to segfaults without
> further explanation.
>
> What could we do? A few options, not all mutally exclusive.
>
> We could extend -fmax-stack-var-size so it allocates memory
> from the heap in recursive procedures, too, and set this to
> some default value.  Of course, it would also have to free them
> afterwards, but we manage that for allocatable arrays already.
>
> We could warn when large arrays with sizes known at compile time
> are translated.
>
> We could use -fsplit-stack by default. How reliable is that
> option? Can it be used, for example, with -fopenmp?
> Is it available on all (relevant) platforms?

Not available on AArch64 (yet, though there are some patches) and Arm
(no current plans that I know of). Probably works best only on x86_64.
I don't think you can rely on that being available everywhere.
Additionally depending on the implementation IIRC that will have a
dependency on a newer glibc as well,so that would depend on a newer
glibc as well for split-stack to work reliably as  platforms.

Ramana

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Dealing with default recursive procedures in Fortran
  2018-04-12 21:50 Dealing with default recursive procedures in Fortran Thomas König
  2018-04-13 10:11 ` N.M. Maclaren
  2018-04-13 11:08 ` Ramana Radhakrishnan
@ 2018-04-13 12:34 ` Janne Blomqvist
  2018-04-16 17:26 ` Michael Matz
  3 siblings, 0 replies; 5+ messages in thread
From: Janne Blomqvist @ 2018-04-13 12:34 UTC (permalink / raw)
  To: Thomas König; +Cc: fortran, gcc mailing list

On Fri, Apr 13, 2018 at 12:50 AM, Thomas König <tk@tkoenig.net> wrote:

> Hello world,
>
> with Fortran 2018, recursive is becoming the default. This will likely
> have a serious impact on many user codes, which often declare large
> arrays which could then overflow stacks, leading to segfaults without
> further explanation.
>

Yes. For reference, we had some previous discussion about this at
https://gcc.gnu.org/ml/gcc-patches/2017-12/msg01417.html and
https://gcc.gnu.org/ml/fortran/2017-12/msg00082.html .


>
> What could we do? A few options, not all mutally exclusive.
>
> We could extend -fmax-stack-var-size so it allocates memory
> from the heap in recursive procedures, too, and set this to
> some default value.  Of course, it would also have to free them
> afterwards, but we manage that for allocatable arrays already.
>

+1. I think this is the pragmatic approach. It ought to work everywhere,
and should be implementable with modest effort (I did try to have a go at
it, but I'm not that familiar with that part of the frontend, so I didn't
really make any progress).


> We could warn when large arrays with sizes known at compile time
> are translated.
>

+1. Although this shouldn't perhaps be part of -Wall, as it's not a
correctness issue, only a *potential* performance one.


> We could use -fsplit-stack by default. How reliable is that
> option? Can it be used, for example, with -fopenmp?
> Is it available on all (relevant) platforms?
> One drawback would be that this would allow for infinite
> recursions to go on for much longer.
>

Seems not all targets support it, like Ramana said.

Also, IIRC go (the language, that is) originally used split stacks, but at
some point they switched to larger stacks, due to the overhead of checking
the stack usage at every procedure call. And Go isn't even a particularly
performance-oriented language (compared to C/C++/Fortran).


>
> Other ideas / options?
>

Nicks suggestion to have a separate split stack for large and
variable-sized arrays sounds good, although I suspect it would run into the
same portability issues as -fsplit-stack and then some.

So in the short term, I think what ought to be done in rough order of
importance:

1) Make -fmax-stack-var-size use the heap instead of static memory.

2) Make -frecursive the default.

3) Warning for array that is large enough to be allocated on the heap.

4) Run-time error for automatic heap allocation.

Longer term, if somebody has the energy to deal with the (potential)
portability issues, Nicks secondary split stack approach could be good.

-- 
Janne Blomqvist

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Dealing with default recursive procedures in Fortran
  2018-04-12 21:50 Dealing with default recursive procedures in Fortran Thomas König
                   ` (2 preceding siblings ...)
  2018-04-13 12:34 ` Janne Blomqvist
@ 2018-04-16 17:26 ` Michael Matz
  3 siblings, 0 replies; 5+ messages in thread
From: Michael Matz @ 2018-04-16 17:26 UTC (permalink / raw)
  To: Thomas König; +Cc: fortran, gcc mailing list

[-- Attachment #1: Type: text/plain, Size: 548 bytes --]

Hi,

On Thu, 12 Apr 2018, Thomas König wrote:

> with Fortran 2018, recursive is becoming the default. This will likely
> have a serious impact on many user codes, which often declare large
> arrays which could then overflow stacks, leading to segfaults without
> further explanation.

-fopenmp already implies max-stack-var-size=-1 (as -fautomatic is 
default).  Same with -Ofast which enables -fstack-arrays (which 
effectively ignores max-stack-var-size for some arrays).  So maybe the 
impact in the real world won't be large?


Ciao,
Michael.

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2018-04-16 17:26 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-04-12 21:50 Dealing with default recursive procedures in Fortran Thomas König
2018-04-13 10:11 ` N.M. Maclaren
2018-04-13 11:08 ` Ramana Radhakrishnan
2018-04-13 12:34 ` Janne Blomqvist
2018-04-16 17:26 ` Michael Matz

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).