1 | //////////////////////////////////////////////////////////////////// |
---|
2 | version="version parallel.lib 4.0.0.0 Dec_2013 "; // $Id$ |
---|
3 | category="General purpose"; |
---|
4 | info=" |
---|
5 | LIBRARY: parallel.lib An abstraction layer for parallel skeletons |
---|
6 | |
---|
7 | AUTHOR: Andreas Steenpass, e-mail: steenpass@mathematik.uni-kl.de |
---|
8 | |
---|
9 | OVERVIEW: |
---|
10 | This library provides implementations of several parallel 'skeletons' (i.e. |
---|
11 | ways in which parallel tasks rely upon and interact with each other). It is |
---|
12 | based on the library tasks.lib and aims at both ordinary Singular users as well |
---|
13 | as authors of Singular libraries. |
---|
14 | |
---|
15 | KEYWORDS: parallelization; parallel skeletons; distributed computing |
---|
16 | |
---|
17 | SEE ALSO: resources_lib, tasks_lib, modstd_lib, modnormal_lib |
---|
18 | |
---|
19 | PROCEDURES: |
---|
20 | parallelWaitN(); execute several jobs in parallel |
---|
21 | and wait for N of them to finish |
---|
22 | parallelWaitFirst(); execute several jobs in parallel |
---|
23 | and wait for the first to finish |
---|
24 | parallelWaitAll(); execute several jobs in parallel |
---|
25 | and wait for all of them to finish |
---|
26 | parallelTestAND(); run several tests in parallel |
---|
27 | and determine if they all succeed |
---|
28 | parallelTestOR(); run several tests in parallel |
---|
29 | and determine if any of them succeeds |
---|
30 | "; |
---|
31 | |
---|
32 | LIB "tasks.lib"; |
---|
33 | |
---|
34 | proc parallelWaitN(alias list commands, alias list args, int N, list #) |
---|
35 | "USAGE: parallelWaitN(commands, arguments, N[, timeout]); commands list, |
---|
36 | arguments list, N int, timeout int |
---|
37 | RETURN: a list, containing the results of commands[i] applied to |
---|
38 | arguments[i], i = 1, ..., size(arguments). |
---|
39 | @* The procedure waits for N jobs to finish. |
---|
40 | @* An optional timeout in ms can be provided. Default is 0 which |
---|
41 | disables the timeout. |
---|
42 | NOTE: The entries of the list commands must be strings. The entries of the |
---|
43 | list arguments must be lists. |
---|
44 | @* The type of any entry of the returned list whose corresponding task |
---|
45 | did not finish (due to timeout or error) is \"none\". |
---|
46 | @* The returned list may contain more than N results if several jobs |
---|
47 | finished \"at the same time\". It may contain less than N results in |
---|
48 | the case of timeout or errors occurring. |
---|
49 | SEE ALSO: parallelWaitAll, parallelWaitFirst, tasks_lib |
---|
50 | EXAMPLE: example parallelWaitN; shows an example" |
---|
51 | { |
---|
52 | // auxiliary variables |
---|
53 | int i; |
---|
54 | |
---|
55 | // read optional parameters |
---|
56 | int timeout; |
---|
57 | int ncores; // obsolete, but kept for compatibility with old libraries |
---|
58 | if (size(#) > 0) { |
---|
59 | if (typeof(#[1]) != "int") { |
---|
60 | ERROR("wrong optional parameters"); |
---|
61 | } |
---|
62 | timeout = #[1]; |
---|
63 | if (size(#) > 1) { |
---|
64 | if (size(#) > 2 || typeof(#[2]) != "int") { |
---|
65 | ERROR("wrong optional parameters"); |
---|
66 | } |
---|
67 | ncores = #[2]; |
---|
68 | } |
---|
69 | } |
---|
70 | |
---|
71 | // apply wrapper for obsolete optional parameter ncores |
---|
72 | if (ncores) { |
---|
73 | list semaphore_save = Resources::setcores_subtree(ncores); |
---|
74 | } |
---|
75 | |
---|
76 | // error checking |
---|
77 | int njobs = size(commands); |
---|
78 | if (njobs != size(args)) { |
---|
79 | ERROR("The number of commands does not match the number of lists" |
---|
80 | +newline+"of arguments."); |
---|
81 | } |
---|
82 | if (njobs == 0) { |
---|
83 | ERROR("no commands specified"); |
---|
84 | } |
---|
85 | for (i = 1; i <= njobs; i++) { |
---|
86 | if (typeof(commands[i]) != "string") { |
---|
87 | ERROR("The first argument is not a list of strings."); |
---|
88 | } |
---|
89 | if (typeof(args[i]) != "list") { |
---|
90 | ERROR("The second argument is not a list of lists."); |
---|
91 | } |
---|
92 | } |
---|
93 | |
---|
94 | // compute the tasks |
---|
95 | for (i = 1; i <= njobs; i++) { |
---|
96 | task t(i) = commands[i], args[i]; |
---|
97 | } |
---|
98 | startTasks(t(1..njobs)); |
---|
99 | list indices = waitTasks(list(t(1..njobs)), N, timeout); |
---|
100 | |
---|
101 | // wrap back to saved semaphore |
---|
102 | if (ncores) { |
---|
103 | Resources::resetcores_subtree(semaphore_save); |
---|
104 | } |
---|
105 | |
---|
106 | // return results |
---|
107 | list results; |
---|
108 | for (i = size(indices); i > 0; i--) { |
---|
109 | results[indices[i]] = getResult(t(indices[i])); |
---|
110 | } |
---|
111 | for (i = 1; i <= njobs; i++) { |
---|
112 | killTask(t(i)); |
---|
113 | } |
---|
114 | return(results); |
---|
115 | } |
---|
116 | example |
---|
117 | { |
---|
118 | "EXAMPLE:"; |
---|
119 | echo = 2; |
---|
120 | ring R = 0, (x,y,z), lp; |
---|
121 | ideal I = 3x3y+x3+xy3+y2z2, 2x3z-xy-xz3-y4-z2, 2x2yz-2xy2+xz2-y4; |
---|
122 | ideal J = x10+x9y2, x2y7-y8; |
---|
123 | list commands = list("std", "std"); |
---|
124 | list arguments = list(list(I), list(J)); |
---|
125 | parallelWaitN(commands, arguments, 1); |
---|
126 | } |
---|
127 | |
---|
128 | proc parallelWaitFirst(alias list commands, alias list args, list #) |
---|
129 | "USAGE: parallelWaitFirst(commands, args[, timeout]); commands list, |
---|
130 | arguments list, timeout int |
---|
131 | RETURN: a list, containing at least one (if no timeout occurs) of the results |
---|
132 | of commands[i] applied to arguments[i], i = 1, ..., size(arguments). |
---|
133 | @* The command @code{parallelWaitFirst(commands, arguments[, timeout])} |
---|
134 | is synonymous to |
---|
135 | @code{parallelWaitN(commands, arguments, 1[, timeout])}. See |
---|
136 | @ref{parallelWaitN} for details on optional arguments and other |
---|
137 | remarks. |
---|
138 | SEE ALSO: parallelWaitN, parallelWaitAll, tasks_lib |
---|
139 | EXAMPLE: example parallelWaitFirst; shows an example" |
---|
140 | { |
---|
141 | return(parallelWaitN(commands, args, 1, #)); |
---|
142 | } |
---|
143 | example |
---|
144 | { |
---|
145 | "EXAMPLE:"; |
---|
146 | echo = 2; |
---|
147 | ring R = 0, (x,y,z), lp; |
---|
148 | ideal I = 3x3y+x3+xy3+y2z2, 2x3z-xy-xz3-y4-z2, 2x2yz-2xy2+xz2-y4; |
---|
149 | ideal J = x10+x9y2, x2y7-y8; |
---|
150 | list commands = list("std", "std"); |
---|
151 | list arguments = list(list(I), list(J)); |
---|
152 | parallelWaitFirst(commands, arguments); |
---|
153 | } |
---|
154 | |
---|
155 | proc parallelWaitAll(def commands, alias list args, list #) |
---|
156 | "USAGE: parallelWaitAll(commands, arguments[, timeout]); commands list or |
---|
157 | string, arguments list, timeout int |
---|
158 | RETURN: a list, containing the results of commands[i] applied to |
---|
159 | arguments[i], i = 1, ..., size(arguments). |
---|
160 | @* The command @code{parallelWaitAll(commands, arguments[, timeout])} is |
---|
161 | synonymous to @code{parallelWaitN(commands, arguments, |
---|
162 | size(arguments)[, timeout])}. See @ref{parallelWaitN} for details on |
---|
163 | optional arguments and other remarks. |
---|
164 | NOTE: As a shortcut, @code{commands} can be a string. This is synonymous to |
---|
165 | providing a list of @code{size(arguments)} copies of this string. |
---|
166 | SEE ALSO: parallelWaitFirst, parallelWaitN, tasks_lib |
---|
167 | EXAMPLE: example parallelWaitAll; shows an example" |
---|
168 | { |
---|
169 | if (typeof(commands) != "list" && typeof(commands) != "string") { |
---|
170 | ERROR("invalid type of first argument"); |
---|
171 | } |
---|
172 | if (typeof(commands) == "list") { |
---|
173 | return(parallelWaitN(commands, args, size(args), #)); |
---|
174 | } |
---|
175 | else { |
---|
176 | list cmds; |
---|
177 | for (int i = size(args); i > 0; i--) { |
---|
178 | cmds[i] = commands; |
---|
179 | } |
---|
180 | return(parallelWaitN(cmds, args, size(args), #)); |
---|
181 | } |
---|
182 | } |
---|
183 | example |
---|
184 | { |
---|
185 | "EXAMPLE:"; |
---|
186 | echo = 2; |
---|
187 | ring R = 0, (x,y,z), dp; |
---|
188 | ideal I1 = z8+z6+4z5+4z3+4z2+4, -z2+y; |
---|
189 | ideal I2 = x9y2+x10, x2y7-y8; |
---|
190 | ideal I3 = x3-2xy, x2y-2y2+x; |
---|
191 | string command = "std"; |
---|
192 | list arguments = list(list(I1), list(I2), list(I3)); |
---|
193 | parallelWaitAll(command, arguments); |
---|
194 | } |
---|
195 | |
---|
196 | proc parallelTestAND(def commands, alias list args, list #) |
---|
197 | "USAGE: parallelTestAND(commands, arguments[, timeout]); commands list or |
---|
198 | string, arguments list, timeout int |
---|
199 | RETURN: 1, if commands[i] applied to arguments[i] is not equal to zero for |
---|
200 | all i = 1, ..., size(arguments); |
---|
201 | 0, otherwise. |
---|
202 | @* An optional timeout in ms can be provided. Default is 0 which |
---|
203 | disables the timeout. In case of timeout, -1 is returned. |
---|
204 | NOTE: The entries of the list commands must be strings. The entries of the |
---|
205 | list arguments must be lists. |
---|
206 | @* commands[i] applied to arguments[i] must evaluate to an integer for |
---|
207 | i = 1, ..., size(arguments). |
---|
208 | @* As a shortcut, @code{commands} can be a string. This is synonymous to |
---|
209 | providing a list of @code{size(arguments)} copies of this string. |
---|
210 | SEE ALSO: parallelTestOR, tasks_lib |
---|
211 | EXAMPLE: example parallelTestAND; shows an example" |
---|
212 | { |
---|
213 | // note: this can be improved |
---|
214 | list results = parallelWaitAll(commands, args, #); |
---|
215 | int i; |
---|
216 | for (i = size(args); i > 0; i--) { |
---|
217 | if (typeof(results[i]) != "int" && typeof(results[i]) != "none") { |
---|
218 | ERROR("result no. "+string(i)+" not of type int"); |
---|
219 | } |
---|
220 | } |
---|
221 | for (i = size(args); i > 0; i--) { |
---|
222 | if (typeof(results[i]) == "none") { // timeout |
---|
223 | return(-1); |
---|
224 | } |
---|
225 | } |
---|
226 | for (i = size(results); i > 0; i--) { |
---|
227 | if (!results[i]) { |
---|
228 | return(0); |
---|
229 | } |
---|
230 | } |
---|
231 | return(1); |
---|
232 | } |
---|
233 | example |
---|
234 | { |
---|
235 | "EXAMPLE:"; |
---|
236 | echo = 2; |
---|
237 | ring R = 0, (x,y,z), dp; |
---|
238 | ideal I = x, y, z; |
---|
239 | intvec v = 0:3; |
---|
240 | list l = list(I, v); |
---|
241 | module m1 = x*gen(1); |
---|
242 | module m2; |
---|
243 | string command = "size"; |
---|
244 | list arguments1 = list(list(I), list(v), list(l), list(m1)); |
---|
245 | list arguments2 = list(list(I), list(v), list(l), list(m2)); |
---|
246 | // test if all the arguments have non-zero size |
---|
247 | parallelTestAND(command, arguments1); |
---|
248 | parallelTestAND(command, arguments2); |
---|
249 | } |
---|
250 | |
---|
251 | proc parallelTestOR(def commands, alias list args, list #) |
---|
252 | "USAGE: parallelTestOR(commands, arguments[, timeout]); commands list or |
---|
253 | string, arguments list, timeout int |
---|
254 | RETURN: 1, if commands[i] applied to arguments[i] is not equal to zero for |
---|
255 | any i = 1, ..., size(arguments); |
---|
256 | 0, otherwise. |
---|
257 | @* An optional timeout in ms can be provided. Default is 0 which |
---|
258 | disables the timeout. In case of timeout, -1 is returned. |
---|
259 | NOTE: The entries of the list commands must be strings. The entries of the |
---|
260 | list arguments must be lists. |
---|
261 | @* commands[i] applied to arguments[i] must evaluate to an integer for |
---|
262 | i = 1, ..., size(arguments). |
---|
263 | @* As a shortcut, @code{commands} can be a string. This is synonymous to |
---|
264 | providing a list of @code{size(arguments)} copies of this string. |
---|
265 | SEE ALSO: parallelTestAND, tasks_lib |
---|
266 | EXAMPLE: example parallelTestAND; shows an example" |
---|
267 | { |
---|
268 | // note: this can be improved |
---|
269 | list results = parallelWaitAll(commands, args, #); |
---|
270 | int i; |
---|
271 | for (i = size(args); i > 0; i--) { |
---|
272 | if (typeof(results[i]) != "int" && typeof(results[i]) != "none") { |
---|
273 | ERROR("result no. "+string(i)+" not of type int"); |
---|
274 | } |
---|
275 | } |
---|
276 | for (i = size(args); i > 0; i--) { |
---|
277 | if (typeof(results[i]) == "none") { // timeout |
---|
278 | return(-1); |
---|
279 | } |
---|
280 | } |
---|
281 | for (i = size(results); i > 0; i--) { |
---|
282 | if (results[i]) { |
---|
283 | return(1); |
---|
284 | } |
---|
285 | } |
---|
286 | return(0); |
---|
287 | } |
---|
288 | example |
---|
289 | { |
---|
290 | "EXAMPLE:"; |
---|
291 | echo = 2; |
---|
292 | ring R = 0, (x,y,z), dp; |
---|
293 | ideal I; |
---|
294 | string s; |
---|
295 | list l; |
---|
296 | module m1 = x*gen(1); |
---|
297 | module m2; |
---|
298 | string command = "size"; |
---|
299 | list arguments1 = list(list(I), list(s), list(l), list(m1)); |
---|
300 | list arguments2 = list(list(I), list(s), list(l), list(m2)); |
---|
301 | // test if any of the arguments has non-zero size |
---|
302 | parallelTestOR(command, arguments1); |
---|
303 | parallelTestOR(command, arguments2); |
---|
304 | } |
---|
305 | |
---|