
| Current Path : /usr/share/gap/doc/hpc/ |
Linux ift1.ift-informatik.de 5.4.0-216-generic #236-Ubuntu SMP Fri Apr 11 19:53:21 UTC 2025 x86_64 |
| Current File : //usr/share/gap/doc/hpc/chap1.txt |
[1X1 [33X[0;0YTasks[133X[101X
[1X1.1 [33X[0;0YOverview[133X[101X
[33X[0;0YTasks provide mid- to high-level functionality for programmers to describe
asynchronous workflows. A task is an asynchronously or synchronously
executing job; functions exist to create tasks that are executed
concurrently, on demand, or in the current thread; to wait for their
completion, check their status, and retrieve any results.[133X
[33X[0;0YHere is a simple example of sorting a list in the background:[133X
[4X[32X Example [32X[104X
[4X[25Xgap>[125X [27Xtask := RunTask(x -> SortedList(x), [3,2,1]);;[127X[104X
[4X[25Xgap>[125X [27XWaitTask(task);[127X[104X
[4X[25Xgap>[125X [27XTaskResult(task);[127X[104X
[4X[28X[ 1, 2, 3 ][128X[104X
[4X[32X[104X
[33X[0;0Y[2XRunTask[102X ([14X1.2-1[114X) dispatches a task to run in the background; a task is
described by a function and zero or more arguments that are passed to
[2XRunTask[102X ([14X1.2-1[114X). [2XWaitTask[102X ([14X1.2-9[114X) waits for the task to complete; and
[10XTaskResult[110X returns the result of the task.[133X
[33X[0;0Y[2XTaskResult[102X ([14X1.2-11[114X) does an implicit [2XWaitTask[102X ([14X1.2-9[114X), so the second line
above can actually be omitted:[133X
[4X[32X Example [32X[104X
[4X[25Xgap>[125X [27Xtask := RunTask(x -> SortedList(x), [3,2,1]);;[127X[104X
[4X[25Xgap>[125X [27XTaskResult(task);[127X[104X
[4X[28X[ 1, 2, 3 ][128X[104X
[4X[32X[104X
[33X[0;0YIt is simple to run two tasks in parallel. Let's compute the factorial of
10000 by splitting the work between two tasks:[133X
[4X[32X Example [32X[104X
[4X[25Xgap>[125X [27Xtask1 := RunTask(Product, [1..5000]);;[127X[104X
[4X[25Xgap>[125X [27Xtask2 := RunTask(Product, [5001..10000]);;[127X[104X
[4X[25Xgap>[125X [27XTaskResult(task1) * TaskResult(task2) = Factorial(10000);[127X[104X
[4X[28Xtrue[128X[104X
[4X[32X[104X
[33X[0;0YYou can use [2XDelayTask[102X ([14X1.2-3[114X) to delay executing the task until its result
is actually needed.[133X
[4X[32X Example [32X[104X
[4X[25Xgap>[125X [27Xtask1 := DelayTask(Product, [1..5000]);;[127X[104X
[4X[25Xgap>[125X [27Xtask2 := DelayTask(Product, [5001..10000]);;[127X[104X
[4X[25Xgap>[125X [27XWaitTask(task1, task2);[127X[104X
[4X[25Xgap>[125X [27XTaskResult(task1) * TaskResult(task2) = Factorial(10000);[127X[104X
[4X[28Xtrue[128X[104X
[4X[32X[104X
[33X[0;0YNote that [2XWaitTask[102X ([14X1.2-9[114X) is used here to start execution of both tasks;
otherwise, [10Xtask2[110X would not be started until [10XTaskResult(task1)[110X has been
evaluated.[133X
[33X[0;0YTo start execution of a delayed task, you can also use [10XExecuteTask[110X. This has
no effect if a task has already been running.[133X
[33X[0;0YFor convenience, you can also use [2XImmediateTask[102X ([14X1.2-7[114X) to execute a task
synchronously (i.e., the task is started immediately and the call does not
return until the task has completed).[133X
[4X[32X Example [32X[104X
[4X[25Xgap>[125X [27Xtask := ImmediateTask(x -> SortedList(x), [3,2,1]);;[127X[104X
[4X[25Xgap>[125X [27XTaskResult(task);[127X[104X
[4X[28X[ 1, 2, 3 ][128X[104X
[4X[32X[104X
[33X[0;0YThis is indistinguishable from calling the function directly, but provides
the same interface as normal tasks.[133X
[33X[0;0YIf e.g. you want to call a function only for its side-effects, it can be
useful to ignore the result of a task. [2XRunAsyncTask[102X ([14X1.2-4[114X) provides the
necessary functionality. Such a task cannot be waited for and its result (if
any) is ignored.[133X
[4X[32X Example [32X[104X
[4X[25Xgap>[125X [27XRunAsyncTask(function() Print("Hello, world!\n"); end);;[127X[104X
[4X[25Xgap>[125X [27X!list[127X[104X
[4X[28X--- Thread 0 [0][128X[104X
[4X[28X--- Thread 5 [5] (pending output)[128X[104X
[4X[25Xgap>[125X [27X!5[127X[104X
[4X[28X--- Switching to thread 5[128X[104X
[4X[28X[5] Hello, world![128X[104X
[4X[28X!0[128X[104X
[4X[28X--- Switching to thread 0[128X[104X
[4X[28Xgap>[128X[104X
[4X[32X[104X
[33X[0;0YFor more information on the multi-threaded user interface, see Chapter [14X4[114X.[133X
[33X[0;0YTask arguments are generally copied so that both the task that created them
and the task that uses them can access the data concurrently without fear of
race conditions. To avoid copying, arguments should be made shared or public
(see the relevant parts of section [14X3.6[114X on migrating objects between
regions); shared and public arguments will not be copied.[133X
[33X[0;0YHPC-GAP currently has multiple implementations of the task API. To use an
alternative implementation to the one documented here, set the environment
variable [10XGAP_WORKSTEALING[110X to a non-empty value before starting GAP.[133X
[1X1.2 [33X[0;0YRunning tasks[133X[101X
[1X1.2-1 RunTask[101X
[33X[1;0Y[29X[2XRunTask[102X( [3Xfunc[103X[, [3Xarg1[103X, [3X...[103X, [3Xargn[103X] ) [32X function[133X
[33X[0;0Y[2XRunTask[102X prepares a task for execution and starts it. The task will call the
function [3Xfunc[103X with arguments [3Xarg1[103X through [3Xargn[103X (if provided). The return
value of [3Xfunc[103X is the result of the task. The [2XRunTask[102X call itself returns a
task object that can be used by functions that expect a task argument.[133X
[1X1.2-2 ScheduleTask[101X
[33X[1;0Y[29X[2XScheduleTask[102X( [3Xcondition[103X, [3Xfunc[103X[, [3Xarg1[103X, [3X...[103X, [3Xargn[103X] ) [32X function[133X
[33X[0;0Y[2XScheduleTask[102X prepares a task for execution, but, unlike [2XRunTask[102X ([14X1.2-1[114X) does
not start it until [3Xcondition[103X is met. See on how to construct conditions.
Simple examples of conditions are individual tasks, where execution occurs
after the task completes, or lists of tasks, where execution occurs after
all tasks in the list complete.[133X
[4X[32X Example [32X[104X
[4X[25Xgap>[125X [27Xt1 := RunTask(x->x*x, 3);;[127X[104X
[4X[25Xgap>[125X [27Xt2 := RunTask(x->x*x, 4);;[127X[104X
[4X[25Xgap>[125X [27Xt := ScheduleTask([t1, t2], function()[127X[104X
[4X[25X>[125X [27X return TaskResult(t1) + TaskResult(t2);[127X[104X
[4X[25X>[125X [27X end);;[127X[104X
[4X[25Xgap>[125X [27XTaskResult(t);[127X[104X
[4X[28X25[128X[104X
[4X[32X[104X
[33X[0;0YWhile the above example could also be achieved with [2XRunTask[102X ([14X1.2-1[114X) in lieu
of [2XScheduleTask[102X, since [2XTaskResult[102X ([14X1.2-11[114X) would wait for [3Xt1[103X and [3Xt2[103X to
complete, the above implementation does not actually start the final task
until the others are complete, making it more efficient, since no additional
worker thread needs to be occupied.[133X
[1X1.2-3 DelayTask[101X
[33X[1;0Y[29X[2XDelayTask[102X( [3Xfunc[103X[, [3Xarg1[103X, [3X...[103X, [3Xargn[103X] ) [32X function[133X
[33X[0;0Y[2XDelayTask[102X works as [2XRunTask[102X ([14X1.2-1[114X), but its start is delayed until it is
being waited for (including implicitly by calling [2XTaskResult[102X ([14X1.2-11[114X)).[133X
[1X1.2-4 RunAsyncTask[101X
[33X[1;0Y[29X[2XRunAsyncTask[102X( [3Xfunc[103X[, [3Xarg1[103X, [3X...[103X, [3Xargn[103X] ) [32X function[133X
[33X[0;0Y[2XRunAsyncTask[102X creates an asynchronous task. It works like [2XRunTask[102X ([14X1.2-1[114X),
except that its result will be ignored.[133X
[1X1.2-5 ScheduleAsyncTask[101X
[33X[1;0Y[29X[2XScheduleAsyncTask[102X( [3Xcondition[103X, [3Xfunc[103X[, [3Xarg1[103X, [3X...[103X, [3Xargn[103X] ) [32X function[133X
[33X[0;0Y[2XScheduleAsyncTask[102X creates an asynchronous task. It works like [2XScheduleTask[102X
([14X1.2-2[114X), except that its result will be ignored.[133X
[1X1.2-6 MakeTaskAsync[101X
[33X[1;0Y[29X[2XMakeTaskAsync[102X( [3Xtask[103X ) [32X function[133X
[33X[0;0Y[2XMakeTaskAsync[102X turns a synchronous task into an asynchronous task that cannot
be waited for and whose result will be ignored.[133X
[1X1.2-7 ImmediateTask[101X
[33X[1;0Y[29X[2XImmediateTask[102X( [3Xfunc[103X[, [3Xarg1[103X, [3X...[103X, [3Xargn[103X] ) [32X function[133X
[33X[0;0Y[2XImmediateTask[102X executes the task specified by its arguments synchronously,
usually within the current thread.[133X
[1X1.2-8 ExecuteTask[101X
[33X[1;0Y[29X[2XExecuteTask[102X( [3Xtask[103X ) [32X function[133X
[33X[0;0Y[2XExecuteTask[102X starts [3Xtask[103X if it is not already running. It has only an effect
if its argument is a task returned by [2XDelayTask[102X ([14X1.2-3[114X); otherwise, it is a
no-op.[133X
[1X1.2-9 WaitTask[101X
[33X[1;0Y[29X[2XWaitTask[102X( [3Xtask1[103X, [3X...[103X, [3Xtaskn[103X ) [32X function[133X
[33X[1;0Y[29X[2XWaitTask[102X( [3Xcondition[103X ) [32X function[133X
[33X[1;0Y[29X[2XWaitTasks[102X( [3Xtask1[103X, [3X...[103X, [3Xtaskn[103X ) [32X function[133X
[33X[0;0Y[2XWaitTask[102X waits until [3Xtask1[103X through [3Xtaskn[103X have completed; after that, it
returns. Alternatively, a condition can be passed to [2XWaitTask[102X in order to
wait until a condition is met. See on how to construct conditions. [2XWaitTasks[102X
is an alias for [2XWaitTask[102X.[133X
[1X1.2-10 WaitAnyTask[101X
[33X[1;0Y[29X[2XWaitAnyTask[102X( [3Xtask1[103X, [3X...[103X, [3Xtaskn[103X ) [32X function[133X
[33X[0;0YThe [2XWaitAnyTask[102X function waits for any of its arguments to finish, then
returns the number of that task.[133X
[4X[32X Example [32X[104X
[4X[25Xgap>[125X [27Xtask1 := DelayTask(x->SortedList(x), [3,2,1]);;[127X[104X
[4X[25Xgap>[125X [27Xtask2 := DelayTask(x->SortedList(x), [6,5,4]);;[127X[104X
[4X[25Xgap>[125X [27Xwhich := WaitAnyTask(task1, task2);[127X[104X
[4X[28X2[128X[104X
[4X[25Xgap>[125X [27Xif which = 1 then[127X[104X
[4X[25X>[125X [27X Display(TaskResult(task1));Display(TaskResult(task2));[127X[104X
[4X[25X>[125X [27X else[127X[104X
[4X[25X>[125X [27X Display(TaskResult(task2));Display(TaskResult(task1));[127X[104X
[4X[25X>[125X [27X fi;[127X[104X
[4X[28X[ 4, 5, 6 ][128X[104X
[4X[28X[ 1, 2, 3 ][128X[104X
[4X[32X[104X
[33X[0;0YOne can pass a list of tasks to [10XWaitAnyTask[110X as an argument;
[10XWaitAnyTask([task1, ..., taskn])[110X behaves identically to [10XWaitAnyTask(task1,
..., taskn)[110X.[133X
[1X1.2-11 TaskResult[101X
[33X[1;0Y[29X[2XTaskResult[102X( [3Xtask[103X ) [32X function[133X
[33X[0;0YThe [2XTaskResult[102X function returns the result of a task. It implicitly calls
[2XWaitTask[102X ([14X1.2-9[114X) if that is necessary. Multiple invocations of [2XTaskResult[102X
with the same task argument will not do repeated waits and always return the
same value.[133X
[33X[0;0YIf the function executed by [3Xtask[103X encounters an error, [2XTaskResult[102X returns
[9Xfail[109X. Whether [3Xtask[103X encountered an error can be checked via [2XTaskSuccess[102X
([14X1.3-1[114X). In case of an error, the error message can be retrieved via
[2XTaskError[102X ([14X1.3-2[114X).[133X
[1X1.2-12 CullIdleTasks[101X
[33X[1;0Y[29X[2XCullIdleTasks[102X( ) [32X function[133X
[33X[0;0YThis function terminates unused worker threads.[133X
[1X1.3 [33X[0;0YInformation about tasks[133X[101X
[1X1.3-1 TaskSuccess[101X
[33X[1;0Y[29X[2XTaskSuccess[102X( [3Xtask[103X ) [32X function[133X
[33X[0;0Y[2XTaskSuccess[102X waits for [3Xtask[103X and returns [9Xtrue[109X if the it finished without
encountering an error. Otherwise the function returns [9Xfalse[109X.[133X
[1X1.3-2 TaskError[101X
[33X[1;0Y[29X[2XTaskError[102X( [3Xtask[103X ) [32X function[133X
[33X[0;0Y[2XTaskError[102X waits for [3Xtask[103X and returns its error message, if it encountered an
error. If it did not encounter an error, the function returns [9Xfail[109X.[133X
[1X1.3-3 CurrentTask[101X
[33X[1;0Y[29X[2XCurrentTask[102X( ) [32X function[133X
[33X[0;0YThe [2XCurrentTask[102X returns the currently running task.[133X
[1X1.3-4 RunningTasks[101X
[33X[1;0Y[29X[2XRunningTasks[102X( ) [32X function[133X
[33X[0;0YThis function returns the number of currently running tasks. Note that it is
only an approximation and can change as new tasks are being started by other
threads.[133X
[1X1.3-5 TaskStarted[101X
[33X[1;0Y[29X[2XTaskStarted[102X( [3Xtask[103X ) [32X function[133X
[33X[0;0YThis function returns true if the task has started executing (i.e., for any
non-delayed task), false otherwise.[133X
[1X1.3-6 TaskFinished[101X
[33X[1;0Y[29X[2XTaskFinished[102X( [3Xtask[103X ) [32X function[133X
[33X[0;0YThis function returns true if the task has finished executing and its result
is available, false otherwise.[133X
[1X1.3-7 TaskIsAsync[101X
[33X[1;0Y[29X[2XTaskIsAsync[102X( [3Xtask[103X ) [32X function[133X
[33X[0;0YThis function returns true if the task is asynchronous, true otherwise.[133X
[1X1.4 [33X[0;0YCancelling tasks[133X[101X
[33X[0;0YHPC-GAP uses a cooperative model for task cancellation. A programmer can
request the cancellation of another task, but it is up to that other task to
actually terminate itself. The tasks library has functions to request
cancellation, to test for the cancellation state of a task, and to perform
actions in response to cancellation requests.[133X
[1X1.4-1 CancelTask[101X
[33X[1;0Y[29X[2XCancelTask[102X( [3Xtask[103X ) [32X function[133X
[33X[0;0Y[2XCancelTask[102X submits a request that [3Xtask[103X is to be cancelled.[133X
[1X1.4-2 TaskCancellationRequested[101X
[33X[1;0Y[29X[2XTaskCancellationRequested[102X( [3Xtask[103X ) [32X function[133X
[33X[0;0Y[2XTaskCancellationRequested[102X returns true if [2XCancelTask[102X ([14X1.4-1[114X) has been called
for [3Xtask[103X, false otherwise.[133X
[1X1.4-3 OnTaskCancellation[101X
[33X[1;0Y[29X[2XOnTaskCancellation[102X( [3Xexit_func[103X ) [32X function[133X
[33X[0;0Y[2XOnTaskCancellation[102X tests if cancellation for the current task has been
requested. If so, then [3Xexit_func[103X will be called (as a parameterless
function) and the current task will be aborted. The result of the current
task will be the value of [3Xexit_func()[103X.[133X
[4X[32X Example [32X[104X
[4X[25Xgap>[125X [27Xtask := RunTask(function()[127X[104X
[4X[25X>[125X [27X while true do[127X[104X
[4X[25X>[125X [27X OnTaskCancellation(function() return 314; end);[127X[104X
[4X[25X>[125X [27X od;[127X[104X
[4X[25X>[125X [27X end);;[127X[104X
[4X[25Xgap>[125X [27XCancelTask(task);[127X[104X
[4X[25Xgap>[125X [27XTaskResult(task);[127X[104X
[4X[28X314[128X[104X
[4X[32X[104X
[1X1.4-4 OnTaskCancellationReturn[101X
[33X[1;0Y[29X[2XOnTaskCancellationReturn[102X( [3Xvalue[103X ) [32X function[133X
[33X[0;0Y[2XOnTaskCancellationReturn[102X is a convenience function that does the same as:
[10XOnTaskCancellation(function() return value; end);[110X[133X
[1X1.5 [33X[0;0YConditions[133X[101X
[33X[0;0Y[2XScheduleTask[102X ([14X1.2-2[114X) and [2XWaitTask[102X ([14X1.2-9[114X) can be made to wait on more
complex conditions than just tasks. A condition is either a milestone, a
task, or a list of milestones and tasks. [2XScheduleTask[102X ([14X1.2-2[114X) starts its
task and [2XWaitTask[102X ([14X1.2-9[114X) returns when the condition has been met. A
condition represented by a task is met when the task has completed. A
condition represented by a milestone is met when the milestone has been
achieved (see below). A condition represented by a list is met when all
conditions in the list have been met.[133X
[1X1.6 [33X[0;0YMilestones[133X[101X
[33X[0;0YMilestones are a way to represent abstract conditions to which multiple
tasks can contribute.[133X
[1X1.6-1 NewMilestone[101X
[33X[1;0Y[29X[2XNewMilestone[102X( [[3Xlist[103X] ) [32X function[133X
[33X[0;0YThe [2XNewMilestone[102X function creates a new milestone. Its argument is a list of
targets, which must be a list of integers and/or strings. If omitted, the
list defaults to [10X[0][110X.[133X
[1X1.6-2 ContributeToMilestone[101X
[33X[1;0Y[29X[2XContributeToMilestone[102X( [3Xmilestone[103X, [3Xtarget[103X ) [32X function[133X
[33X[0;0YThe [2XContributeToMilestone[102X milestone function contributes the specified
target to the milestone. Once all targets have been contributed to a
milestone, it has been achieved.[133X
[1X1.6-3 AchieveMilestone[101X
[33X[1;0Y[29X[2XAchieveMilestone[102X( [3Xmilestone[103X ) [32X function[133X
[33X[0;0YThe [2XAchieveMilestone[102X function allows a program to achieve a milestone in a
single step without adding individual targets to it. This is most useful in
conjunction with the default value for [2XNewMilestone[102X ([14X1.6-1[114X), e.g.[133X
[4X[32X Example [32X[104X
[4X[25Xgap>[125X [27Xm := NewMilestone();;[127X[104X
[4X[25Xgap>[125X [27XAchieveMilestone(m);[127X[104X
[4X[32X[104X
[33X[0;0Y>[133X
[1X1.6-4 IsMilestoneAchieved[101X
[33X[1;0Y[29X[2XIsMilestoneAchieved[102X( [3Xmilestone[103X ) [32X function[133X
[33X[0;0Y[2XIsMilestoneAchieved[102X tests explicitly if a milestone has been achieved. It
returns [10Xtrue[110X on success, [10Xfalse[110X otherwise.[133X
[4X[32X Example [32X[104X
[4X[25Xgap>[125X [27Xm := NewMilestone([1,2]);;[127X[104X
[4X[25Xgap>[125X [27XContributeToMilestone(m, 1);[127X[104X
[4X[25Xgap>[125X [27XIsMilestoneAchieved(m);[127X[104X
[4X[28Xfalse[128X[104X
[4X[25Xgap>[125X [27XContributeToMilestone(m, 2);[127X[104X
[4X[25Xgap>[125X [27XIsMilestoneAchieved(m);[127X[104X
[4X[28Xtrue[128X[104X
[4X[32X[104X