1SetInfoLevel(InfoParkit,2);
2Test1 := function()
3    local   m,  NoOp,  type,  outs;
4
5    m := CreateParkitManager();
6
7    NoOp := function(taskid, m, inputs)
8        Print("Hello World\n");
9        m.finished(taskid);
10    end;
11
12    m.register("NoOp", NoOp, 0);
13    m.submit("NoOp",[],[],0);
14    StopParkitManager(m);
15
16end;
17
18ParListViaParkitDivideAndConquer := function(l, f, chunk)
19    local   m,  emitter,  collector,  worker,  splitter,  joiner,
20            overall,  x,  func,  taskID,  v,  ins, res;
21    m := CreateParkitManager();
22
23    emitter := function(taskID, m, ins)
24        m.provideOutput(1,l,taskID);
25        m.finished(taskID);
26    end;
27
28    collector := function(taskID, m, ins)
29        SyncWrite(v,ins[1]);
30        m.finished(taskID);
31    end;
32
33    worker := function(taskID, m, ins)
34        local   l;
35        l := Length(ins[1]);
36        if l > chunk then
37            m.submit("splitter", [1],["t1","t2"], taskID);
38            m.submit("worker", ["t1"],["u1"],taskID);
39            m.submit("worker", ["t2"],["u2"],taskID);
40            m.submit("joiner", ["u1","u2"],[1], taskID);
41        else
42            m.provideOutput(1, List(ins[1],f), taskID);
43        fi;
44        m.finished(taskID);
45    end;
46
47    splitter := function(taskID, m, ins)
48        local   l,  n;
49        l := Length(ins[1]);
50        n := Int(l/2);
51        m.provideOutput(1,ins[1]{[1..n]},taskID);
52        m.provideOutput(2,ins[1]{[n+1..l]},taskID);
53        m.finished(taskID);
54    end;
55
56    joiner := function(taskID, m, ins)
57        m.provideOutput(1,Concatenation(ins), taskID);
58        m.finished(taskID);
59    end;
60
61    overall := function(taskID, m, ins)
62        m.submit("emitter",[],["t1"], taskID);
63        m.submit("worker",["t1"],["u1"], taskID);
64        m.submit("collector",["u1"],[], taskID);
65        m.finished(taskID);
66    end;
67    for x in [["emitter",emitter], ["collector", collector],
68            ["splitter", splitter], ["joiner", joiner],
69            ["worker", worker], ["overall", overall]] do
70        m.register(x[1],x[2],0);
71    od;
72    v := CreateSyncVar();
73    m.submit("overall",[],[],0,fail);
74    res := SyncRead(v);
75    StopParkitManager(m);
76    return res;
77end;
78
79
80StrassenMult := function(m1,m2, threshold)
81    local   m,  n,  emitter,  collector,  splitter,  joiner,  adder,
82            sub,  multiplier,  overall,  v,  x,  res;
83
84    m := CreateParkitManager();
85    n := Length(m1);
86
87    emitter := x-> function(taskID, m, ins)
88        m.provideOutput(1,x,taskID);
89        m.finished(taskID);
90    end;
91
92    collector := v-> function(taskID, m, ins)
93        SyncWrite(v,ins[1]);
94        m.finished(taskID);
95    end;
96
97    splitter := function(taskID, m, ins)
98        local   t,  n,  l,  s,  z,  pad,  r,  v;
99        t := Runtime();
100        n := Length(ins[1]);
101        l := QuoInt(n+1,2);
102        s := ins[1]{[1..l]}{[1..l]};
103        m.provideOutput(1,s,taskID);
104        z := Zero(ins[1][1][1]);
105        s := ins[1]{[1..l]}{[l+1..n]};
106        pad := n mod 2 = 1;
107        if pad then
108            for r in s do
109                Add(r,z);
110            od;
111        fi;
112        m.provideOutput(2,s,taskID);
113        s := ins[1]{[l+1..n]}{[1..l]};
114        if pad then
115            v := ListWithIdenticalEntries(l,z);
116            Add(s,v);
117        fi;
118        m.provideOutput(3,s,taskID);
119        s := ins[1]{[l+1..n]}{[l+1..n]};
120        if pad then
121            for r in s do
122                Add(r,z);
123            od;
124            Add(s,v);
125        fi;
126        m.provideOutput(4,s,taskID);
127        m.finished(taskID, Runtime() - t);
128    end;
129
130
131       joiner := function(taskID, m, ins)
132           local   l,  f,  s, t;
133           t := Runtime();
134           l := Length(ins[1]);
135           f := DefaultRing(ins[1]);
136           s := NullMat(2*l,2*l,f);
137           s{[1..l]}{[1..l]} := ins[1];
138           m.releaseInput(1,taskID);
139           s{[1..l]}{[l+1..2*l]} := ins[2];
140           m.releaseInput(2,taskID);
141           s{[l+1..2*l]}{[1..l]} := ins[3];
142           m.releaseInput(3,taskID);
143           s{[l+1..2*l]}{[l+1..2*l]} := ins[4];
144           m.releaseInput(4,taskID);
145           m.provideOutput(1,s,taskID);
146           m.finished(taskID, Runtime()-t);
147       end;
148
149       adder := function(taskID, m, ins)
150           local t;
151           t := Runtime();
152           m.provideOutput(1,Sum(ins),taskID);
153           m.finished(taskID, Runtime()-t);
154       end;
155
156       sub := function(taskID, m, ins)
157           local t;
158           t := Runtime();
159           m.provideOutput(1,ins[1]-ins[2],taskID);
160           m.finished(taskID, Runtime()-t);
161       end;
162
163       multiplier := function(taskID, m, ins)
164           local t;
165           t := Runtime();
166           if Length(ins[1]) <= threshold then
167               Perform(ins, TypeObj);
168               m.provideOutput(1,Product(ins), taskID);
169           else
170               m.submit("splitter", [1],["a11","a12","a21","a22"], taskID);
171               m.releaseInput(1,taskID);
172               m.submit("splitter", [2],["b11","b12","b21","b22"], taskID);
173               m.releaseInput(2,taskID);
174               m.submit("adder", ["a11","a22"],["t1"], taskID);
175               m.submit("adder", ["b11","b22"],["t2"], taskID);
176               m.submit("multiplier",["t1","t2"],["m1"],taskID);
177               m.submit("adder",["a21","a22"],["t3"],taskID);
178               m.submit("multiplier",["t3","b11"],["m2"], taskID);
179               m.submit("sub",["b12","b22"],["t4"],taskID);
180               m.submit("multiplier",["a11","t4"],["m3"], taskID);
181               m.submit("sub",["b21","b11"],["t5"],taskID);
182               m.submit("multiplier",["a22","t5"],["m4"], taskID);
183               m.submit("adder",["a11","a12"],["t6"],taskID);
184               m.submit("multiplier",["t6","b22"],["m5"], taskID);
185               m.submit("sub",["a21","a11"],["t7"], taskID);
186               m.submit("adder",["b11","b12"],["t8"],taskID);
187               m.submit("multiplier", ["t7", "t8"], ["m6"], taskID);
188               m.submit("sub",["a12","a22"],["t9"], taskID);
189               m.submit("adder",["b21","b22"],["t10"],taskID);
190               m.submit("multiplier", ["t9", "t10"], ["m7"], taskID);
191
192               m.submit("adder",["m1","m4","m7"],["u1"], taskID);
193               m.submit("sub", ["u1", "m5"], ["c11"], taskID);
194               m.submit("adder", ["m3","m5"], ["c12"], taskID);
195               m.submit("adder", ["m2", "m4"], ["c21"], taskID);
196               m.submit("adder", ["m1", "m3", "m6"], ["u2"], taskID);
197               m.submit("sub", ["u2", "m2"], ["c22"], taskID);
198
199               m.submit("joiner", ["c11","c12", "c21", "c22"], [1], taskID);
200           fi;
201           m.finished(taskID, Runtime() -t );
202       end;
203
204       overall := function(taskID, m, ins)
205           m.submit("emitter1",[],["t1"], taskID);
206           m.submit("emitter2",[],["t2"], taskID);
207           m.submit("multiplier",["t1", "t2"],["u"], taskID);
208           m.submit("collector",["u"],[], taskID);
209           m.finished(taskID);
210       end;
211    v := CreateSyncVar();
212    for x in [["emitter1",emitter(m1)],
213            ["emitter2",emitter(m2)],
214            ["collector", collector(v)],
215            ["splitter", splitter], ["joiner", joiner],
216            ["adder", adder],
217            ["sub", sub],
218            ["multiplier", multiplier],
219            ["overall", overall]] do
220        m.register(x[1],x[2],0);
221    od;
222    m.submit("overall",[],[],0);
223    res := SyncRead(v);
224    StopParkitManager(m);
225    return res{[1..n]}{[1..n]};
226end;
227