[m-rev.] for review: dependent parallel conjunctions (1/2)
Peter Wang
wangp at students.cs.mu.OZ.AU
Sun Jun 25 13:59:00 AEST 2006
On 2006-06-23, Julien Fischer <juliensf at cs.mu.OZ.AU> wrote:
> >
> > compiler/mode_util.m:
> > compiler/modes.m:
> > compiler/unique_modes.m:
> > Update mode, uniqueness checking for dependent parallel conjunctions.
>
> Please provide more details about how the mode checking of parallel
> conjunctions has changed here.
Ok.
> > + % Transforming the parallel conjunction.
> > + %
> > + % As a simple first step, all we do is insert waits and signals directly
> > + % into the conjunction. If a conjunct produces a shared variable we turn
> > + % that conjunct into a sequential conjunction:
> > + %
> > + % prod(Y) ==> ( prod(Y), impure signal(PrY, Y) )
> > + %
> > + % If the conjunct consumes a shared variable we will turn that conjunct
> > + % into a sequential conjunction:
> > + %
> > + % consume(Y) ==> ( wait(PrY, Y), consume(Y) )
> > + %
>
> I think it would be worth documenting the transformtion for an actual
> conjunction as well as specifying the transformation for individual conjuncts.
Not sure what you mean.
> > + % References to shared variables need to be renamed apart so that the
> > + % conjuncts only share promises.
> > + %
> > +:- pred transform_conjunction(module_info::in, set(prog_var)::in,
> > + hlds_goals::in, hlds_goal_info::in, hlds_goal::out, instmap::in,
> > + prog_varset::in, prog_varset::out, vartypes::in, vartypes::out) is det.
> > +
> > +transform_conjunction(ModuleInfo, SharedVars, Goals, GoalInfo, NewGoal,
> > + InstMap, !VarSet, !VarTypes) :-
> > + allocate_promises(ModuleInfo, SharedVars, !VarTypes, !VarSet,
> > + AllocatePromises, PromiseMap),
> > + list.map_foldl3(transform_conjunct(ModuleInfo, SharedVars, PromiseMap),
> > + Goals, NewGoals, InstMap, _, !VarSet, !VarTypes),
> > + % XXX not sure about GoalInfo
>
> What are you not sure about the GoalInfo?
Looking at it again it does seem ok, but I'm never sure about GoalInfos.
> > +:- pred find_changed_vars(module_info::in, list(instmap_delta)::in,
> > + prog_var::in, set(prog_var)::in, set(prog_var)::out) is det.
> > +
> > +find_changed_vars(ModuleInfo, InstMapDeltas, UnboundVar, !SharedVars) :-
> > + (if
> > + % Is the unbound nonlocal bound in one of the conjuncts?
> > + InstMapDelta `member` InstMapDeltas,
>
>
> s/member/list.member/
> (There may be ambiguity problems building the compiler with
> --intermodule-optization otherwise.)
That's not too good. I've changed it.
> > + % Construct type promise(T) given type T.
> > + %
>
> In par_builtin the type is called prom(T) so fix the above comment.
Regarding the other message, 'future' is an alternative to 'promise'
so I'm going with that.
> > +:- pred det_delete_nth(int::in, list(T)::in, list(T)::out) is det.
> > +
> > +det_delete_nth(N, List0, List) :-
> > + list.det_split_list(N, List0, Left, Right),
> > + List = Left ++ det_tail(Right).
>
> Perhaps one for the standard library?
Maybe later.
> > @@ -2431,6 +2432,9 @@
> >
> > maybe_structure_reuse_analysis(Verbose, Stats, !HLDS, !IO),
> > maybe_dump_hlds(!.HLDS, 212, "structure_reuse", !DumpInfo, !IO),
> > +
> > + maybe_dependent_par_conj(Verbose, Stats, !HLDS, !IO),
> > + maybe_dump_hlds(!.HLDS, 214, "dependent_par_conj", !DumpInfo, !IO),
>
> Is this the right spot for this? Can it be performed any earlier or must it
> be done here?
>
> (Note: this occurs well after inlining so none of the calls to the service
> predicates in par_builtin will be inlined. At this stage I don't think it's
> important, but you add a comment at the top of dep_par_conj.m that it should
> be looked at again in the future.)
I'm not sure where it should be. Zoltan suggested I put it fairly late.
But it's true that the primitives really should be inlined.
> > @@ -2793,6 +2794,13 @@
> > !:UseDeps = [MercuryTermSizeProfBuiltin | !.UseDeps]
> > ;
> > true
> > + ),
> > + globals.lookup_bool_option(Globals, parallel, Parallel),
> > + (
> > + Parallel = yes,
> > + !:UseDeps = [MercuryParBuiltin | !.UseDeps]
> > + ;
> > + Parallel = no
> > ).
>
> Won't that also implicitly import the par_builtin module in the high-level
> parallel grades? (I thought that par_builtin was only needed by the
> low-level grades.)
Yes. In the future the module might be useful for other parallel
grades, but I've made it only import in low-level grades for now.
Interdiff follows.
Peter
--- dep_par.0.txt 2006-06-23 19:49:30.000000000 +1000
+++ dep_par.txt 2006-06-24 20:25:34.946507482 +1000
@@ -58,9 +58,14 @@
conjunctions.
compiler/mode_util.m:
+ Treat parallel and plain conjunctions equally when recomputing instmap
+ deltas.
+
compiler/modes.m:
compiler/unique_modes.m:
- Update mode, uniqueness checking for dependent parallel conjunctions.
+ Treat parallel and plain conjunctions equally when checking modes and
+ uniqueness. However, don't flatten parallel conjunctions into plain
+ conjunctions and vice versa.
compiler/simplify.m:
Don't reset instmaps and seen calls after each conjunct of a parallel
diff -u compiler/dep_par_conj.m compiler/dep_par_conj.m
--- compiler/dep_par_conj.m 22 Jun 2006 04:04:20 -0000
+++ compiler/dep_par_conj.m 25 Jun 2006 03:53:06 -0000
@@ -1,7 +1,7 @@
%-----------------------------------------------------------------------------%
% vim: ft=mercury ts=8 sw=4 et
%-----------------------------------------------------------------------------%
-% Copyright (C) 2005-2006 The University of Melbourne.
+% Copyright (C) 2006 The University of Melbourne.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
%-----------------------------------------------------------------------------%
@@ -9,30 +9,40 @@
% File: dep_par_conj.m.
% Author: wangp.
+% This module transforms the HLDS to implement dependent parallel conjunction.
+% The transformation involves adding calls to the predicates defined in
+% library/par_builtin.m.
+%
% For a parallel conjunction (A & B), if the goal B is dependent on a variable
% X which is bound by goal A, we transform the conjunction into the following:
%
-% par_builtin.new_promise(PromiseX),
+% par_builtin.new_future(FutureX),
% (
% (
% A(X), % binds X
-% impure par_builtin.signal(PromiseX, X)
+% impure par_builtin.signal(FutureX, X)
% )
% &
% (
-% par_builtin.wait(PromiseX, X1),
+% par_builtin.wait(FutureX, X1),
% B(X1) % uses X
% )
% )
%
% That is, goal B must wait for the value to be produced by A before it begins
-% executing. This transformation is not just useful in practice (you might as
+% executing. This transformation is not yet useful in practice (you might as
% well use a sequential conjunction). A later version of this transformation
% will move signal and wait calls into goals to, hopefully, actually allow
% parallelism.
%
% If building in a non-parallel grade then dependent parallel conjunctions
% are simply converted into sequential conjunctions.
+%
+% TODO:
+% - move signal and wait calls into goals
+% - only run this pass if parallel conjunctions are present in a module
+% - reconsider when this pass is run; in particular par_builtin primitives
+% ought to be inlined
%-----------------------------------------------------------------------------%
@@ -204,8 +214,8 @@
Goals0, Goals, !IO),
conj_list_to_goal(Goals, GI, Goal)
;
- ConjType = parallel_conj,
- munge_par_conj(ModuleInfo, !VarSet, !VarTypes, InstMap,
+ ConjType = parallel_conj,
+ maybe_transform_par_conj(ModuleInfo, !VarSet, !VarTypes, InstMap,
Goals0, GI, Goal, !IO)
).
@@ -239,38 +249,44 @@
%-----------------------------------------------------------------------------%
- % We found a parallel conjunction. We have to check if there are
- % dependencies between the conjuncts and insert the synchronisation.
+ % We found a parallel conjunction. We need to check there any dependencies
+ % between the conjuncts and, if so, insert sychronisation primitives.
%
-:- pred munge_par_conj(module_info::in, prog_varset::in, prog_varset::out,
- vartypes::in, vartypes::out, instmap::in,
+:- pred maybe_transform_par_conj(module_info::in, prog_varset::in,
+ prog_varset::out, vartypes::in, vartypes::out, instmap::in,
hlds_goals::in, hlds_goal_info::in, hlds_goal::out, io::di, io::uo) is det.
-munge_par_conj(ModuleInfo, !VarSet, !VarTypes, InstMap,
+maybe_transform_par_conj(ModuleInfo, !VarSet, !VarTypes, InstMap,
Conjuncts0, GoalInfo, NewGoal, !IO) :-
% Search subgoals for nested parallel conjunctions.
search_goals_for_par_conj(ModuleInfo, !VarSet, !VarTypes, InstMap,
Conjuncts0, Conjuncts, !IO),
- % Find the variables that are shared between conjunctions.
+ % Find the variables that are shared between conjuncts.
find_shared_variables(ModuleInfo, InstMap, Conjuncts, SharedVars),
% Dependent parallel conjunctions only supported on lowlevel C parallel
% grades. For other grades convert any dependent parallel conjunctions
- % into plain conjunctions.
- globals.io_get_target(Target, !IO),
- globals.io_lookup_bool_option(highlevel_code, HighLevelCode, !IO),
- globals.io_lookup_bool_option(parallel, Parallel, !IO),
+ % into plain conjunctions. Independent parallel conjunctions can be left
+ % as-is.
(if
- set.non_empty(SharedVars),
- Target = target_c,
- HighLevelCode = no,
- Parallel = yes
+ set.empty(SharedVars)
then
- transform_conjunction(ModuleInfo, SharedVars,
- Conjuncts, GoalInfo, NewGoal, InstMap, !VarSet, !VarTypes)
+ par_conj_list_to_goal(Conjuncts, GoalInfo, NewGoal)
else
- conj_list_to_goal(Conjuncts, GoalInfo, NewGoal)
+ globals.io_get_target(Target, !IO),
+ globals.io_lookup_bool_option(highlevel_code, HighLevelCode, !IO),
+ globals.io_lookup_bool_option(parallel, Parallel, !IO),
+ (if
+ Target = target_c,
+ HighLevelCode = no,
+ Parallel = yes
+ then
+ transform_conjunction(ModuleInfo, SharedVars,
+ Conjuncts, GoalInfo, NewGoal, InstMap, !VarSet, !VarTypes)
+ else
+ conj_list_to_goal(Conjuncts, GoalInfo, NewGoal)
+ )
).
% Transforming the parallel conjunction.
@@ -287,7 +303,7 @@
% consume(Y) ==> ( wait(PrY, Y), consume(Y) )
%
% References to shared variables need to be renamed apart so that the
- % conjuncts only share promises.
+ % conjuncts only share futures.
%
:- pred transform_conjunction(module_info::in, set(prog_var)::in,
hlds_goals::in, hlds_goal_info::in, hlds_goal::out, instmap::in,
@@ -295,20 +311,19 @@
transform_conjunction(ModuleInfo, SharedVars, Goals, GoalInfo, NewGoal,
InstMap, !VarSet, !VarTypes) :-
- allocate_promises(ModuleInfo, SharedVars, !VarTypes, !VarSet,
- AllocatePromises, PromiseMap),
- list.map_foldl3(transform_conjunct(ModuleInfo, SharedVars, PromiseMap),
+ allocate_futures(ModuleInfo, SharedVars, !VarTypes, !VarSet,
+ AllocateFutures, FutureMap),
+ list.map_foldl3(transform_conjunct(ModuleInfo, SharedVars, FutureMap),
Goals, NewGoals, InstMap, _, !VarSet, !VarTypes),
- % XXX not sure about GoalInfo
- Conj = AllocatePromises ++ [conj(parallel_conj, NewGoals) - GoalInfo],
+ Conj = AllocateFutures ++ [conj(parallel_conj, NewGoals) - GoalInfo],
conj_list_to_goal(Conj, GoalInfo, NewGoal).
:- pred transform_conjunct(module_info::in, set(prog_var)::in,
- promise_map::in, hlds_goal::in, hlds_goal::out,
+ future_map::in, hlds_goal::in, hlds_goal::out,
instmap::in, instmap::out, prog_varset::in, prog_varset::out,
vartypes::in, vartypes::out) is det.
-transform_conjunct(ModuleInfo, SharedVars, PromiseMap, Goal0, Goal,
+transform_conjunct(ModuleInfo, SharedVars, FutureMap, Goal0, Goal,
!InstMap, !VarSet, !VarTypes) :-
goal_get_nonlocals(Goal0, Nonlocals),
set.intersect(Nonlocals, SharedVars, Intersect),
@@ -325,7 +340,7 @@
Intersect, ProducedVars, ConsumedVars),
% Rename references to consumed variables. We let the producer keep
- % the original name. This helps because there may be references to
+ % the original name in order to avoid having to rename references to
% the original name following the parallel conjunction.
create_variables(set.to_sorted_list(ConsumedVars),
!.VarSet, !.VarTypes,
@@ -333,9 +348,9 @@
rename_vars_in_goal(Renaming, Goal0, Goal1),
% Make wait and signal goals.
- list.map(make_wait(ModuleInfo, PromiseMap, Renaming),
+ list.map(make_wait(ModuleInfo, FutureMap, Renaming),
set.to_sorted_list(ConsumedVars), WaitGoals),
- list.map(make_signal(ModuleInfo, PromiseMap),
+ list.map(make_signal(ModuleInfo, FutureMap),
set.to_sorted_list(ProducedVars), SignalGoals),
% Insert signal goals after the conjunct and waits before the conjunct.
@@ -350,18 +365,18 @@
update_instmap(Goal0, !InstMap)
).
- % Make a goal to wait on a promise for a consumed variable to be produced.
+ % Make a goal to wait on a future for a consumed variable to be produced.
%
-:- pred make_wait(module_info::in, promise_map::in,
+:- pred make_wait(module_info::in, future_map::in,
prog_var_renaming::in, prog_var::in, hlds_goal::out) is det.
-make_wait(ModuleInfo, PromiseMap, Renaming, ConsumedVar, WaitGoal) :-
- map.lookup(PromiseMap, ConsumedVar, PromiseVar),
+make_wait(ModuleInfo, FutureMap, Renaming, ConsumedVar, WaitGoal) :-
+ map.lookup(FutureMap, ConsumedVar, FutureVar),
map.lookup(Renaming, ConsumedVar, WaitVar),
ModuleName = mercury_par_builtin_module,
PredName = "wait",
- Args = [PromiseVar, WaitVar],
+ Args = [FutureVar, WaitVar],
Features = [],
InstMapSrc = [WaitVar - ground(shared, none)],
Context = term.context_init,
@@ -371,15 +386,15 @@
% Make a goal to signal that a variable is produced.
%
-:- pred make_signal(module_info::in, promise_map::in,
+:- pred make_signal(module_info::in, future_map::in,
prog_var::in, hlds_goal::out) is det.
-make_signal(ModuleInfo, PromiseMap, ProducedVar, SignalGoal) :-
- map.lookup(PromiseMap, ProducedVar, PromiseVar),
+make_signal(ModuleInfo, FutureMap, ProducedVar, SignalGoal) :-
+ map.lookup(FutureMap, ProducedVar, FutureVar),
ModuleName = mercury_par_builtin_module,
PredName = "signal",
- Args = [PromiseVar, ProducedVar],
+ Args = [FutureVar, ProducedVar],
Features = [],
InstMapSrc = [],
Context = term.context_init,
@@ -458,7 +473,7 @@
find_changed_vars(ModuleInfo, InstMapDeltas, UnboundVar, !SharedVars) :-
(if
% Is the unbound nonlocal bound in one of the conjuncts?
- InstMapDelta `member` InstMapDeltas,
+ InstMapDelta `list.member` InstMapDeltas,
instmap_delta_search_var(InstMapDelta, UnboundVar, Inst),
inst_is_bound(ModuleInfo, Inst)
then
@@ -469,61 +484,65 @@
%-----------------------------------------------------------------------------%
-:- type promise_map == map(prog_var, prog_var).
+ % A map from a variable to the future object created for that variable.
+ % i.e. for variable X with future F, when X is bound to a value then F is
+ % signalled. A consumer of X waits (blocks) on F until that happens.
+ %
+:- type future_map == map(prog_var, prog_var).
- % Make goals to allocate promise objects for variables shared
+ % Make goals to allocate future objects for variables shared
% between two parallel conjuncts (a producer and one or more consumers).
%
-:- pred allocate_promises(module_info::in, set(prog_var)::in,
+:- pred allocate_futures(module_info::in, set(prog_var)::in,
vartypes::in, vartypes::out, prog_varset::in, prog_varset::out,
- hlds_goals::out, promise_map::out) is det.
+ hlds_goals::out, future_map::out) is det.
-allocate_promises(ModuleInfo, SharedVars, !VarTypes, !VarSet,
- AllocGoals, PromiseMap) :-
- set.fold4(allocate_promise(ModuleInfo), SharedVars,
- !VarTypes, !VarSet, [], AllocGoals, map.init, PromiseMap).
+allocate_futures(ModuleInfo, SharedVars, !VarTypes, !VarSet,
+ AllocGoals, FutureMap) :-
+ set.fold4(allocate_future(ModuleInfo), SharedVars,
+ !VarTypes, !VarSet, [], AllocGoals, map.init, FutureMap).
-:- pred allocate_promise(module_info::in, prog_var::in,
+:- pred allocate_future(module_info::in, prog_var::in,
vartypes::in, vartypes::out, prog_varset::in, prog_varset::out,
- hlds_goals::in, hlds_goals::out, promise_map::in, promise_map::out) is det.
+ hlds_goals::in, hlds_goals::out, future_map::in, future_map::out) is det.
-allocate_promise(ModuleInfo, SharedVar, !VarTypes, !VarSet,
- !AllocGoals, !PromiseMap) :-
+allocate_future(ModuleInfo, SharedVar, !VarTypes, !VarSet,
+ !AllocGoals, !FutureMap) :-
map.lookup(!.VarTypes, SharedVar, SharedVarType),
- make_promise(ModuleInfo, SharedVarType, SharedVar, !VarTypes, !VarSet,
- AllocGoal, PromiseVar),
+ make_future(ModuleInfo, SharedVarType, SharedVar, !VarTypes, !VarSet,
+ AllocGoal, FutureVar),
list.cons(AllocGoal, !AllocGoals),
- svmap.det_insert(SharedVar, PromiseVar, !PromiseMap).
+ svmap.det_insert(SharedVar, FutureVar, !FutureMap).
-:- pred make_promise(module_info::in, mer_type::in, prog_var::in, vartypes::in,
+:- pred make_future(module_info::in, mer_type::in, prog_var::in, vartypes::in,
vartypes::out, prog_varset::in, prog_varset::out, hlds_goal::out,
prog_var::out) is det.
-make_promise(ModuleInfo, SharedVarType, SharedVar, !VarTypes, !VarSet,
- AllocGoal, PromiseVar) :-
- construct_promise_type(SharedVarType, PromiseType),
+make_future(ModuleInfo, SharedVarType, SharedVar, !VarTypes, !VarSet,
+ AllocGoal, FutureVar) :-
+ construct_future_type(SharedVarType, FutureType),
varset.lookup_name(!.VarSet, SharedVar, SharedVarName),
- svvarset.new_named_var("Promise" ++ SharedVarName, PromiseVar, !VarSet),
- svmap.det_insert(PromiseVar, PromiseType, !VarTypes),
+ svvarset.new_named_var("Future" ++ SharedVarName, FutureVar, !VarSet),
+ svmap.det_insert(FutureVar, FutureType, !VarTypes),
ModuleName = mercury_par_builtin_module,
- PredName = "new_promise",
- Args = [PromiseVar],
+ PredName = "new_future",
+ Args = [FutureVar],
Features = [],
- InstMapSrc = [PromiseVar - ground(shared, none)],
+ InstMapSrc = [FutureVar - ground(shared, none)],
Context = term.context_init,
goal_util.generate_simple_call(ModuleName, PredName, predicate,
only_mode, det, Args, Features, InstMapSrc, ModuleInfo,
Context, AllocGoal).
- % Construct type promise(T) given type T.
+ % Construct type future(T) given type T.
%
-:- pred construct_promise_type(mer_type::in, mer_type::out) is det.
+:- pred construct_future_type(mer_type::in, mer_type::out) is det.
-construct_promise_type(T, PromiseT) :-
- Prom = qualified(mercury_private_builtin_module, "prom"),
- PromiseCtor = type_ctor(Prom, 1),
- construct_type(PromiseCtor, [T], PromiseT).
+construct_future_type(T, FutureT) :-
+ Future = qualified(mercury_par_builtin_module, "future"),
+ FutureCtor = type_ctor(Future, 1),
+ construct_type(FutureCtor, [T], FutureT).
%-----------------------------------------------------------------------------%
diff -u compiler/mode_util.m compiler/mode_util.m
--- compiler/mode_util.m 18 Jun 2006 08:19:48 -0000
+++ compiler/mode_util.m 23 Jun 2006 13:15:30 -0000
@@ -1008,18 +1008,10 @@
VarTypes, InstMap, NonLocals, InstMapDelta, !RI)
).
-recompute_instmap_delta_2(Atomic, conj(ConjType, Goals0), GoalInfo,
+recompute_instmap_delta_2(Atomic, conj(ConjType, Goals0), _GoalInfo,
conj(ConjType, Goals), VarTypes, InstMap, InstMapDelta, !RI) :-
- (
- ConjType = plain_conj,
- recompute_instmap_delta_conj(Atomic, Goals0, Goals,
- VarTypes, InstMap, InstMapDelta, !RI)
- ;
- ConjType = parallel_conj,
- goal_info_get_nonlocals(GoalInfo, NonLocals),
- recompute_instmap_delta_par_conj(Atomic, Goals0, Goals,
- VarTypes, InstMap, NonLocals, InstMapDelta, !RI)
- ).
+ recompute_instmap_delta_conj(Atomic, Goals0, Goals,
+ VarTypes, InstMap, InstMapDelta, !RI).
recompute_instmap_delta_2(Atomic, disj(Goals0), GoalInfo, disj(Goals),
VarTypes, InstMap, InstMapDelta, !RI) :-
@@ -1145,29 +1137,6 @@
%-----------------------------------------------------------------------------%
-:- pred recompute_instmap_delta_par_conj(bool::in, list(hlds_goal)::in,
- list(hlds_goal)::out, vartypes::in, instmap::in, set(prog_var)::in,
- instmap_delta::out, recompute_info::in, recompute_info::out) is det.
-
-recompute_instmap_delta_par_conj(_, [], [], _, _, _, InstMapDelta, !RI) :-
- instmap_delta_init_unreachable(InstMapDelta).
-recompute_instmap_delta_par_conj(Atomic, [Goal0], [Goal],
- VarTypes, InstMap, _, InstMapDelta, !RI) :-
- recompute_instmap_delta_1(Atomic, Goal0, Goal, VarTypes, InstMap,
- InstMapDelta, !RI).
-recompute_instmap_delta_par_conj(Atomic, [Goal0 | Goals0], [Goal | Goals],
- VarTypes, InstMap0, NonLocals, InstMapDelta, !RI) :-
- Goals0 = [_ | _],
- recompute_instmap_delta_1(Atomic, Goal0, Goal,
- VarTypes, InstMap0, InstMapDelta0, !RI),
- instmap.apply_instmap_delta(InstMap0, InstMapDelta0, InstMap1),
- recompute_instmap_delta_par_conj(Atomic, Goals0, Goals,
- VarTypes, InstMap1, NonLocals, InstMapDelta1, !RI),
- instmap_delta_apply_instmap_delta(InstMapDelta0, InstMapDelta1,
- large_overlay, InstMapDelta).
-
-%-----------------------------------------------------------------------------%
-
:- pred recompute_instmap_delta_disj(bool::in, list(hlds_goal)::in,
list(hlds_goal)::out, vartypes::in, instmap::in, set(prog_var)::in,
instmap_delta::out, recompute_info::in, recompute_info::out) is det.
diff -u compiler/modes.m compiler/modes.m
--- compiler/modes.m 19 Jun 2006 04:19:03 -0000
+++ compiler/modes.m 23 Jun 2006 08:13:52 -0000
@@ -1293,7 +1293,7 @@
;
ConjType = parallel_conj,
mode_checkpoint(enter, "par_conj", !ModeInfo, !IO),
- % empty parallel conjunction should not be a common case
+ % Empty parallel conjunction should not be a common case.
modecheck_conj_list(ConjType, Goals0, Goals, !ModeInfo, !IO),
par_conj_list_to_goal(Goals, GoalInfo0, Goal - _GoalInfo),
mode_checkpoint(exit, "par_conj", !ModeInfo, !IO)
@@ -2016,7 +2016,7 @@
:- type impurity_errors == list(mode_error_info).
- % Flatten conjunctions as we go, as long as they are of the same type).
+ % Flatten conjunctions as we go, as long as they are of the same type.
% Call modecheck_conj_list_3 to do the actual scheduling.
%
:- pred modecheck_conj_list_2(conj_type::in,
diff -u compiler/modules.m compiler/modules.m
--- compiler/modules.m 21 Jun 2006 06:35:35 -0000
+++ compiler/modules.m 23 Jun 2006 09:31:51 -0000
@@ -2795,12 +2795,17 @@
;
true
),
+ globals.get_target(Globals, Target),
+ globals.lookup_bool_option(Globals, highlevel_code, HighLevelCode),
globals.lookup_bool_option(Globals, parallel, Parallel),
(
- Parallel = yes,
+ Target = target_c,
+ HighLevelCode = no,
+ Parallel = yes
+ ->
!:UseDeps = [MercuryParBuiltin | !.UseDeps]
;
- Parallel = no
+ true
).
:- pred contains_tabling_pragma(item_list::in) is semidet.
diff -u compiler/par_conj_gen.m compiler/par_conj_gen.m
--- compiler/par_conj_gen.m 19 Jun 2006 12:26:13 -0000
+++ compiler/par_conj_gen.m 23 Jun 2006 09:41:35 -0000
@@ -262,9 +262,9 @@
% XXX at the moment we are copying back too much. Conjuncts which
% are only consumers of variable X should not be copying it back.
%
- % Also, variables which are shared (i.e. we allocate a promise for
+ % Also, variables which are shared (i.e. we allocate a future for
% it) do not need copying back if we take the address of the
- % shared variable and store it in the promise, then write
+ % shared variable and store it in the future, then write
% to that address on `signal' or the last `wait'.
%
:- pred copy_outputs(code_info::in, list(prog_var)::in, lval::in,
diff -u library/par_builtin.m library/par_builtin.m
--- library/par_builtin.m 21 Jun 2006 09:17:49 -0000
+++ library/par_builtin.m 23 Jun 2006 10:52:52 -0000
@@ -28,11 +28,26 @@
:- interface.
-:- type prom(T).
+:- type future(T).
-:- pred new_promise(prom(T)::uo) is det.
-:- pred wait(prom(T)::in, T::out) is det.
-:- impure pred signal(prom(T)::in, T::in) is det.
+ % Allocate a new future object. A future acts as a intermediary for a
+ % shared variable between parallel conjuncts, when one conjunct produces
+ % the value for other conjuncts.
+ %
+:- pred new_future(future(T)::uo) is det.
+
+ % wait(Future, Value)
+ % Wait until Future is signalled, blocking if necessary. Then the value
+ % bound to the variable associated with the future is bound to Value.
+ %
+:- pred wait(future(T)::in, T::out) is det.
+
+ % Notify that the variable associated with the given future has been bound
+ % to a value. Threads waiting on the future will be woken. Future waits
+ % on the future will succeed immediately. A future can only be signalled
+ % once.
+ %
+:- impure pred signal(future(T)::in, T::in) is det.
%-----------------------------------------------------------------------------%
@@ -40,14 +55,14 @@
:- pragma foreign_decl("C",
"
- typedef struct MR_Promise MR_Promise;
+ typedef struct MR_Future MR_Future;
#ifdef MR_THREAD_SAFE
# ifdef MR_HAVE_SEMAPHORE_H
/* POSIX 1003.1b semaphores available. */
#include <semaphore.h>
- struct MR_Promise {
+ struct MR_Future {
sem_t semaphore;
MR_Word value;
};
@@ -55,74 +70,75 @@
/* Use POSIX thread mutexes and condition variables. */
#include <pthread.h>
- struct MR_Promise {
+ struct MR_Future {
pthread_mutex_t mutex;
pthread_cond_t cond;
MR_Word value;
};
# endif /* !MR_HAVE_SEMAPHORE_H */
#else /* !MR_THREAD_SAFE */
- struct MR_Promise {
+ struct MR_Future {
};
#endif /* !MR_THREAD_SAFE */
").
-:- pragma foreign_type("C", prom(T), "MR_Promise *").
+:- pragma foreign_type("C", future(T), "MR_Future *",
+ [can_pass_as_mercury_type]).
% Placeholder only.
-:- pragma foreign_type(il, prom(T), "class [mscorlib]System.Object").
+:- pragma foreign_type(il, future(T), "class [mscorlib]System.Object").
:- pragma foreign_proc("C",
- new_promise(Promise::uo),
+ new_future(Future::uo),
[will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail],
"
#ifdef MR_THREAD_SAFE
# ifdef MR_HAVE_SEMAPHORE_H
- Promise = MR_GC_NEW(MR_Promise);
- sem_init(&Promise->semaphore, MR_NO, 0);
- Promise->value = 0;
+ Future = MR_GC_NEW(MR_Future);
+ sem_init(&Future->semaphore, MR_NO, 0);
+ Future->value = 0;
# else
- Promise = MR_GC_NEW(MR_Promise);
- pthread_mutex_init(&Promise->mutex, NULL);
- pthread_cond_init(&Promise->cond, NULL);
- Promise->value = 0;
+ Future = MR_GC_NEW(MR_Future);
+ pthread_mutex_init(&Future->mutex, NULL);
+ pthread_cond_init(&Future->cond, NULL);
+ Future->value = 0;
# endif
#endif
").
:- pragma foreign_proc("C",
- wait(Promise::in, Value::out),
+ wait(Future::in, Value::out),
[will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail],
"
#ifdef MR_THREAD_SAFE
# ifdef MR_HAVE_SEMAPHORE_H
- sem_wait(&Promise->semaphore);
- sem_post(&Promise->semaphore);
- Value = Promise->value;
+ sem_wait(&Future->semaphore);
+ sem_post(&Future->semaphore);
+ Value = Future->value;
# else
- pthread_mutex_lock(&Promise->mutex);
- while (!Promise->pass) {
- pthread_cond_wait(&Promise->cond, &Promise->mutex);
+ pthread_mutex_lock(&Future->mutex);
+ while (!Future->pass) {
+ pthread_cond_wait(&Future->cond, &Future->mutex);
}
- Value = Promise->value;
- pthread_mutex_unlock(&Promise->mutex);
+ Value = Future->value;
+ pthread_mutex_unlock(&Future->mutex);
# endif
#endif
").
:- pragma foreign_proc("C",
- signal(Promise::in, Value::in),
+ signal(Future::in, Value::in),
[will_not_call_mercury, thread_safe, will_not_modify_trail],
"
#ifdef MR_THREAD_SAFE
# ifdef MR_HAVE_SEMAPHORE_H
- Promise->value = Value;
- sem_post(&Promise->semaphore);
+ Future->value = Value;
+ sem_post(&Future->semaphore);
# else
- pthread_mutex_lock(&Promise->mutex);
- Value = Promise->value;
- pthread_cond_broadcast(&Promise->cond);
- pthread_mutex_unlock(&Promise->mutex);
+ pthread_mutex_lock(&Future->mutex);
+ Value = Future->value;
+ pthread_cond_broadcast(&Future->cond);
+ pthread_mutex_unlock(&Future->mutex);
# endif
#endif
").
diff -u library/private_builtin.m library/private_builtin.m
--- library/private_builtin.m 13 Jun 2006 15:46:40 -0000
+++ library/private_builtin.m 23 Jun 2006 08:28:55 -0000
@@ -16,7 +16,7 @@
% implementing polymorphism, unification, compare/3, etc.
% Note that the builtins used for tabling, deep profiling and parallelism are
% in separate modules (table_builtin.m, profiling_builtin.m and
-% par_builting.m).
+% par_builtin.m).
% This module is a private part of the Mercury implementation; user modules
% should never explicitly import this module. The interface for this module
diff -u mdbcomp/program_representation.m mdbcomp/program_representation.m
--- mdbcomp/program_representation.m 18 Jun 2006 11:33:05 -0000
+++ mdbcomp/program_representation.m 23 Jun 2006 12:50:13 -0000
@@ -334,6 +334,13 @@
% implemented by foreign language code in the standard library.
% For some, but not all, the compiler generates code inline.
%
+ % If you are adding a predicate to no_type_info_builtin, remember that
+ % this will only affect code built by a compiler linked with the new
+ % mdbcomp library. e.g. if you add a predicate P to no_type_info_builtin,
+ % the compiler building the stage 1 library won't yet know about P.
+ % The stage 1 compiler _will_ know about P, so stage 2 is when P will
+ % be compiled differently.
+ %
:- pred no_type_info_builtin(module_name::in, string::in, int::in) is semidet.
%-----------------------------------------------------------------------------%
@@ -573,7 +580,7 @@
no_type_info_builtin_2(table_builtin, "table_lookup_insert_typeinfo", 3).
no_type_info_builtin_2(table_builtin, "table_lookup_insert_typeclassinfo", 3).
no_type_info_builtin_2(term_size_prof_builtin, "increment_size", 2).
-no_type_info_builtin_2(par_builtin, "new_promise", 1).
+no_type_info_builtin_2(par_builtin, "new_future", 1).
no_type_info_builtin_2(par_builtin, "wait", 2).
no_type_info_builtin_2(par_builtin, "signal", 2).
--------------------------------------------------------------------------
mercury-reviews mailing list
post: mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------
More information about the reviews
mailing list