[mercury-users] SICStus vs Mercury
Fergus Henderson
fjh at cs.mu.OZ.AU
Mon Sep 25 21:30:35 AEDT 2000
On 20-Sep-2000, Mattias Waldau <mattias.waldau at abc.se> wrote:
> I selected to test Mercury by implementing a simple genetic program,
> currently it sorts an array. The program can be found at the links below.
> I selected this problem, since the program was deterministic and very moded.
> It is a perfect candidate for Mercury.
...
> Mercury is about 3 times faster than SICStus on this problem. I expected
> more since the program is completely deterministic. Maybe one of the
> developers of Mercury or HAL should include this program into their test
> suite and try to understand why the difference isn't bigger.
>
> http://www.abc.se/~m10217/download/genetic_test.pl
> http://www.abc.se/~m10217/download/genetic_test.m
Well, to start with, make sure you compile the Mercury version with
all optimizations enabled, e.g. using the following Mmakefile
$ cat Mmakefile
MCFLAGS = -O6 --intermodule-optimization
CFLAGS = -DML_OMIT_ARRAY_BOUNDS_CHECKS
> P.P.s. Comments on how to make the Mercury-programs better is appreciated.
The first step is to run the profiler:
$ mmake GRADEFLAGS=--profiling
$ ./genetic_test
$ mprof | less
$ mprof -c | less
This quickly shows that this program is "map-limited", i.e. it is spending
most of its time in map__insert, specifically the calls from mate_copy/7.
The following patch, which changes the program to use an array rather
than a map for representing the set of ints, improved the speed of the
program by a factor of about 3.5.
There was a similar performance problem in the standard library
predicate random__permutation -- it was using a map when an array
would have been faster. I have fixed that in the latest development
version of the Mercury compiler. That change improved the speed
a bit more, up to about 5.5 times the speed of the original.
Cheers,
Fergus.
--- genetic_test.m.orig Mon Sep 25 18:22:35 2000
+++ genetic_test.m Mon Sep 25 18:49:24 2000
@@ -527,18 +528,18 @@
%%% between Start and Stop in Master is copied to Copy. Copied is a tree
%%% of all the positions copied, which will be used to fast lookup.
:- pred mate_copy(int::in, int::in, array(int)::in,
- array(int)::array_uo, map(int,int)::out
+ array(int)::array_uo, intset::intset_uo
) is det.
mate_copy(Start, Stop, Master, NewCopy, NewCopied) :-
%% create an initial empty Copy
array__init(array__size(Master), -1, Copy),
- map__init(Copied),
+ intset_init(array_max_elem(Master) + 1, Copied),
mate_copy(Start, Stop, Master, Copy, NewCopy, Copied, NewCopied).
:- pred mate_copy(int::in, int::in, array(int)::in,
array(int)::array_di, array(int)::array_uo,
- map(int,int)::in, map(int,int)::out
- ) is det.
+ intset::intset_di, intset::intset_uo
+ ) is det.
mate_copy(Current, Stop, Master, Copy, NewCopy, Copied, NewCopied) :-
(
Current > Stop
@@ -548,13 +549,38 @@
;
Element = array__lookup(Master, Current),
array__set(Copy, Current, Element, Copy2),
- map__det_insert(Copied, Element, 1, Copied2),
+ intset_add(Copied, Element, Copied2),
mate_copy(Current+1, Stop, Master, Copy2, NewCopy, Copied2, NewCopied)
).
+:- func array_max_elem(array(int)) = int.
+array_max_elem(Array) = array_max_elem_2(Array, MinInt, 0, array__size(Array)) :-
+ int__min_int(MinInt).
+
+:- func array_max_elem_2(array(int), int, int, int) = int.
+array_max_elem_2(Array, Max0, Count, Size) = Max :-
+ ( Count = Size ->
+ Max = Max0
+ ;
+ Elem = array__lookup(Array, Count),
+ int__max(Max0, Elem, Max1),
+ Max = array_max_elem_2(Array, Max1, Count + 1, Size)
+ ).
-
-
+:- type intset == array(bool).
+:- mode intset_di == array_di.
+:- mode intset_uo == array_uo.
+
+:- pred intset_init(int::in, intset::array_uo) is det.
+intset_init(Size, IntSet) :- array__init(Size, no, IntSet).
+
+:- pred intset_add(intset::array_di, int::in, intset::array_uo).
+intset_add(IntSet0, Elem, IntSet) :-
+ array__set(IntSet0, Elem, yes, IntSet).
+
+:- pred intset_contains(intset::in, int::in) is semidet.
+intset_contains(IntSet, Elem) :-
+ array__lookup(IntSet, Elem, yes).
%%% mate_otherhalf(Start, Stop, Master, Copy, Copied, NewCopy, Duplicates, Empty) is true if all elements
%%% in Master between Start and Stop os copied into Copy, the result is NewCopy.
@@ -565,7 +591,7 @@
%%%
%%% I had to change arg 3 from array_di to in, since I only know in!
:- pred mate_otherhalf(int::in, int::in, array(int)::in,
- array(int)::array_di, map(int,int)::in,
+ array(int)::array_di, intset::in,
array(int)::array_uo, list(int)::out, list(int)::out
) is det.
mate_otherhalf(Start, Stop, Master, Copy, Copied,
@@ -579,7 +605,7 @@
;
Element = array__lookup(Master, Start),
(
- map__search(Copied, Element, _) %could use map__member
+ intset_contains(Copied, Element)
->
%% this value already exists
mate_otherhalf(Start+1, Stop, Master, Copy, Copied,
--
Fergus Henderson <fjh at cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3 | -- the last words of T. S. Garp.
--------------------------------------------------------------------------
mercury-users mailing list
post: mercury-users at cs.mu.oz.au
administrative address: owner-mercury-users at cs.mu.oz.au
unsubscribe: Address: mercury-users-request at cs.mu.oz.au Message: unsubscribe
subscribe: Address: mercury-users-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------
More information about the users
mailing list