Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 165 lines (133 sloc) 5.134 kB
fccc685 Initial open-source release
MLstate authored
1 (*
2 Copyright © 2011 MLstate
3
4 This file is part of OPA.
5
6 OPA is free software: you can redistribute it and/or modify it under the
7 terms of the GNU Affero General Public License, version 3, as published by
8 the Free Software Foundation.
9
10 OPA is distributed in the hope that it will be useful, but WITHOUT ANY
11 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
13 more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with OPA. If not, see <http://www.gnu.org/licenses/>.
17 *)
18 (*
19 @author Louis Gesbert
20 **)
21
22 (* temporary place-holder (see mli) *)
23
24 type 'a t = {
25 items : 'a array;
26 flat_replication : int;
27 }
28
29 type key = int (* keep this abstract *)
30
31 let create ~flat_replication items = {
32 items = Array.of_list items;
33 flat_replication = flat_replication;
34 }
35
36 (* todo: move somewhere else *)
37 module Parallel_schedule = struct
38 open Cps.Ops
39
40 (** Runs a set of cps functions in parallel, ending with a barrier then
41 a single continuation. Returns right away.
42
43 Provided "iter" function should iter on all the tasks you want to run. It
44 should never schedule, this function assumes it is atomic (consistently,
45 it's not CPS). For example, to execute function [f] in parallel over array
46 [arr], you would use the iter function
47 [(fun g -> Array.iter (fun x -> g (f x)) arr)] *)
48 let iter sched (iter: (unit Cps.t -> unit) -> unit) (k: unit -> unit) =
49 let n = ref 0 in
50 let k () = decr n; if !n > 0 then () else k () in
51 iter (fun f -> incr n; Scheduler.push sched (fun () -> f @> k))
52
53 (** Same as iter but passes the array of results to the continuation. *)
54 let map sched (iter: ('a Cps.t -> unit) -> unit) (k: 'a array -> unit) =
55 let n = ref 0 in
56 let results = ref [||] in
57 let ki =
58 fun i x ->
59 !results.(i) <- Some x;
60 decr n;
61 if !n > 0 then () else Array.map Option.get !results |> k
62 in
63 iter
64 (fun f ->
65 let i = !n in incr n;
66 Scheduler.push sched (fun () -> f @> ki i));
67 results := Array.make !n None
68
69 (** Same as map but reduces the results with the given operator. Order
70 of reduction is {b not} guaranteed, you should probably use an associative,
71 commutative operator. *)
72 let reduce sched
73 (iter: ('a Cps.t -> unit) -> unit)
74 (op: 'acc -> 'a -> 'acc)
75 (acc: 'acc)
76 (k: 'acc -> unit) =
77 let n = ref 0 in
78 let acc = ref acc in
79 let k x = acc := op !acc x; decr n; if !n > 0 then () else !acc |> k in
80 iter (fun f -> incr n; Scheduler.push sched (fun () -> f @> k))
81
82 let map_reduce sched
83 (iter: ('a Cps.t -> unit) -> unit)
84 (op: 'acc -> 'a -> 'b * 'acc)
85 (acc: 'acc)
86 (k: 'b array * 'acc -> unit) =
87 let n = ref 0 in
88 let acc_ref = ref acc in
89 let results = ref [||] in
90 let ki =
91 fun i x ->
92 let elt_i, acc = op !acc_ref x in
93 acc_ref := acc;
94 !results.(i) <- Some elt_i;
95 decr n;
96 if !n > 0 then () else (Array.map Option.get !results, !acc_ref) |> k
97 in
98 iter
99 (fun f ->
100 let i = !n in incr n;
101 Scheduler.push sched (fun () -> f @> ki i));
102 results := Array.make !n None
103 end
104
105 let to_list t = Array.to_list t.items
106
107 module P = Parallel_schedule
108 open Cps.Ops
109
110 let sched = Scheduler.default
111
112 let iter t f k = P.iter sched (fun g -> Array.iter (fun x -> g (f x)) t.items) @> k
113
114 let sequential_iter t f = Array.iter (fun x -> f x @> fun _ -> ()) t.items
115
116 let map t f k =
117 P.map sched (fun g -> Array.iter (fun x -> g (f x)) t.items)
118 @> fun arr -> { t with items = arr } |> k
119
120 let mapi t f k =
121 P.map sched (fun g -> Array.iteri (fun key x -> g (f key x)) t.items)
122 @> fun arr -> { t with items = arr } |> k
123
124 let reduce t op acc f k =
125 P.reduce sched (fun g -> Array.iter (fun x -> g (f x)) t.items)
126 op acc @> k
127
128 let map_reduce t op acc f k =
129 P.map_reduce sched (fun g -> Array.iter (fun x -> g (f x)) t.items) op acc
130 @> fun (arr,res) -> ({ t with items = arr }, res) |> k
131
132
133 let who_has t (path: Path.t) =
134 (Hashtbl.hash path mod
135 (Array.length t.items / t.flat_replication))
136 (* * Random.int t.flat_replication
137 -- we should take always the same random within a transaction *)
138
139 let who_has_all t (path: Path.t) =
140 let offset = who_has t path in
141 let chunksize = Array.length t.items / t.flat_replication in
142 Base.List.init t.flat_replication
143 (fun i -> i * chunksize + offset)
144
145 let at_path t path f k =
146 let key = who_has t path in
147 f key t.items.(key) @> k
148
149 let mapi_path t path f k =
150 let where = who_has_all t path in
151 P.map sched (fun g -> List.iter (fun key -> g (f key t.items.(key))) where)
152 @> fun results ->
153 let arr = Array.copy t.items in
154 Base.List.iteri (fun key i -> arr.(key) <- results.(i)) where;
155 { t with items = arr } |> k
156
157 let get_key t key = t.items.(key)
158
159 let set_key t key value =
160 let arr = Array.copy t.items in
161 t.items.(key) <- value;
162 { t with items = arr }
163
164 let push_key t key value = t.items.(key) <- value
Something went wrong with that request. Please try again.