The task system schedules functions and inputs to run on a preset number of threads. The number of threads to be used is given by the variable allowableThreads, and may be examined and changed as follows.
i1 : allowableThreads o1 = 2 |
i2 : allowableThreads = 4 o2 = 4 |
To run a function in another thread use schedule, as in the following example.
i3 : R = ZZ/101[x,y,z]; |
i4 : I = (ideal vars R)^2 2 2 2 o4 = ideal (x , x*y, x*z, y , y*z, z ) o4 : Ideal of R |
i5 : dogb = I -> () -> res quotient module I o5 = dogb o5 : FunctionClosure |
i6 : f = dogb I o6 = f o6 : FunctionClosure |
i7 : t = schedule f o7 = <<task, result available, task done>> o7 : Task |
Note that schedule returns a task, not the result of the computation, which will be accessible only after the task has completed the computation.
i8 : t o8 = <<task, result available, task done>> o8 : Task |
Use isReady to check whether the result is available yet.
i9 : isReady t o9 = true |
i10 : while not isReady t do sleep 1 |
To retrieve the result, use taskResult.
i11 : taskResult t 1 6 8 3 o11 = R <-- R <-- R <-- R <-- 0 0 1 2 3 4 o11 : ChainComplex |
i12 : assert instance(oo,ChainComplex) |
It is possible to make a task without starting it running, using createTask.
i13 : t' = createTask f o13 = <<task, created>> o13 : Task |
i14 : t' o14 = <<task, created>> o14 : Task |
Start it running with schedule.
i15 : schedule t'; |
i16 : t' o16 = <<task, result available, task done>> o16 : Task |
i17 : while not isReady t' do sleep 1 |
i18 : taskResult t' 1 6 8 3 o18 = R <-- R <-- R <-- R <-- 0 0 1 2 3 4 o18 : ChainComplex |
One may use addStartTask to specify that one task is to be started after another one finishes. In the following example, G will start after F finishes.
i19 : F = createTask(() -> "result of F") o19 = <<task, created>> o19 : Task |
i20 : G = createTask(() -> "result of G") o20 = <<task, created>> o20 : Task |
i21 : addStartTask(F,G) |
i22 : schedule F o22 = <<task, result available, task done>> o22 : Task |
i23 : while not isReady F do sleep 1 |
i24 : taskResult F o24 = result of F |
i25 : while not isReady G do sleep 1 |
i26 : taskResult G o26 = result of G |
Use addCancelTask to specify that the completion of one task triggers the cancellation of another, by means of an interrupt exception.
Use addDependencyTask to schedule a task, but to ensure that it will not run until one or more other tasks finish running.
Using the functions above, essentially any parallel functionality needed can be created.
Low level C API functionality using the same scheduler also exists in the Macaulay2/system directory. It works essentially the same way as the Macaulay2 interface.
Warning: Access to external libraries such as singular, etc., may not currently be thread safe.