[m-users.] How to write stack-friendly mercury-code?
Paul Bone
paul at bone.id.au
Tue Mar 29 23:07:12 AEDT 2016
On Tue, Mar 29, 2016 at 01:30:17PM +0200, Dirk Ziegemeyer wrote:
> Hi Paul,
>
> > Am 28.03.2016 um 12:51 schrieb Paul Bone <paul at bone.id.au>:
> >
> > On Mon, Mar 28, 2016 at 11:51:52AM +0200, Dirk Ziegemeyer wrote:
> >> Hi,
> >>
> >> when I increase the data volume that is processed by a mercury application, the windows-version (asm_fast.gc/i686-w64-mingw32.static) stops at runtime with this error message:
> >>
> >> *** Mercury runtime: caught segmentation violation ***
> >> This may have been caused by a stack overflow, due to unbounded recursion.
> >> exiting from signal handler
> >>
> >> The Mac OS X version (hlc.gc/x86_64-apple-darwin14.5.0) still works.
> >
> > Hi Dirk, There's a couple of things you can do.
>
> Thank you for explaining the options to improve stack usage and especially the examples of non-obvious non-tail-recursive code.
>
> I’m running through these options to see what helps.
>
> > + Enable --last-call-modulo-recursion optimisation (LCMC).
> >
> > This will make map tail recursive by performing the construction [Y | Ys]
> > before the recursive call, and filling in the value Ys in this term
> > within the recursive call.
>
> I wasn’t successful yet with the best option of all: to make the code tail recursive. Call the compiler with command
> „mmc --make --optimize-constructor-last-call“
> didn’t solve it and the problematic part of the code was not apparent to me yet. Is this the option you mean with „--last-call-modulo-recursion“?
>
yes, that's it. I didn't remember the name properly.
> > + Use a segmented stack
> >
> > If you use --stack-segments (an stseg grade component, compatible with
> > low level C grades) then a segmented stack will be used, a segmented
> > stack grows and shrinks as necessary. Unbounded recursion can now cause
> > your computer to thrash, rather than just crashing your program. This
> > is the easiest option, but it doesn't reduce your program's memory usage.
> > It's a good option if the limit is the size of the stack, and not how
> > much RAM you have.
>
> I’ll try the stseg-grade next. This will take me some time because I first need to install this grade for the MingGW-Cross-Compiler.
>
> > + Increase the size of the stack.
> >
> > In low-level graces, like asm_fast, put MERCURY_OPTIONS="--detstack-size
> > N" in your environment. Check the Mercury user's guide.
>
> A fruitless try was to put this in the last line of file Mercury.options:
> MERCURY_OPTIONS = --detstack-size 8192
MERCURY_OPTIONS is an environment veriable. On Linux/BSD/OS X you would do
something like:
$ MERCURY_OPTIONS="--detstack-size 8192" ./my_program
Or
$ export MERCURY_OPTIONS="--detstack-size 8192"
$ ./my_program
I know that windows has environment variables but I don't know how to
set/use them.
> > I've been working on some changes to Mercury that will make it easier for
> > developers to find which parts of their program are potentially causing
> > crashes due to stack exhaustion.
>
> Are your changes available in a recent rotd already? I have to make a new install of Mercury with stseg anyway.
>
Some of them are in this year's ROTDs. All versions have a
--warn-non-tail-recursion option. However this option isn't very smart
about what it reports as a lack of tail recursion. I've tried to improve it
to help it catch the not-obvious things, without reporting the definitly
obvious things.
This option is still likely to be very noisy, so I've added a pragma that
helps control the amount of warnings you will get.
Firstly you can tell it that you _know_ some code is not tail recursive and
you don't want to see a warning for it, because you know it can't be fixed
or isn't why your program crashes.
:- pragma require_tail_recursion(harmless_predicate_name/2, [none]).
Or, if you only want warnings for one or two predicates in your whole
module, then you can add this predicate without the "[none]" option to those
predicates and _not_ execute mercury with --warn-non-tail-recursion:
:- pragma require_tail_recursion(problematic_predicate/2).
There are other things you can do, more information is in the reference
manual, but commented out until the feature is stable:
https://github.com/Mercury-Language/mercury/blob/master/doc/reference_manual.texi#L10592
Cheers.
--
Paul Bone
More information about the users
mailing list