[m-users.] seg fault, 64 bit
Tomas By
tomas at basun.net
Sat Jun 8 09:31:15 AEST 2013
Hi,
Thanks for the reply. I am using the default grade (asm_fast?)
What confuses me is that it is not that much data, and 3GB is a ridiculous
amount of stack. I have run (what I believe to be) bigger computations on
32 bit machines with less than a GB total memory (this machine has 8GB).
I do not have any tail(or mistakenly non-tail)-recursive functions in my
code, only foldl's and traversal of recursive data structures.
The code that causes the problem is this:
| :- type tnfstats--->
tnfs(vstats,vstats,vstats,vstats,map(int,int),map(reftype,int)).
| :- type vstats ---> vs(int,int,int,map(string,int),int,int).
| :- func new_vs = vstats.
| new_vs = vs(0,0,0,map.init,0,0).
|
| :- pred tnfiles_stats(list(tnfile)::in,tnfstats::out) is det.
| tnfiles_stats(Fs,Stats) :-
| Stats0 = tnfs(new_vs,new_vs,new_vs,new_vs,map.init,map.init),
| foldl(tnfile_stats,Fs,Stats0,Stats1),
| Stats1 = tnfs(SS,PS,OS,RS,Cmap,Rmap),
| map.foldl((pred(_::in,V::in,M0::in,M::out) is det :-
| ( map.search(M0,V,N) ->
| map.det_update(V,N+1,M0,M)
| ; map.det_insert(V,1,M0,M) )),Cmap,map.init,Imap),
| Stats = tnfs(SS,PS,OS,RS,Imap,Rmap).
|
| :- pred tnfile_stats(tnfile::in,tnfstats::in,tnfstats::out) is det.
| tnfile_stats(file(_,Chunks),!Stats) :-
| foldl(chunk_stats,Chunks,!Stats).
|
| :- pred chunk_stats(chunk::in,tnfstats::in,tnfstats::out) is det.
| chunk_stats(chunk(_,_,_,_,_,Triples),!Stats) :-
| foldl(triple_stats,Triples,!Stats).
where triple_stats/3 updates the tnfstats (no recursive calls).
Should I use some other data structure than map's?
The tnfile's vary a bit in size (by a factor ten or so), and there are
around a thousand of them.
Shouldn't the stack be back to `zero' at each iteration of
`foldl(tnfile_stats,Fs,Stats0,Stats1)' ?
If not, how does your suggestion to split the loops help?
(Will try your other suggestions)
/Tomas
On Sat, June 8, 2013 00:57, Paul Bone wrote:
> On Fri, Jun 07, 2013 at 08:38:55PM +0200, Tomas By wrote:
>> Hi all,
>>
>> I am getting this error on Ubuntu 64 bit, with Mercury 13.05:
>>
>> | *** Mercury runtime: caught segmentation violation ***
>> | cause: address not mapped to object
>> | address involved: (nil)
>> | This may have been caused by a stack overflow, due to unbounded
>> recursion.
>> | exiting from signal handler
>> | Segmentation fault (core dumped)
>>
>> with these settings:
>>
>> | MERCURY_OPTIONS=--detstack-size 3000000 --nondetstack-size 3000000
>>
>> and this amount of data (output of wc):
>>
>> | 289358 1735415 33502285 total
>>
>> Does this behaviour seem reasonable?
>>
>
> Although you describe your data in your later e-mail, remember that stack
> usage does not have to correlate with data size. It is possible (and
> easy) to create a very small program that exhausts the stack size.
>
>> Any ideas about anything I can change?
>
> I will assume that the segfault is definitely caused by a stack overflow,
> there is no proof that this is the case. However you say that running on
> a
> single data file does not make the program crash, so it is a likely cause.
>
> We have a stack segments grade that allows the runtime system to use a
> dynamic amount of stack size. Try compiling with the grade flag
> --stack-segments or add .stseg to your low-level C grade string. Note
> that
> the high-level C grades always use C's stack (--(non)detstack-size will
> not
> help). This can be useful if you need just that tiny bit more stack size,
> or if you want to avoid tuning or configuration when you distribute the
> program.
>
> Not all 'last calls' are tail cails. Consider:
>
> map(_, [], []).
> map(P, [X | Xs], [Y | Ys]) :-
> P(X, Y),
> map(P, Xs, Ys).
>
> Looks tail recursive right? It's not. The construction of [Y | Ys]
> must occur after the recursive call to map. (This is not true in
> Prolog). So it can be easy to write non tail recursive code. This can be
> fixed by using the Last Call Modulo Construction (LCMC) optimisation. Try
> enabling this optimisation (See the user guide).
>
> To find out which recursions are very deep (but may or may not be tail
> calls) try using the debugger. Run your program until it crashes, look at
> the last event number, run the program again stepping over this many minus
> about 100 events and the program's state will be near the point at which
> it
> crashed. Then give the 'stack' command to see a list of stack frames.
> The
> stack command will show you recursive and mutually recursive parts of your
> program, along with how deep the recursions are.
>
> Some code such as the map example above, even if it's not tail recursive,
> can be made to use less stack space with a simple transformation. Take
> your
> existing loop and make two nested loops. Make the inner loop return after
> so many iterations, say 100,000. Then in the next iteration of the outer
> loop call the inner loop again to work on some more of the input.
>
>
>>
>> Is there another way to set the stack sizes? It seems that MCFLAGS in
>> Mmake no longer works.
>
> I thought it was always in MERCURY_OPTIONS which is used at runtime.
> I think, but aren't certain, that defaults for MERCURY_OPTIONS can be set
> in
> mkinit's parameters.
>
> Good luck.
>
>
> --
> Paul Bone
> http://www.bone.id.au
>
More information about the users
mailing list