Tutorial
This section provides a step-by-step by tutorial on how to develop Building Blocks using the permedcoe package and an application that uses them.
Requirements
It is required to install the permedcoe
package.
To this end, you can use pip:
python3 -m pip install permedcoe
Tip
Alternatively, it is possible to be installed from source
And it is also required to install singularity. Please, check the Singularity installation documentation.
Step-by-step
Step 1: Create a Building Block
The first step to create a building block is to generate a template to start
with. The template can be created with the following permedcoe
command:
$ permedcoe template building_block my_building_block
Creating Building Block template
------------------------------------------
To be completed:
- definitions.py:(11): TODO: Define your container.
- main.py:(35): TODO: (optional) Pure python code calling to PyCOMPSs tasks (that can be defined in this file or in another).
- main.py:(39): TODO: Define the binary to be used (can be within my_building_block_ASSETS_PATH (e.g. my_binary.sh)).
- main.py:(40): TODO: Define the inputs and output parameters.
- main.py:(41): TODO: Define a representative task name.
- main.py:(42): TODO: Define the binary parameters.
- main.py:(43): TODO: Define the binary parameters.
- main.py:(44): TODO: Define the binary parameters.
- main.py:(45): TODO: Add tmpdir=TMPDIR if the tmpdir will be used by the asset script.
- main.py:(71): TODO: Define the arguments required by the Building Block in definition.json file.
- main.py:(73): TODO: Declare how to run the binary specification (convert config into building_block_task call).
- __main__.py:(13): TODO: Add require_tmpdir=True if the asset requires to write within the tmpdir.
------------------------------------------
The result of this command is a folder named my_building_block
containing
a python package with all scripts and base code to start developing your
Building Block.
Important
The Building Block name in this example is my_building_block
, but
should be defined for your Building Block with a specific name (e.g.
tool used inside the Building Block or functionality).
This tutorial will continue using my_building_block
, so take it into
account if you define a different name and swap my_building_block
with
yours.
Step 2: Create your container
The Building Block template already provides a sample container definition located in:
$ tree my_building_block/container
my_building_block/container/
├── create_container.sh
└── sample.def
This folder contains:
sample.def
Container definition file: Recipe to create the container.
create_container.sh
Container creation script from the container definition file. It invokes Singularity with
sample.def
to generate the container (sample.sif
).
In order to continue with the tutorial it is necessary to create the sample
container from sample.def
with create_container.sh
:
$ cd my_building_block/container
$ ./create_container.sh
Caution
The create_container.sh
script requires root privileges and assumes
that the singularity
command is available in $PATH
as root.
If sudo: singularity: command not found
error happens, the container
can be created by defining explicitly the singularity path:
$ sudo /usr/local/bin/singularity build sample.sif sample.def
Step 3: Develop the Building Block logic
Now its time to add logic to the Building Block template. To this end, you can use your desired text editor or Python IDE.
There are three files that require attention: definition.json, definitions.py and main.py:
$ cd my_building_block/src/my_building_block
First, edit the definition.json file and define the Building Block parameters.
“definition.json” development
In this sample definition.json file, there are two parametes defined that will be required when the Building Block is executed through the command line:
Input: model of file type.
Output: result of file type.
It includes the Building Block short and long descriptions.
{
"short_description": "my_building_block Building Block short description.",
"long_description": "my_building_block Building Block short description. Give more details about the Building Block.",
"use_description": "long",
"parameters": {
"default": [
{
"type": "input",
"name": "model",
"format": "file",
"description": "Input file (model)"
},
{
"type": "output",
"name": "result",
"format": "file",
"description": "Result file"
}
]
}
}
Tip
The parameters dictionary can contain multiple elements, so that a Building Block can have multiple operation modes.
Second, edit the definitions.py file and define the Building Block container.
“definition.json” development
In the definitions.py file, there is one line that requires attention:
# ...
CONTAINER = "my_bulding_block.sif"
# ...
It must be updated with the container name if changed.
Third and finally, edit the main.py file defining the main building block logic.
“main.py” development
In this file, it is necessary to develop the following methods:
building_block_task
[MANDATORY]invoke
[MANDATORY]function_name
[OPTIONAL]
The next Subsections describe each method development:
“building_block_task” method development
The building_block_task
is the core method of the Building Block. It
is used to define the Building Block functionality, and requires attention in
two main places: its decorators and its parameters.
The building_block_task
needs to be decorated with the permedcoe
’s
decorators (in the same order from top to bottom):
@container
To define the container to be used for the building block execution.
@binary
To define if the
building_block_task
represents the execution of a binary application (that must be available in the container). It includes the information related to the binary to be executed when the method is invoked. This decorator is optional. When this decorator is present, thebuilding_block_task
method must be empty (include onlypass
). However, thebuilding_block_task
can contain Python code when it is not defined.@task
To define that the method
building_block_task
is going to be considered as a single task. It includes the information related to the parameters, such as type and direction (e.g.FILE_IN
,FILE_OUT
,FILE_INOUT
,DIRECTORY_IN
,DIRECTORY_OUT
,DIRECTORY_INOUT
).
Lets consider the following code as example:
@container(engine="SINGULARITY", image=my_building_block_CONTAINER)
@binary(binary="cp")
@task(input_file=FILE_IN, output_file=FILE_OUT)
def building_block_task(input_file=None,
output_file=None,
verbose="-v"):
# Empty function since it represents a binary execution:
pass
The building_block_task
is a method that is equivalent to:
cp <input_file> <output_file> -v
Where the decorators define:
@container(engine="SINGULARITY", image=SAMPLE_CONTAINER)
The container that will be used to execute the Building Block.
It must be updated with the container path for your Building Block.
@binary(binary="cp")
The binary to be executed by the Building Block.
It must be updated with the binary path for your Building Block.
@task(input_file=FILE_IN, output_file=FILE_OUT)
The parameters type and direction. In this example, there are two parameters that are files, one used as input (
input_file
) and another produced by the binary execution (output_file
).It must be updated with the function’s parameters type (if files or directories) and/or direction.
And the function is defined:
def building_block_task(input_file=None,
output_file=None,
verbose="-v"):
Each parameter is interpreted in order, and all of them should include the
default value to ease the invocation (e.g. None
is useful for FILES
and DIRECTORIES
, whilst for the rest integers or strings is enough).
The two required actions in the function definition are:
Define a representative function name (e.g.
building_block_task
in the example)Define the function parameters
Important
Please, check carefully the function parameters as well as the @task
parameter definition.
Hint
It can also be a normal python function that calls decorated methods.
This will enable to exploit inner parallelism when used with PyCOMPSs.
“invoke” method development
The invoke
method is necessary to bind the parameters defined through
command line into the invocation of building_block_task
function.
Caution
The name invoke
MUST NOT be changed.
The invoke
method receives two parameters:
arguments
Parsed arguments. Received from command line invocation.
config
Dictionary with the yaml configuration provided.
Consider the following invoke
example:
def invoke(arguments, config):
input_file = arguments.model
output_file = arguments.result
building_block_task(input_file=input_file,
output_file=output_file)
This example shows how to get get the operation
field from config,
gets the input and output files and invokes the building_block_task
method specifying the necessary parameters explicitly (input_file
and output_file
).
“function_name” method development
A building block can be invoked through command line, and the method
used in this case is invoke
.
However, since the Building Block can be used in PyCOMPSs workflows,
the methods can be invoked directly. This means that the workflow can
directly invoke building_block_task
or any other method.
Consequently, this method is OPTIONAL but it is recommended in order to ease the Building Block call from a PyCOMPSs workflow application.
Hint
It can also be a normal python function that calls decorated methods.
This will enable to exploit inner parallelism when used with PyCOMPSs.
Step 4: Test the Building Block
In order to test the Building Block it is necessary to install it.
To this end, the Building Block already includes a install.sh
script:
$ my_building_block/./install.sh
Once installed the my_building_block
package, it provides the
my_building_block
command, that can be used from the command line.
For example:
$ my_building_block -h
usage: my_building_block [-h] --model MODEL --result RESULT [-c CONFIG] [-d]
[-l {debug,info,warning,error,critical}] [--tmpdir TMPDIR]
[--processes PROCESSES] [--gpus GPUS] [--memory MEMORY]
[--mount_points MOUNT_POINTS]
my_building_block Building Block short description. Give more details about the Building Block.
options:
-h, --help show this help message and exit
--model MODEL (INPUT - str (file)) Input file (model)
--result RESULT (OUTPUT - str) Result file
-c CONFIG, --config CONFIG
(CONFIG) Configuration file path
-d, --debug Enable Building Block debug mode. Overrides log_level
-l {debug,info,warning,error,critical}, --log_level {debug,info,warning,error,critical}
Set logging level
--tmpdir TMPDIR Temp directory to be mounted in the container
--processes PROCESSES
Number of processes for MPI executions
--gpus GPUS Requirements for GPU jobs
--memory MEMORY Memory requirement
--mount_points MOUNT_POINTS
Comma separated alias:folder to be mounted in the container
And to test the Building Block, provide the necessary parameters:
# Generate a testing files
$ echo "hello world" > hi.txt
$ my_building_block --model hi.txt --result bye.txt
The result will be the appearance of the bye.txt
file, which is a copy of hi.txt
.
Step 5: Create an Application
The first step to create an application is to generate a template to start
with. The template can be created with the following permedcoe
command:
$ permedcoe template application my_application
Creating Application template
------------------------------------------
To be completed:
- app.py:(6): TODO: Import the desired building blocks entry points and use invoke or any other function.
- Snakefile:(0): TODO: Declare the building blocks to be used as rules.
- Snakefile:(9): TODO: Change bb to the building block name.
- NextFlow.nf:(7): TODO: Declare the building blocks to be used as process.
- NextFlow.nf:(18): TODO: Change bb to the building block name.
------------------------------------------
The result of this command is a folder named my_application
containing
a three folders: NextFlow, PyCOMPSs and Snakemake. Each subfolder contains
a template for that workflow manager with all scripts and base code to start
developing your application.
Important
The application name in this example is my_application
, but
should be defined for your application with a specific name.
This tutorial will continue using my_application`, so take it into
account if you define a different name and swap ``my_application
with
yours.
Tip
It is possible to create the template for a single workflow manager by specifying it in the template creation:
$ permedcoe template application -t <WORKFLOW_MANAGER> my_application
Where <WORKFLOW_MANAGER>
can be: pycompss, nextflow or snakemake.
Step 6: Use the Building Block from the Application
The Building Block is ready to be used from multiple workflow managers, and we already have a template for each workflow manager:
PyCOMPSs
Now its time to add logic to the application template. To this end, you can use your desired text editor or Python IDE.
There is only one file that requires attention (app.py):
$ cd my_application/PyCOMPSs/
# Edit: app.py
In this file, it is necessary to develop the following:
- Imports [MANDATORY]
It is necessary to import the building block (in the template
my_building_block
) methods:# Import building block entry points from my_building_block import invoke from my_building_block import my_building_block_task
Tip
You can import any other method from the Building Block.
main
method [MANDATORY]It is required to implement the logic of the application that uses the building blocks methods.
It can use directly
invoke
to mimic the command line interface. But you can use any other method from the Building Blocks and invoke them directly.Tip
The
my_application
already usesmy_building_block
.def main(): # Sample application: print("Sample python application using my_building_block BB") # Get parameters input_file = str(sys.argv[1]) output_file = str(sys.argv[2]) conf = {} # conf is empty since it is not used by my_building_block # Building Block invocation building_block_task(input_file=input_file, output_file=output_file)
NOTE: That the parameters match the
building_block_task
function definition.
Snakemake
Now its time to add logic to the SnakeMake application template. To this end, you can use your desired text editor or Python IDE.
There is only one file that requires attention (Snakefile):
$ cd my_application/SnakeMake/
# Edit: Snakefile
In this file, it is necessary to declare the building blocks as rules and implement their dependencies. The next code snippet shows an example using my_bulding_block:
rule BUILDINGBLOCK:
input:
dataset="/path/to/dataset",
config="/path/to/conf.yaml"
output:
result="/path/to/result"
shell:
"permedcoe execute building_block my_building_block --model {input.dataset} --result {output.result} --config {input.config}"
NextFlow
Now its time to add logic to the NextFlow application template. To this end, you can use your desired text editor or Python IDE.
There is only one file that requires attention (NextFlow):
$ cd my_application/NextFlow/
# Edit: NextFlow.nf
In this file, it is necessary to declare the building blocks as rules and implement their dependencies. The next code snippet shows an example using my_bulding_block:
params.input="/path/to/dataset"
params.config="/path/to/conf.yaml"
input_ch = Channel.fromPath(params.input)
conf_ch = Channel.fromPath(params.config)
process BUILDINGBLOCK {
input:
file dataset from input_ch
file conf from conf_ch
output:
file "output" into res_ch
"""
permedcoe execute building_block my_building_block --model $dataset --result output --config $conf
"""
}
Step 7: Test the Application
The template application (my_application
) is ready to be used with
multiple workflow managers:
PyCOMPSs
Caution
It is necessary to have installed PyCOMPSs in order to test the application.
Please, check the PyCOMPSs installation manual
There is a ready to use script (launch.sh
) in order to execute the application:
$ cd my_application/PyCOMPSs
$ ./launch.sh hi.txt bye2.txt
------------------------------------------
------------ STDOUT ------------
[ INFO] Inferred PYTHON language
[ INFO] Using default location for project file: /opt/COMPSs//Runtime/configuration/xml/projects/default_project.xml
[ INFO] Using default location for resources file: /opt/COMPSs//Runtime/configuration/xml/resources/default_resources.xml
[ INFO] Using default execution type: compss
----------------- Executing app.py --------------------------
Binding debug is activated
[BINDING-COMMONS] - @JNI_On - Creating the JVM
[BINDING-COMMONS] - @create_vm - reading file in JVM_OPTIONS_FILE
[BINDING-COMMONS] - @create_vm - Launching JVM
[BINDING-COMMONS] - @create_vm - JVM Ready
[BINDING-COMMONS] - @JNI_On - Obtaining Runtime classes
Loading LoggerManager
[BINDING-COMMONS] - @JNI_On - Creating runtime object
[(505) API] - Deploying COMPSs Runtime v3.1
[BINDING-COMMONS] - @JNI_On - Calling runtime start
[(506) API] - Starting COMPSs Runtime v3.1
[(506) API] - Initializing components
[(880) API] - Ready to process tasks
[BINDING-COMMONS] - @Init JNI Types
[BINDING-COMMONS] - @Init JNI Types DONE
[BINDING-COMMONS] - @Init JNI Master
[BINDING-COMMONS] - @Init JNI Methods
[BINDING-COMMONS] - @Init JNI Methods DONE
[BINDING-COMMONS] - @Init JNI OnFailure Types
[BINDING-COMMONS] - @Init JNI Direction Types
[BINDING-COMMONS] - @Init JNI Direction Types DONE
[BINDING-COMMONS] - @Init JNI Stream Types
[BINDING-COMMONS] - @Init JNI Stream Types
[BINDING-COMMONS] - @Init JNI Parameter Prefix
[BINDING-COMMONS] - @Init JNI Parameter Prefix DONE
[BINDING-COMMONS] - @Init Master DONE
[BINDING-COMMONS] - @JNI_Get_AppDir - Getting application directory.
[BINDING-COMMONS] - @JNI_Get_AppDir - directory name: /home/user/.COMPSs/app.py_01/
Sample python application using my_building_block BB
[(888) API] - Registering CoreElement my_building_block.main.building_block_task
[(889) API] - - Implementation: my_building_block.main.building_block_task
[(889) API] - - Constraints :
[(889) API] - - Type : CONTAINER
[(889) API] - - I/O : False
[(889) API] - - ImplTypeArgs :
[(889) API] - Arg: SINGULARITY
[(889) API] - Arg: /home/user/permedcoe/my_building_block/container/sample.sif
[(889) API] - Arg: CET_BINARY
[(889) API] - Arg: cp
[(889) API] - Arg: [unassigned]
[(889) API] - Arg: [unassigned]
[(889) API] - Arg: false
[BINDING-COMMONS] - @JNI_RegisterCE - Task registered: my_building_block.main.building_block_task
[BINDING-COMMONS] - @JNI_ExecuteTaskNew - Processing task execution in bindings-common.
[BINDING-COMMONS] - @JNI_ExecuteTaskNew - Processing parameter 0
[BINDING-COMMONS] - @process_param
[BINDING-COMMONS] - @process_param - ENUM DATA_TYPE: 9
[BINDING-COMMONS] - @process_param - File: hi.txt
[BINDING-COMMONS] - @process_param - ENUM DIRECTION: 0
[BINDING-COMMONS] - @process_param - ENUM STD IO STREAM: 3
[BINDING-COMMONS] - @process_param - PREFIX: null
[BINDING-COMMONS] - @process_param - NAME: #kwarg_input_file
[BINDING-COMMONS] - @process_param - CONTENT TYPE: FILE
[BINDING-COMMONS] - @process_param - WEIGHT : 1.0
[BINDING-COMMONS] - @process_param - KEEP RENAME : 0
[BINDING-COMMONS] - @JNI_ExecuteTaskNew - Processing parameter 1
[BINDING-COMMONS] - @process_param
[BINDING-COMMONS] - @process_param - ENUM DATA_TYPE: 9
[BINDING-COMMONS] - @process_param - File: bye2.txt
[BINDING-COMMONS] - @process_param - ENUM DIRECTION: 1
[BINDING-COMMONS] - @process_param - ENUM STD IO STREAM: 3
[BINDING-COMMONS] - @process_param - PREFIX: null
[BINDING-COMMONS] - @process_param - NAME: #kwarg_output_file
[BINDING-COMMONS] - @process_param - CONTENT TYPE: FILE
[BINDING-COMMONS] - @process_param - WEIGHT : 1.0
[BINDING-COMMONS] - @process_param - KEEP RENAME : 0
[BINDING-COMMONS] - @JNI_ExecuteTaskNew - Processing parameter 2
[BINDING-COMMONS] - @process_param
[BINDING-COMMONS] - @process_param - ENUM DATA_TYPE: 8
[BINDING-COMMONS] - @process_param - String: -v
[BINDING-COMMONS] - @process_param - ENUM DIRECTION: 0
[BINDING-COMMONS] - @process_param - ENUM STD IO STREAM: 3
[BINDING-COMMONS] - @process_param - PREFIX: null
[BINDING-COMMONS] - @process_param - NAME: #kwarg_verbose
[BINDING-COMMONS] - @process_param - CONTENT TYPE: #UNDEFINED#:#UNDEFINED#
[BINDING-COMMONS] - @process_param - WEIGHT : 1.0
[BINDING-COMMONS] - @process_param - KEEP RENAME : 1
[(902) API] - Creating task from method my_building_block.main.building_block_task for application 0
[(902) API] - There are 3 parameters
[(905) API] - Parameter 0 has type FILE_T
[(909) API] - Parameter 1 has type FILE_T
[(909) API] - Parameter 2 has type STRING_T
[BINDING-COMMONS] - @JNI_ExecuteTaskNew - Task processed.
[BINDING-COMMONS] - @JNI_Off
[BINDING-COMMONS] - @Off - Waiting to end tasks
[(912) API] - No more tasks for app 0
[(4229) API] - Getting Result Files for app0
[BINDING-COMMONS] - @Off - Stopping runtime
[(4265) API] - Stopping Wall Clock limit Timer
[(4265) API] - Stop IT reached
[(4265) API] - Stopping Graph generation...
[(4265) API] - Stopping AP...
[(4266) API] - Stopping TD...
[(4418) API] - Stopping Comm...
[(4419) API] - Runtime stopped
[(4419) API] - Execution Finished
[BINDING-COMMONS] - @Off - Revoke thread access to JVM
[BINDING-COMMONS] - @Off - Removing JVM
[BINDING-COMMONS] - @Off - Removing environment
[BINDING-COMMONS] - @Off - End
------------------------------------------------------------
------------ STDERR ------------
WARNING: COMPSs Properties file is null. Setting default values
2021-11-16 15:43:46,197 - DEBUG - Executing container_f wrapper.
2021-11-16 15:43:46,198 - DEBUG - Configuring @container core element.
2021-11-16 15:43:46,198 - DEBUG - Executing binary_f wrapper.
2021-11-16 15:43:46,198 - DEBUG - Configuring @binary core element.
2021-11-16 15:43:46,198 - DEBUG - [@TASK] Task type of function building_block_task in module my_building_block.main: CONTAINER
2021-11-16 15:43:46,199 - DEBUG - Configuring core element.
2021-11-16 15:43:46,199 - DEBUG - [@TASK] Registering the function building_block_task in module my_building_block.main
2021-11-16 15:43:46,199 - DEBUG - Registering CE with signature: my_building_block.main.building_block_task
2021-11-16 15:43:46,199 - DEBUG - - Implementation signature: my_building_block.main.building_block_task
2021-11-16 15:43:46,199 - DEBUG - - Implementation constraints:
2021-11-16 15:43:46,199 - DEBUG - - Implementation type: CONTAINER
2021-11-16 15:43:46,199 - DEBUG - - Implementation type arguments: SINGULARITY /home/user/permedcoe/my_building_block/container/sample.sif CET_BINARY cp [unassigned] [unassigned] false
2021-11-16 15:43:46,204 - DEBUG - CE with signature my_building_block.main.building_block_task registered.
2021-11-16 15:43:46,209 - DEBUG - Final type for parameter #kwarg_input_file: 9
2021-11-16 15:43:46,210 - DEBUG - Final type for parameter #kwarg_output_file: 9
2021-11-16 15:43:46,210 - DEBUG - Final type for parameter #kwarg_verbose: 8
2021-11-16 15:43:46,210 - DEBUG - TASK: building_block_task of type 1, in module my_building_block.main, in class
2021-11-16 15:43:46,210 - DEBUG - Processing task:
2021-11-16 15:43:46,210 - DEBUG - - App id: 0
2021-11-16 15:43:46,210 - DEBUG - - Signature: my_building_block.main.building_block_task
2021-11-16 15:43:46,210 - DEBUG - - Has target: False
2021-11-16 15:43:46,210 - DEBUG - - Names: #kwarg_input_file #kwarg_output_file #kwarg_verbose
2021-11-16 15:43:46,210 - DEBUG - - Values: hi.txt bye2.txt -v
2021-11-16 15:43:46,210 - DEBUG - - COMPSs types: 9 9 8
2021-11-16 15:43:46,210 - DEBUG - - COMPSs directions: 0 1 0
2021-11-16 15:43:46,210 - DEBUG - - COMPSs streams: 3 3 3
2021-11-16 15:43:46,211 - DEBUG - - COMPSs prefixes: null null null
2021-11-16 15:43:46,211 - DEBUG - - Content Types: FILE FILE #UNDEFINED#:#UNDEFINED#
2021-11-16 15:43:46,211 - DEBUG - - Weights: 1.0 1.0 1.0
2021-11-16 15:43:46,211 - DEBUG - - Keep_renames: False False True
2021-11-16 15:43:46,211 - DEBUG - - Priority: False
2021-11-16 15:43:46,211 - DEBUG - - Num nodes: 1
2021-11-16 15:43:46,211 - DEBUG - - Reduce: False
2021-11-16 15:43:46,211 - DEBUG - - Chunk Size: 0
2021-11-16 15:43:46,211 - DEBUG - - Replicated: False
2021-11-16 15:43:46,211 - DEBUG - - Distributed: False
2021-11-16 15:43:46,211 - DEBUG - - On failure behavior: RETRY
2021-11-16 15:43:46,212 - DEBUG - - Task time out: 0
2021-11-16 15:43:46,223 - DEBUG - --- END ---
2021-11-16 15:43:46,223 - INFO - Stopping runtime...
2021-11-16 15:43:46,223 - INFO - Cleaning objects...
2021-11-16 15:43:46,223 - INFO - Stopping COMPSs...
2021-11-16 15:43:50,330 - INFO - Cleaning temps...
2021-11-16 15:43:50,345 - INFO - COMPSs stopped
------------------------------------------
Caution
If your application requires parameters, the launch.sh
script needs
to be tuned accordingly.
Tip
The output is very verbose since PyCOMPSs has been executed in debug
mode. It can be executed silently by removing the -d
flag from
the launch.sh
script.
Tip
If any error occurs, it is necessary to debug the execution. To this end it is helpful to execute in debug mode (as it is currently) and check the Troubleshooting for Python section from the PyCOMPSs documentation.
Tip
It is possible to run the application without PyCOMPSs installed
using the launch_without_pycompss.sh
script. However, the execution
of the application will be performed entirely sequentially.
Snakemake
Caution
It is necessary to have installed Snakemake in order to test the application.
There is a ready to use script (launch.sh
) in order to execute the application:
$ cd my_application/SnakeMake
$ ./launch.sh
NextFlow
Caution
It is necessary to have installed NextFlow in order to test the application.
There is a ready to use script (launch.sh
) in order to execute the application:
$ cd my_application/NextFlow
$ ./launch.sh
Step 8: Run your Application in a Supercomputer
The final steps are: to deploy the Building Blocks and Application into a supercomputer and run the Application using a workflow manager.
To this end, contact the PerMedCoE partners: infoPerMedCoE@bsc.es