[dc8c23] | 1 | //////////////////////////////////////////////////////////////////// |
---|
| 2 | version="version parallel.lib 4.0.0.0 Dec_2013 "; // $Id$ |
---|
[5f0de8] | 3 | category="General purpose"; |
---|
| 4 | info=" |
---|
[dc8c23] | 5 | LIBRARY: parallel.lib An abstraction layer for parallel skeletons |
---|
| 6 | |
---|
[5f0de8] | 7 | AUTHOR: Andreas Steenpass, e-mail: steenpass@mathematik.uni-kl.de |
---|
| 8 | |
---|
[e1b841] | 9 | OVERVIEW: |
---|
[dc8c23] | 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. |
---|
[e1b841] | 14 | |
---|
[dc8c23] | 15 | KEYWORDS: parallelization; parallel skeletons; distributed computing |
---|
[5f0de8] | 16 | |
---|
[dc8c23] | 17 | SEE ALSO: resources_lib, tasks_lib, modstd_lib, modnormal_lib |
---|
[5f0de8] | 18 | |
---|
| 19 | PROCEDURES: |
---|
[dc8c23] | 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 |
---|
[5f0de8] | 30 | "; |
---|
| 31 | |
---|
[dc8c23] | 32 | LIB "tasks.lib"; |
---|
[e1b841] | 33 | |
---|
[dc8c23] | 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" |
---|
[5f0de8] | 51 | { |
---|
[dc8c23] | 52 | // auxiliary variables |
---|
| 53 | int i; |
---|
[5f0de8] | 54 | |
---|
[dc8c23] | 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"); |
---|
[5f0de8] | 61 | } |
---|
[dc8c23] | 62 | timeout = #[1]; |
---|
| 63 | if (size(#) > 1) { |
---|
| 64 | if (size(#) > 2 || typeof(#[2]) != "int") { |
---|
| 65 | ERROR("wrong optional parameters"); |
---|
| 66 | } |
---|
| 67 | ncores = #[2]; |
---|
[5f0de8] | 68 | } |
---|
| 69 | } |
---|
| 70 | |
---|
[dc8c23] | 71 | // apply wrapper for obsolete optional parameter ncores |
---|
| 72 | if (ncores) { |
---|
| 73 | list semaphore_save = Resources::setcores_subtree(ncores); |
---|
[5f0de8] | 74 | } |
---|
[dc8c23] | 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."); |
---|
[5f0de8] | 88 | } |
---|
[dc8c23] | 89 | if (typeof(args[i]) != "list") { |
---|
| 90 | ERROR("The second argument is not a list of lists."); |
---|
[5f0de8] | 91 | } |
---|
| 92 | } |
---|
| 93 | |
---|
[dc8c23] | 94 | // compute the tasks |
---|
| 95 | for (i = 1; i <= njobs; i++) { |
---|
| 96 | task t(i) = commands[i], args[i]; |
---|
[5f0de8] | 97 | } |
---|
[dc8c23] | 98 | startTasks(t(1..njobs)); |
---|
| 99 | list indices = waitTasks(list(t(1..njobs)), N, timeout); |
---|
[5f0de8] | 100 | |
---|
[dc8c23] | 101 | // wrap back to saved semaphore |
---|
| 102 | if (ncores) { |
---|
| 103 | Resources::resetcores_subtree(semaphore_save); |
---|
[5f0de8] | 104 | } |
---|
| 105 | |
---|
[dc8c23] | 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); |
---|
[5f0de8] | 115 | } |
---|
| 116 | example |
---|
| 117 | { |
---|
[dc8c23] | 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); |
---|
[5f0de8] | 126 | } |
---|
| 127 | |
---|
[dc8c23] | 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" |
---|
[5f0de8] | 140 | { |
---|
[dc8c23] | 141 | return(parallelWaitN(commands, args, 1, #)); |
---|
[5f0de8] | 142 | } |
---|
| 143 | example |
---|
| 144 | { |
---|
[dc8c23] | 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); |
---|
[5f0de8] | 153 | } |
---|
| 154 | |
---|
[dc8c23] | 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" |
---|
[5f0de8] | 168 | { |
---|
[dc8c23] | 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), #)); |
---|
[5f0de8] | 181 | } |
---|
| 182 | } |
---|
| 183 | example |
---|
| 184 | { |
---|
[dc8c23] | 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); |
---|
[5f0de8] | 194 | } |
---|
| 195 | |
---|
[dc8c23] | 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" |
---|
[5f0de8] | 212 | { |
---|
[dc8c23] | 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 | } |
---|
[5f0de8] | 220 | } |
---|
[dc8c23] | 221 | for (i = size(args); i > 0; i--) { |
---|
| 222 | if (typeof(results[i]) == "none") { // timeout |
---|
| 223 | return(-1); |
---|
| 224 | } |
---|
[5f0de8] | 225 | } |
---|
[dc8c23] | 226 | for (i = size(results); i > 0; i--) { |
---|
| 227 | if (!results[i]) { |
---|
| 228 | return(0); |
---|
| 229 | } |
---|
[5f0de8] | 230 | } |
---|
[dc8c23] | 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"); |
---|
[5f0de8] | 274 | } |
---|
| 275 | } |
---|
[dc8c23] | 276 | for (i = size(args); i > 0; i--) { |
---|
| 277 | if (typeof(results[i]) == "none") { // timeout |
---|
| 278 | return(-1); |
---|
[5f0de8] | 279 | } |
---|
[dc8c23] | 280 | } |
---|
| 281 | for (i = size(results); i > 0; i--) { |
---|
| 282 | if (results[i]) { |
---|
| 283 | return(1); |
---|
[5f0de8] | 284 | } |
---|
| 285 | } |
---|
[dc8c23] | 286 | return(0); |
---|
[5f0de8] | 287 | } |
---|
[dc8c23] | 288 | example |
---|
[5f0de8] | 289 | { |
---|
[dc8c23] | 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); |
---|
[5f0de8] | 304 | } |
---|
[7f30e2] | 305 | |
---|