Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add memory / CPU usage properties to pipeline nodes #1203

Merged
merged 20 commits into from
Jan 24, 2021
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions elyra/pipeline/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,9 @@ def _create_pipeline_operation(node: Dict, super_node: Optional[Dict] = None):
id=node_id,
type=node.get('type'),
classifier=node.get('op'),
cpu=PipelineParser._get_app_data_field(node, 'cpu'),
gpu=PipelineParser._get_app_data_field(node, 'gpu'),
memory=PipelineParser._get_app_data_field(node, 'memory'),
filename=PipelineParser._get_app_data_field(node, 'filename'),
runtime_image=PipelineParser._get_app_data_field(node, 'runtime_image'),
dependencies=PipelineParser._get_app_data_field(node, 'dependencies', []),
Expand Down
51 changes: 39 additions & 12 deletions elyra/pipeline/pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ class Operation(object):
Represents a single operation in a pipeline
"""

def __init__(self, id, type, classifier, filename, runtime_image, dependencies=None,
include_subdirectories: bool = False, env_vars=None, inputs=None, outputs=None,
def __init__(self, id, type, classifier, filename, runtime_image, memory=None, cpu=None, gpu=None,
dependencies=None, include_subdirectories: bool = False, env_vars=None, inputs=None, outputs=None,
parent_operations=None):
"""
:param id: Generated UUID, 128 bit number used as a unique identifier
Expand All @@ -42,6 +42,9 @@ def __init__(self, id, type, classifier, filename, runtime_image, dependencies=N
:param inputs: List of files to be consumed by this operation, produced by parent operation(s)
:param outputs: List of files produced by this operation to be included in a child operation(s)
:param parent_operations: List of parent operation 'ids' required to execute prior to this operation
:param cpu: number of cpus requested to run the operation
:param memory: amount of memory requested to run the operation (in Gi)
:param gpu: number of gpus requested to run the operation
"""

# validate that the operation has all required properties
Expand All @@ -67,6 +70,9 @@ def __init__(self, id, type, classifier, filename, runtime_image, dependencies=N
self._inputs = inputs or []
self._outputs = outputs or []
self._parent_operations = parent_operations or []
self._cpu = cpu
self._gpu = gpu
self._memory = memory

@property
def id(self):
Expand Down Expand Up @@ -104,6 +110,18 @@ def include_subdirectories(self):
def env_vars(self):
return self._env_vars

@property
def cpu(self):
return self._cpu

@property
def memory(self):
return self._memory

@property
def gpu(self):
return self._gpu

def env_vars_as_dict(self, logger: Optional[object] = None) -> Dict:
"""Operation stores environment variables in a list of name=value pairs, while
subprocess.run() requires a dictionary - so we must convert. If no envs are
Expand Down Expand Up @@ -155,7 +173,10 @@ def __eq__(self, other: object) -> bool:
self.include_subdirectories == other.include_subdirectories and \
self.outputs == other.outputs and \
self.inputs == other.inputs and \
self.parent_operations == other.parent_operations
self.parent_operations == other.parent_operations and \
self.cpu == other.cpu and \
self.gpu == other.gpu and \
self.memory == other.memory

def __str__(self) -> str:
return "componentID : {id} \n " \
Expand All @@ -166,15 +187,21 @@ def __str__(self) -> str:
"filename : {filename} \n " \
"inputs : {inputs} \n " \
"outputs : {outputs} \n " \
"runtime image : {image} \n ".format(id=self.id,
name=self.name,
parent_op=self.parent_operations,
depends=self.dependencies,
inc_subdirs=self.include_subdirectories,
filename=self.filename,
inputs=self.inputs,
outputs=self.outputs,
image=self.runtime_image)
"image : {image} \n " \
"gpu: {gpu} \n " \
"memory: {memory} \n " \
"cpu : {cpu} \n ".format(id=self.id,
name=self.name,
parent_op=self.parent_operations,
depends=self.dependencies,
inc_subdirs=self.include_subdirectories,
filename=self.filename,
inputs=self.inputs,
outputs=self.outputs,
image=self.runtime_image,
gpu=self.gpu,
cpu=self.cpu,
memory=self.memory)


class Pipeline(object):
Expand Down
3 changes: 3 additions & 0 deletions elyra/pipeline/processor_kfp.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,9 @@ def _cc_pipeline(self, pipeline, pipeline_name):
pipeline_outputs=operation.outputs,
pipeline_envs=pipeline_envs,
emptydir_volume_size=emptydir_volume_size,
cpu_request=operation.cpu,
mem_request=operation.memory,
gpu_limit=operation.gpu,
image=operation.runtime_image,
file_outputs={
'mlpipeline-metrics':
Expand Down
3 changes: 3 additions & 0 deletions elyra/templates/kfp_template.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ def create_pipeline():
cos_dependencies_archive='{{ operation.cos_dependencies_archive }}',
pipeline_inputs={{ operation.pipeline_inputs }},
pipeline_outputs={{ operation.pipeline_outputs }},
cpu_request='{{ operation.cpu_request }}',
mem_request='{{ operation.mem_request }}G',
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there supposed to be a G at the end of this line?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

its a little weird I admit, looking for hands if we want to change it.
We could add another parameter to the template rendering function in the kfp processor to pass the value with G appended to it, in this case it was just quicker to add a G to the template.

gpu_limit='{{ operation.gpu_limit }}',
image='{{ operation.image }}',
file_outputs={
'mlpipeline-metrics': '{{ metrics_file }}',
Expand Down
6 changes: 6 additions & 0 deletions packages/pipeline-editor/src/PipelineEditorWidget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,9 @@ export class PipelineEditor extends React.Component<
app_data.dependencies;
node_props.parameterDef.current_parameters.include_subdirectories =
app_data.include_subdirectories;
node_props.parameterDef.current_parameters.cpu = app_data.cpu;
node_props.parameterDef.current_parameters.memory = app_data.memory;
node_props.parameterDef.current_parameters.gpu = app_data.gpu;
node_props.parameterDef.titleDefinition = {
title: this.canvasController.getNode(source.id).label,
editable: true
Expand Down Expand Up @@ -540,6 +543,9 @@ export class PipelineEditor extends React.Component<
app_data.env_vars = propertySet.env_vars;
app_data.dependencies = propertySet.dependencies;
app_data.include_subdirectories = propertySet.include_subdirectories;
app_data.cpu = propertySet.cpu;
app_data.memory = propertySet.memory;
app_data.gpu = propertySet.gpu;
this.validateAllNodes();
this.updateModel();
}
Expand Down
189 changes: 189 additions & 0 deletions packages/pipeline-editor/src/properties.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,21 @@
"enum": [],
"required": true
},
{
"id": "cpu",
"type": "double",
"required": "false"
},
{
"id": "gpu",
"type": "double",
lresende marked this conversation as resolved.
Show resolved Hide resolved
"required": "false"
},
{
"id": "memory",
"type": "double",
"required": "false"
},
{
"id": "dependencies",
"type": "array[string]",
Expand Down Expand Up @@ -59,6 +74,33 @@
"default": "Container image used as execution environment"
}
},
{
"parameter_ref": "cpu",
"label": {
"default": "CPU"
},
"description": {
"default": "For CPU-intensive workloads, you can choose more than 1 CPU (e.g. 1.5)."
}
},
{
"parameter_ref": "gpu",
"label": {
"default": "GPU"
},
"description": {
"default": "For GPU-intensive workloads, you can choose more than 1 GPU. Must be an integer."
}
},
{
"parameter_ref": "memory",
"label": {
"default": "RAM(GB)"
},
"description": {
"default": "The total amount of RAM specified."
}
},
{
"parameter_ref": "dependencies",
"label": {
Expand Down Expand Up @@ -150,6 +192,11 @@
"type": "controls",
"parameter_refs": ["runtime_image"]
},
{
"id": "nodeUsageControls",
"type": "controls",
"parameter_refs": ["cpu", "gpu", "memory"]
},
{
"id": "nodeDependenciesControls",
"type": "panels",
Expand All @@ -170,5 +217,147 @@
}
]
},
"conditions": [
{
"validation": {
"fail_message": {
"type": "error",
"focus_parameter_ref": "memory",
"message": {
"default": "Memory must be greater than 0."
}
},
"evaluate": {
"or": [
{
"condition": {
"parameter_ref": "memory",
"op": "greaterThan",
"value": 0
}
},
{
"condition": {
"parameter_ref": "memory",
"op": "isEmpty"
}
}
]
}
}
},
{
"validation": {
"fail_message": {
"type": "error",
"focus_parameter_ref": "cpu",
"message": {
"default": "CPU must be greater than 0."
}
},
"evaluate": {
"or": [
{
"condition": {
"parameter_ref": "cpu",
"op": "greaterThan",
"value": 0
}
},
{
"condition": {
"parameter_ref": "cpu",
"op": "isEmpty"
}
}
]
}
}
},
{
"validation": {
"fail_message": {
"type": "error",
"focus_parameter_ref": "gpu",
"message": {
"default": "GPU must be greater than 0."
}
},
"evaluate": {
"or": [
{
"condition": {
"parameter_ref": "gpu",
"op": "greaterThan",
"value": 0
}
},
{
"condition": {
"parameter_ref": "gpu",
"op": "isEmpty"
}
}
]
}
}
},
{
"validation": {
"fail_message": {
"type": "error",
"focus_parameter_ref": "cpu",
"message": {
"default": "CPU must be less than 99."
}
},
"evaluate": {
"or": [
{
"condition": {
"parameter_ref": "cpu",
"op": "lessThan",
"value": 99
}
},
{
"condition": {
"parameter_ref": "cpu",
"op": "isEmpty"
}
}
]
}
}
},
{
"validation": {
"fail_message": {
"type": "error",
"focus_parameter_ref": "gpu",
"message": {
"default": "GPU must be less than 99."
}
},
"evaluate": {
"or": [
{
"condition": {
"parameter_ref": "gpu",
"op": "lessThan",
"value": 99
}
},
{
"condition": {
"parameter_ref": "gpu",
"op": "isEmpty"
}
}
]
}
}
}
],
"resources": {}
}
Loading