[m-users.] Too Slow
Peter Wang
novalazy at gmail.com
Mon May 11 18:10:13 AEST 2015
Hi,
On Fri, 08 May 2015 13:12:46 +0100, matthias.guedemann at googlemail.com (Matthias Güdemann) wrote:
> Hi Peter,
>
> thank you for your comments, I integrated them with the exception of
> two:
>
> > Most foreign procs could be more succinctly written, e.g.
>
> > :- pragma foreign_proc("C", mp_init(Value::in, Result::out,
> > Mp_Int::out),
> > [will_not_call_mercury, promise_pure, thread_safe],
> > "
> > Mp_Int = MR_GC_NEW_ATTRIB(mp_int, MR_ALLOC_ID);
> > Result = mp_init(Mp_Int);
> > if (Result == MP_OKAY) {
> > Result = mp_set_int(Mp_Int, Value);
> > }
> > ").
>
> I fully agree with you, but I think the C compiler will do that
> anyway. As "--no-c-optimize" must be specified explicitly, I assume
> that at least some optimization will be done normally, and the
> superfluous ints will go away.
Yes. I suggested it for readability.
>
> ,----
> | to_int(A, N) :-
> | ( ( A >= min_int, A =< max_int) ->
> | mp_to_long(A, N)
> | ;
> | fail
> | ).
> |
> | :- pred mp_to_long(mp_int::in, int::out)
> | is det.
> | :- pragma foreign_proc("C",
> | mp_to_long(A::in, N::out),
> | [will_not_call_mercury, promise_pure, thread_safe],
> | "
> | unsigned long n;
> | n = mp_get_long(A);
> | N = (int) n;
> | ").
> `----
>
> > Hmm.
>
> The predicate checks whether the value is between min and max int,
> shouldn't this therefore work? (I added the explicit cast to int at the
> end).
Mercury ints have C type `MR_Integer' which may be wider than C `int',
so the explicit cast to `int' could truncate the value.
On 64-bit Windows it may be the case that
sizeof(unsigned long) < sizeof(MR_Integer)
To avoid truncation, you might have to use the mp_*_long_long functions.
You can check long long is at least as wide as MR_Integer,
at compile-time, with:
:- pragma foreign_code("C", "
MR_STATIC_ASSERT(mp_int, sizeof(unsigned long long) >= sizeof(MR_Integer));
").
mp_init/4 contains a mp_set_int call.
There is a problem with:
mp_int(N) = Res :-
mp_init(abs(N), Res0),
( N < 0 ->
Res = -Res0
;
Res = Res0
).
abs(min_int) will overflow silently or crash the program.
> > It would be preferable to statically allocate the mp_ints for these
> > values. Something like:
>
> > :- pragma foreign_decl("C", local, " static mp_int constant_one;
> > ... ").
>
> > :- initialise init/2.
>
> > :- pred init(io::di, io::uo) is det.
>
> > init(!IO) :- ...
>
> > :- pragma foreign_proc("C", one = (X::out), [ ... ], " X =
> > &constant_one; ").
>
> > But it can be left for later.
>
> this is not done yet. Could this not simply be memoized?
Yes. There's a bit of runtime overhead per call.
Peter
More information about the users
mailing list