@constraint

It is possible to define constraints for each task. To this end, the @constraint (or @Constraint) decorator followed by the desired constraints needs to be placed ON TOP of the @task decorator (Code 30).

Important

Please note the the order of @constraint and @task decorators is important.

Definition

Code 30 Constrained task example
from pycompss.api.task import task
from pycompss.api.constraint import constraint
from pycompss.api.parameter import INOUT

@constraint(computing_units="4")
@task(c=INOUT)
def func(a, b, c):
     c += a * b
     ...

This decorator enables the user to set the particular constraints for each task, such as the amount of Cores required explicitly. Alternatively, it is also possible to indicate that the value of a constraint is specified in a environment variable (Code 31).

For example:

Code 31 Constrained task with environment variable example
from pycompss.api.task import task
from pycompss.api.constraint import constraint
from pycompss.api.parameter import INOUT

@constraint(computing_units="4",
            app_software="numpy,scipy,gnuplot",
            memory_size="$MIN_MEM_REQ")
@task(c=INOUT)
def func(a, b, c):
     c += a * b
     ...

Or another example requesting a CPU core and a GPU (Code 32).

Code 32 CPU and GPU constrained task example
from pycompss.api.task import task
from pycompss.api.constraint import constraint

@constraint(processors=[{'processorType':'CPU', 'computingUnits':'1'},
                        {'processorType':'GPU', 'computingUnits':'1'}])
@task(returns=1)
def func(a, b, c):
     ...
     return result

When the task requests a GPU, COMPSs provides the information about the assigned GPU through the COMPSS_BINDED_GPUS, CUDA_VISIBLE_DEVICES and GPU_DEVICE_ORDINAL environment variables. This information can be gathered from the task code in order to use the GPU.

Please, take into account that in order to respect the constraints, the peculiarities of the infrastructure must be defined in the resources.xml file.

Supported constraints

The constraints are defined as key-value pairs, where the key is the name of the constraint. Table 10 details the available constraints names for Python its value type, its default value and a brief description.

Table 10 Arguments of the @constraint decorator

Python

Value type

Default value

Description

computing_units

<string>

β€œ1”

Required number of computing units

is_local

<β€œtrue”|”false”>

β€œfalse”

The task must be executed in the node it’s detected

processor_name

<string>

β€œ[unassigned]”

Required processor name

processor_speed

<string>

β€œ[unassigned]”

Required processor speed

processor_architecture

<string>

β€œ[unassigned]”

Required processor architecture

processor_type

<string>

β€œ[unassigned]”

Required processor type

processor_property_name

<string>

β€œ[unassigned]”

Required processor property

processor_property_value

<string>

β€œ[unassigned]”

Required processor property value

processor_internal_memory_size

<string>

β€œ[unassigned]”

Required internal device memory

processors

Dict<Processor>

β€œ{}”

Required processors (check Table 11 for Processor details)

memory_size

<string>

β€œ[unassigned]”

Required memory size in GBs

memory_type

<string>

β€œ[unassigned]”

Required memory type (SRAM, DRAM, etc.)

storage_size

<string>

β€œ[unassigned]”

Required storage size in GBs

storage_type

<string>

β€œ[unassigned]”

Required storage type (HDD, SSD, etc.)

operating_system_type

<string>

β€œ[unassigned]”

Required operating system type (Windows, MacOS, Linux, etc.)

operating_system_distribution

<string>

β€œ[unassigned]”

Required operating system distribution (XP, Sierra, OpenSUSE, etc.)

operating_system_version

<string>

β€œ[unassigned]”

Required operating system version

wall_clock_limit

<string>

β€œ[unassigned]”

Maximum wall clock time

host_queues

<string>

β€œ[unassigned]”

Required queues

app_software

<string>

β€œ[unassigned]”

Required applications that must be available within the remote node for the task

All constraints are defined with a simple value except the host_queues and app_software constraints, which allow multiple values.

The processors constraint allows the users to define multiple processors for a task execution. This constraint is specified as a list that must be defined as shown in Table 11

Table 11 Arguments of the processor type

Key

Value type

Default value

Description

processorType

<string>

β€œCPU”

Required processor type (e.g. CPU or GPU)

computingUnits

<string>

β€œ1”

Required number of computing units

name

<string>

β€œ[unassigned]”

Required processor name

speed

<string>

β€œ[unassigned]”

Required processor speed

architecture

<string>

β€œ[unassigned]”

Required processor architecture

propertyName

<string>

β€œ[unassigned]”

Required processor property

propertyValue

<string>

β€œ[unassigned]”

Required processor property value

internalMemorySize

<string>

β€œ[unassigned]”

Required internal device memory

Dynamic constraints

The dynamic constraints are supported for computing units, memory size and disk size. In order to define a constraint as dynamic, instead of setting a static value or environment variable, the user needs to set the name of the global variable desired for the constraint.

Code 33 dynamic_constraint task example
from pycompss.api.task import task
from pycompss.api.constraint import constraint
MS = 1

@constraint(memory_size="MS")
@task()
def func(a, b, c):
     c += a * b
     ...

Having the dynamic constraint defined with a global variable, the user now has the ability to change the global variable value between task calls, in order to have different constraint values for each call.

Code 34 dynamic_constraint task call example
def main():
    global MS
    {...}
    func(a, b, c)
    MS = 2
    func(a, b, c)
    MS = a + b * c
    func(a, b, c)

Tip

It is possible to define dynamic constraints using alternative syntax.

Variable from the arguments

The constraint name needs to match a name of a parameter in the arguments of the function, this can be useful if you can easily add a new parameter to the function, or if you already pass the desired constraint value to the function.

Code 35 dynamic_constraint argument task example
from pycompss.api.task import task
from pycompss.api.constraint import constraint

@constraint(computing_units="comp")
@task()
def func(a, b, c, comp):
    c += a + b
    ...

The way you pass the argument can change between function calls including its value.

Code 36 dynamic_constraint argument task call example
def main():
    {...}
    func(a, b, c, 2)
    comp = 4
    func(a, b, c, comp)
    func(a, b, c, comp=1)
Evaluation of a regular expression

All the variable names used in the expression need to match the ones from the function definition. This way there is no need to add an extra parameter to the function or create a new global variable, but is only useful if you can get the constraint value you want from the parameters.

Code 37 dynamic_constraint eval task example
from pycompss.api.task import task
from pycompss.api.constraint import constraint

@constraint(computing_units="int((a * 2) / c)")
@task()
def func(a, b, c):
    c += a + b
    ...
Code 38 dynamic_constraint eval task call example
def main():
    {...}
    func(a, b, c)
    a = 2
    func(a, b, c)
    c = 4
    func(a, b, c)

Important

When using evaluation of variables, it is very important the evaluation of the expression returns a usable value for the constraint, also be careful when using Future Objects because they cannot be evaluated.

Special constraints

There is a special constraint when considering the COMPSs agents deployment (Agents Deployments) to specify that the task MUST be executed in the node that received the task. This constraint is indicated in the @constraint decorator with the is_local argument equal a boolean (True or False) (Code 39) in addition to other constraints.

Code 39 is_local task example
from pycompss.api.task import task
from pycompss.api.constraint import constraint

@constraint(is_local=True)
@task(c=INOUT)
def func(a, b, c):
     c += a * b

Important

The is_local constraint has NO effect with the default COMPSs deployment (master-workers) (Deployment Models).