GLOST: Difference between revisions

From Alliance Doc
Jump to navigation Jump to search
No edit summary
m (Updated the modules to use the StdEnv/2023 environment.)
 
(35 intermediate revisions by 6 users not shown)
Line 1: Line 1:
<languages />
<languages />
<translate>
<translate>
= Introduction =
= Introduction = <!--T:1-->


[https://github.com/cea-hpc/glost GLOST], the Greedy Launcher Of Small Tasks, is a tool for running many sequential or serial jobs at the same time in the same manner as an MPI job that can use many cores (or nodes). It works similarly like [[GNU Parallel|GNU parallel]] and/or [[Job arrays|job arrays]] but it has a simpler syntax. It needs a text file with the commands related to all the jobs. It is useful for running a large number of serial jobs or tasks, especially if they are short or variable duration, as well as when doing a parameter sweep. '''GLOST''' uses a wrapper called <code>gloost_launch</code> and it works with <code>srun</code>, <code>mpiexec</code> and <code>mpirun</code> in the same way as any [[MPI]] job. The serial jobs should be grouped into one text file, '''list_glost_tasks.txt''', that will be used as an argument for the '''gloost_launch''' wrapper.
<!--T:2-->
[https://github.com/cea-hpc/glost GLOST], the Greedy Launcher Of Small Tasks, is a tool for running many sequential jobs of short or variable duration, or for doing parameter sweeps. It works like [[GNU Parallel|GNU parallel]] or [[Job arrays|job arrays]] but with a simpler syntax.  
GLOST uses a wrapper called <code>glost_launch</code> and [[MPI]] commands <code>srun</code>, <code>mpiexec</code> and <code>mpirun</code>. Jobs are grouped into one text file, <b>list_glost_tasks.txt</b>, which is used as an argument for <code>glost_launch</code>.


'''GLOST''' can be used in the following situations:
<!--T:3-->
<b>GLOST</b> can be used in the following situations:


* large number of serial jobs with comparative run time.
<!--T:4-->
* large number of short serial jobs.
* large number of serial jobs with comparative runtime,
* large number of short serial jobs,
* serial jobs with different parameters (parameter sweep).
* serial jobs with different parameters (parameter sweep).


The idea behind using GLOST consists on bundling serial jobs and run them as an MPI job. It can use multiple cores (one or more nodes). This will reduce considerably the number of the jobs on the queue, and therefore, reduce the stress scheduler [[SLURM]].
<!--T:5-->
The idea behind using GLOST consists on bundling serial jobs and run them as an MPI job. It can use multiple cores (one or more nodes). This will reduce considerably the number of the jobs on the queue, and therefore, reduce the stress on the [[Running jobs | scheduler]].


'''Note:''' please read this document till the end and if you think that your workflow can fit within this framework, contact your support team to help you change your workflow: [mailto:support@computecanada.ca support@computecanada.ca]
<!--T:53-->
As an alternative, you may also want to consider the [[META: A package for job farming | META]] software package developed by our staff, which has some important advantages over GLOST. In particular, with META the queue wait time may be significantly shorter than with GLOST, and META overheads are smaller (fewer wasted CPU cycles). In addition, META has a convenient mechanism for re-submitting all the computations that never ran or failed. Finally, unlike GLOST, META can be used for all kinds of jobs; serial, multi-threaded, MPI, GPU, or hybrid.


= Advantage of using GLOST =
<!--T:7-->
<b>Note:</b> please read this document until the end and if you think that your workflow can fit within this framework, contact [[Technical support]] to help you change your workflow.


GLOST is used to bundle a bench of serial jobs into one single or more MPI jobs depending on the duration of the jobs and their number.
= Advantage of using GLOST = <!--T:52-->


Submitting a large number of serial jobs at once can slow down the scheduler leading in most cases to a slow response and frequent time out from <code>sbatch</code> or <code>squeue</code> requests. The idea is to put all the serial tasks into one single file, for example '''list_glost_tasks.txt''', and submit an MPI job using '''gloost_launch''' wrapper. This will reduce considerably the number of the jobs on the queue leading to less requests to the scheduler compared to the situation if the jobs are submitted separately. Using GLOST to submit serial jobs reduce the stress experienced by the scheduler SLURM when a large number of jobs are submitted at the same time without any delay.
<!--T:51-->
GLOST is used to bundle a set of serial jobs into one single or more MPI jobs depending on the duration of the jobs and their number.  


<!--T:9-->
Submitting a large number of serial jobs at once can slow down the scheduler leading in most cases to a slow response and frequent time out from <code>sbatch</code> or <code>squeue</code> requests. The idea is to put all the serial tasks into one single file, for example <b>list_glost_tasks.txt</b>, and submit an MPI job using the <code>glost_launch</code> wrapper. This will reduce considerably the number of the jobs on the queue leading to less requests to the scheduler compared to the situation if the jobs are submitted separately. Using GLOST to submit serial jobs reduces the stress experienced by the Slurm scheduler when a large number of jobs are submitted at the same time without any delay.
<!--T:10-->
Using GLOST, the user will submit and handle few MPI jobs rather than hundreds or thousands serial jobs.
Using GLOST, the user will submit and handle few MPI jobs rather than hundreds or thousands serial jobs.


= Modules =
= Modules = <!--T:11-->


GLOST uses OpenMPI to run a bench of serial tasks as an MPI job. For each OpenMPI version, a corresponding module of Glost is installed. To use it, make sure to load OpenMPI and Glost modules. For more information, please refer to the page [[using modules]]. To see the current installed modules on Compute Canada systems, use <code>module spider glost</code>. Before submitting a job, make sure that you can load GLOST along with the other modules that are required to run your application.
<!--T:12-->
GLOST uses OpenMPI to run a set of serial tasks as an MPI job. For each OpenMPI version, a corresponding module of Glost is installed. To use it, make sure to load OpenMPI and Glost modules. For more information, please refer to the page [[using modules]]. To see the current installed modules on our systems, use <code>module spider glost</code>. Before submitting a job, make sure that you can load GLOST along with the other modules that are required to run your application.
</translate>
</translate>
<source lang="bash">
<source lang="bash">
$  module spider glost/0.3.1
$  module spider glost/0.3.1


----------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------
   glost: glost/0.3.1
   glost: glost/0.3.1
----------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------
     Description:
     Description:
       This is GLOST, the Greedy Launcher Of Small Tasks.  
       This is GLOST, the Greedy Launcher Of Small Tasks.  


    Properties:
      Tools for development / Outils de développement


     You will need to load all module(s) on any one of the lines below before the "glost/0.3.1" module is available to load.
     You will need to load all module(s) on any one of the lines below before the "glost/0.3.1" module is available to load.


       nixpkgs/16.09 gcc/5.4.0 openmpi/2.0.2
       StdEnv/2023 gcc/12.3 openmpi/4.1.5
      nixpkgs/16.09  gcc/5.4.0  openmpi/2.1.1
       StdEnv/2023 intel/2023.2.1  openmpi/4.1.5
      nixpkgs/16.09  intel/2016.4  openmpi/2.0.2
       nixpkgs/16.09 intel/2016.4  openmpi/2.1.1
      nixpkgs/16.09  intel/2017.1  openmpi/2.0.2
      nixpkgs/16.09  intel/2017.1 openmpi/2.1.1
   
   
     Help:
     Help:
Line 56: Line 67:
       ================
       ================
       - Homepage: https://github.com/cea-hpc/glost
       - Homepage: https://github.com/cea-hpc/glost
</source>
</source>
<translate>
<translate>
<!--T:13-->
If there is already an OpenMPI module in your environment, like the default environment, adding <code>module load glost</code> to your list of the modules needed for your application, is sufficient to activate GLOST. Use <code>module list</code> to make sure that GLOST module is loaded along with other modules before submitting your job.
If there is already an OpenMPI module in your environment, like the default environment, adding <code>module load glost</code> to your list of the modules needed for your application, is sufficient to activate GLOST. Use <code>module list</code> to make sure that GLOST module is loaded along with other modules before submitting your job.


= How to use GLOST? =
= How to use GLOST? = <!--T:14-->


== GLOST syntax ==
== GLOST syntax == <!--T:15-->


<!--T:16-->
The general syntax of GLOST can take one of the following forms:
The general syntax of GLOST can take one of the following forms:


<!--T:17-->
<source lang="bash">
<source lang="bash">
srun glost_launch list_glost_tasks.txt
srun glost_launch list_glost_tasks.txt


<!--T:18-->
mpiexec glost_launch list_glost_tasks.txt  
mpiexec glost_launch list_glost_tasks.txt  


<!--T:19-->
mpirun glost_launch list_glost_tasks.txt
mpirun glost_launch list_glost_tasks.txt
</source>
</source>


== Number of cores versus number of jobs ==
== Number of cores versus number of jobs == <!--T:20-->


GLOST uses a cyclic distribution to distribute the serial jobs among the available cores for the job. The GLOST wrapper picks the first lines from the list of jobs and assign one processor to each job (or line from the list) and when one or more processors are done with the first tasks, GLOST will assign them the following lines on the list until the end of the list or till the job run out of time. Therefore, the number of cores may not necessarily match the number of requested jobs in the list. However, in order to optimize the use of resources, one may need to make sure that the serial jobs have similar run time and they can be distributed evenly among the cores asked for. Different situations can be treated:
<!--T:21-->
GLOST uses a cyclic distribution to distribute the serial jobs among the available cores for the job. The GLOST wrapper picks the first lines from the list of jobs and assign one processor to each job (or line from the list) and when one or more processors are done with the first tasks, GLOST will assign them the following lines on the list until the end of the list or until the job runs out of time. Therefore, the number of cores may not necessarily match the number of requested jobs in the list. However, in order to optimize the use of resources, one may need to make sure that the serial jobs have similar runtime and they can be distributed evenly among the cores asked for. Different situations can be treated:


* If you have a large number of very short serial jobs to run (hundreds or thousands of jobs with a very short time, few minutes for example), you submit one or more GLOST jobs that will run a bench of serial jobs using few cores. The jobs can be scheduled for short time and by node to take advantage of the back-filling and the scheduler.  
<!--T:22-->
* If you have tens to hundreds of relatively short run time jobs (an hour or so), you can bundle them into one or more GLOST jobs.
* If you have a large number of very short serial jobs to run (hundreds or thousands of jobs with a very short time, few minutes for example), you submit one or more GLOST jobs that will run a set of serial jobs using few cores. The jobs can be scheduled for short time and by node to take advantage of the back-filling and the scheduler.  
* If you have many long serial jobs with similar run time, they can also be used as a GLOS job.  
* If you have tens to hundreds of relatively short runtime jobs (an hour or so), you can bundle them into one or more GLOST jobs.
* If you have many long serial jobs with similar runtimes, they can also be used as a GLOST job.  


== Estimation of the wall time for GLOST job ==
== Estimation of the wall time for GLOST job == <!--T:23-->


Before running a GLOST job, try to estimate the run time for your serial jobs. It can be used to estimate the wall time for you GLOST job.
<!--T:24-->
Before running a GLOST job, try to estimate the runtime for your serial jobs. It can be used to estimate the wall time for your GLOST job.
   
   
Let us suppose you want to run a GLOST job where you have a list of '''Njobs''' of similar jobs where each job take '''t0''' as a run time using 1 processor. The total run time for all these jobs will be: '''t0*Njobs'''
Let us suppose you want to run a GLOST job where you have a list of <b>Njobs</b> of similar jobs where each job take <b>t0</b> as a runtime using 1 processor. The total runtime for all these jobs will be: <b>t0*Njobs</b>


Now, if you are going to use '''Ncores''' to run your GLOST job, the time required for this job will be: '''wt = t0*Njobs/Ncores'''
<!--T:25-->
Now, if you are going to use <b>Ncores</b> to run your GLOST job, the time required for this job will be: <b>wt = t0*Njobs/Ncores</b>.


'''Note:''' A regular MPI job uses many cores and a communication between the different processors is required to exchange the information between them. More communications reduce the efficiency of the code. In contrary, GLOST uses MPI without any communication of information between the different processors involved within the job. Therefore, one can expect 100 % of time efficiency.
<!--T:26-->
<b>Note:</b> An MPI job is often designed so that MPI processes need to exchange information. Designs like this can spend a large fraction of time on communication, and so wind up doing less computation.  Many, small, dependent communications can reduce the efficiency of the code. In contrast, GLOST uses MPI but only to start entirely serial jobs, which means that communication overhead is relatively infrequent. You could write the same program yourself, using MPI directly, but GLOST provides nearly the same efficiency, without the effort of writing MPI.


== Choosing the memory ==
== Choosing the memory == <!--T:27-->


GLOST uses MPI to run serial jobs and the memory per core should be the same as the memory required for the serial job if it runs separately. Use <code>--mem-per-cpu</code> instead of <code>--mem</code> in your SLURM script.
<!--T:28-->
GLOST uses MPI to run serial jobs and the memory per core should be the same as the memory required for the serial job if it runs separately. Use <code>--mem-per-cpu</code> instead of <code>--mem</code> in your Slurm script.


== Create the list of tasks ==
== Create the list of tasks == <!--T:29-->


Before submitting a job using GLOST, create a text file,'''list_glost_tasks.txt''', that contains all the commands needed to run the serial jobs: one job per line. Ideally, one has to choose jobs with similar run time in order to optimize the use of resources asked for. The GLOST job can run all the tasks in one or multiple directories. If you run all the jobs in one directory, make sure that the output from the different jobs do not overlap or use the same temporary or output files. To do so, standard output may be redirected to a file with a variable indicating the argument or the option used to run the corresponding jobs. In case of the jobs use similar temporary or output files, you may need to create a directory for each task: one directory for each argument or option that correspond to a particular job.  
<!--T:30-->
Before submitting a job using GLOST, create a text file,<b>list_glost_tasks.txt</b>, that contains all the commands needed to run the serial jobs: one job per line. Ideally, one has to choose jobs with similar runtime in order to optimize the use of resources asked for. The GLOST job can run all the tasks in one or multiple directories. If you run all the jobs in one directory, make sure that the output from the different jobs do not overlap or use the same temporary or output files. To do so, standard output may be redirected to a file with a variable indicating the argument or the option used to run the corresponding jobs. In case of the jobs use similar temporary or output files, you may need to create a directory for each task: one directory for each argument or option that correspond to a particular job.  


'''Note:''' one job may contain one command or multiple commands executed one after another. The commands should be separated by <code>&&</code>.
<!--T:31-->
<b>Note:</b> one job may contain one command or multiple commands executed one after another. The commands should be separated by <code>&&</code>.


Here is an example of the file '''list_glost_example.txt''' with 8 jobs:
<!--T:32-->
</translate>
Here is an example of the file <b>list_glost_example.txt</b> with 8 jobs:
<tabs>
<tabs>
<tab name="Script">
<tab name="Script">
Line 112: Line 137:
#!/bin/bash
#!/bin/bash


<!--T:55-->
#SBATCH --nodes=1
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=2
#SBATCH --ntasks-per-node=2
Line 117: Line 143:
#SBATCH --mem-per-cpu=4000M
#SBATCH --mem-per-cpu=4000M


<!--T:56-->
# Load GLOST module:
# Load GLOST module:


module load nixpkgs/16.09  intel/2016.4 openmpi/2.0.2 glost/0.3.1
<!--T:57-->
module load intel/2023.2.1 openmpi/4.1.5 glost/0.3.1


<!--T:58-->
echo "Starting run at: `date`"
echo "Starting run at: `date`"


<!--T:59-->
# Run GLOST with the argument: list_glost_example.txt
# Run GLOST with the argument: list_glost_example.txt


<!--T:60-->
srun glost_launch list_glost_example.txt
srun glost_launch list_glost_example.txt


<!--T:61-->
echo "Program glost_launch finished with exit code $? at: `date`"
echo "Program glost_launch finished with exit code $? at: `date`"
}}
}}
</tab>
</tab>


<tab name="List of Tasks">
<!--T:62-->
<tab name="List of tasks">
{{File
{{File
   |name=list_glost_example.txt
   |name=list_glost_example.txt
Line 147: Line 180:
</tab>
</tab>


<!--T:33-->
</tabs>
</tabs>
<translate>
<b>Note:</b> the above example cannot be executed. The commands are not defined. It shows only:
'''Note:''' the above example can not be executed. The commands are not defined. It shows only:


* a simple syntax for a list of jobs, '''list_glost_tasks.txt'''. that will serve as an argument for the wrapper '''glost_launch'''.
<!--T:34-->
* a simple syntax for a list of jobs, <b>list_glost_tasks.txt</b> that will serve as an argument for the <code>glost_launch</code> wrapper;
* a typical script to submit the job.
* a typical script to submit the job.


<!--T:35-->
Both the list of jobs and the script should be adapted to your workflow.
Both the list of jobs and the script should be adapted to your workflow.


== List of jobs to run in one directory ==
== List of jobs to run in one directory == <!--T:36-->


GLOST can be used to run a bench or a list of serial jobs in one directory. To avoid the overlap of the results, one has to make sure that the different jobs will not use the same temporary or output file. This can be achieved by adding arguments to differentiate the different jobs. In the following example, we have a list of 10 tasks. Each task may contain one or more commands. In this example, each job runs three commands one after another:
<!--T:37-->
GLOST can be used to run a set or a list of serial jobs in one directory. To avoid the overlap of the results, one has to make sure that the different jobs will not use the same temporary or output file. This can be achieved by adding arguments to differentiate the different jobs. In the following example, we have a list of 10 tasks. Each task may contain one or more commands. In this example, each job runs three commands one after another:


* '''First command:''' Fix a variable '''nargument'''. This could be a parameter or a variable to pass to the program for example.
<!--T:38-->
* '''Second command:''' run the program. For testing, we have used the command <code>sleep 360</code>. This should be replaced by the command line to run your application. For example: <code>./my_first_prog < first_input_file.txt > first_output_file.txt</code>
* <b>First command:</b> Fix a variable <b>nargument</b>. This could be a parameter or a variable to pass to the program for example.
* '''Third command:''' If needed, add one or more commands that will be executed just after the previous ones. All the commands should be separated by <code>&&</code>. For testing, we have used the command: <code>echo ${nargument}.`hostname` > log_${nargument}.txt</code>. For this command, we print out the argument and the <code>hostname</code> to a file log_${nargument}.txt. Similarly to the second command, this line should be replaced by another command line to run an application just after the previous one if needed. For example: <code>./my_second_prog < second_input_file.txt > second_output_file.txt</code>.   
* <b>Second command:</b> run the program. For testing, we have used the command <code>sleep 360</code>. This should be replaced by the command line to run your application. For example: <code>./my_first_prog < first_input_file.txt > first_output_file.txt</code>
</translate>
* <b>Third command:</b> If needed, add one or more commands that will be executed just after the previous ones. All the commands should be separated by <code>&&</code>. For testing, we have used the command: <code>echo ${nargument}.`hostname` > log_${nargument}.txt</code>. For this command, we print out the argument and the <code>hostname</code> to a file log_${nargument}.txt. Similarly to the second command, this line should be replaced by another command line to run an application just after the previous one if needed. For example: <code>./my_second_prog < second_input_file.txt > second_output_file.txt</code>.   
<tabs>
<tabs>
<tab name="Script">
<tab name="Script">
Line 172: Line 208:
#!/bin/bash
#!/bin/bash


<!--T:63-->
#SBATCH --nodes=1
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=2
#SBATCH --ntasks-per-node=2
Line 177: Line 214:
#SBATCH --mem-per-cpu=4000M
#SBATCH --mem-per-cpu=4000M


<!--T:64-->
# Load GLOST module along with the modules required to run your application:
# Load GLOST module along with the modules required to run your application:


module load nixpkgs/16.09  intel/2016.4 openmpi/2.0.2 glost/0.3.1
<!--T:65-->
module load intel/2023.2.1 openmpi/4.1.5 glost/0.3.1


<!--T:66-->
echo "Starting run at: `date`"
echo "Starting run at: `date`"


<!--T:67-->
# Run GLOST with the argument: list_glost_tasks.txt
# Run GLOST with the argument: list_glost_tasks.txt


<!--T:68-->
srun glost_launch list_glost_tasks.txt
srun glost_launch list_glost_tasks.txt


<!--T:69-->
echo "Program glost_launch finished with exit code $? at: `date`"
echo "Program glost_launch finished with exit code $? at: `date`"
}}
}}
</tab>
</tab>


<tab name="List of Tasks">
<!--T:70-->
<tab name="List of tasks">
{{File
{{File
   |name=list_glost_tasks.txt
   |name=list_glost_tasks.txt
Line 209: Line 253:
</tab>
</tab>


<!--T:71-->
</tabs>
</tabs>
<translate>
'''Note:''' In the above example, we have used 2 cores and a list of 10 jobs. GLOST will assign the first two jobs (two first lines) to the available processors, and whenever one and/or both of them are done with the first set of jobs, they will continue with the following jobs until the end of the list.


== List of jobs to run in separate directories ==
<!--T:39-->
<b>Note:</b> In the above example, we have used 2 cores and a list of 10 jobs. GLOST will assign the first two jobs (two first lines) to the available processors, and whenever one and/or both of them are done with the first set of jobs, they will continue with the following jobs until the end of the list.
 
== List of jobs to run in separate directories == <!--T:40-->


<!--T:41-->
Similarly to the previous case, GLOST can be used to run multiple serial jobs where each one is executed in a dedicated directory. This could be useful to run a program that uses files (temporary, input and/or output) with the same names in order to avoid the crash of the jobs or an overlap of the results from the different jobs. To do so, one has to make sure to create the input files and a directory for each job before running GLOST. It can be also achieved if included within the line commands as shown in the following example:     
Similarly to the previous case, GLOST can be used to run multiple serial jobs where each one is executed in a dedicated directory. This could be useful to run a program that uses files (temporary, input and/or output) with the same names in order to avoid the crash of the jobs or an overlap of the results from the different jobs. To do so, one has to make sure to create the input files and a directory for each job before running GLOST. It can be also achieved if included within the line commands as shown in the following example:     
</translate>
<tabs>
<tabs>
<tab name="Script">
<tab name="Script">
Line 225: Line 271:
#!/bin/bash
#!/bin/bash


<!--T:72-->
#SBATCH --nodes=1
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=3
#SBATCH --ntasks-per-node=3
Line 230: Line 277:
#SBATCH --mem-per-cpu=4000M
#SBATCH --mem-per-cpu=4000M


<!--T:73-->
# Load GLOST module along with the modules required to run your application:
# Load GLOST module along with the modules required to run your application:


module load nixpkgs/16.09  intel/2016.4 openmpi/2.0.2 glost/0.3.1
<!--T:74-->
module load intel/2023.2.1 openmpi/4.1.5 glost/0.3.1


<!--T:75-->
echo "Starting run at: `date`"
echo "Starting run at: `date`"


<!--T:76-->
# Run GLOST with the argument: list_glost_tasks.txt
# Run GLOST with the argument: list_glost_tasks.txt


<!--T:77-->
srun glost_launch list_glost_tasks.txt
srun glost_launch list_glost_tasks.txt


<!--T:78-->
echo "Program glost_launch finished with exit code $? at: `date`"
echo "Program glost_launch finished with exit code $? at: `date`"
}}
}}
</tab>
</tab>


<tab name="List of Tasks">
<!--T:79-->
<tab name="List of tasks">
{{File
{{File
   |name=list_glost_tasks.txt
   |name=list_glost_tasks.txt
Line 265: Line 319:


</tabs>
</tabs>
<translate>
== Restarting a GLOST job == <!--T:42-->
== Restarting a GLOST job ==


If you underestimated the wall time for your GLOST job, it may require to be restarted to complete the list of the jobs that were inserted in the list of glost tasks. In this case, make sure to identify the jobs that are already done in order to not run them again. Once identified, remove the corresponding lines from the list of the tasks or create a new list of the jobs that contain the remaining jobs from the previous GLOST job and resubmit your script using the new list as an argument for the wrapper "glost_launch"
<!--T:43-->
If you underestimated the wall time for your GLOST job, it may require to be restarted to complete the list of the jobs that were inserted in the list of glost tasks. In this case, make sure to identify the jobs that are already done in order to not run them again. Once identified, remove the corresponding lines from the list of the tasks or create a new list of the jobs that contain the remaining jobs from the previous GLOST job and resubmit your script using the new list as an argument for the <code>glost_launch</code> wrapper.


== More examples ==
== More examples == <!--T:44-->


If you are an advanced user and familiar with scripting, you may have a look to the examples by making a copy of the original scripts and adapt them to your workflow.
<!--T:45-->
If you are an advanced user and familiar with scripting, you may have a look at the examples by making a copy of the original scripts and adapting them to your workflow.


<!--T:46-->
After loading GLOST module, the examples can be copied to your local directory by running the command:
After loading GLOST module, the examples can be copied to your local directory by running the command:


<!--T:47-->
<source lang="bash">
<source lang="bash">
cp -r $EBROOTGLOST/examples Glost_Examples
cp -r $EBROOTGLOST/examples Glost_Examples
</source>
</source>


<!--T:48-->
The copy of the examples will be saved under the directory: Glost_Examples
The copy of the examples will be saved under the directory: Glost_Examples


= Related links =
= Related links = <!--T:49-->


<!--T:50-->
* [[GNU Parallel]]
* [[GNU Parallel]]
* [[Job arrays]]
* [[Job arrays]]

Latest revision as of 18:51, 3 April 2024

Other languages:

Introduction[edit]

GLOST, the Greedy Launcher Of Small Tasks, is a tool for running many sequential jobs of short or variable duration, or for doing parameter sweeps. It works like GNU parallel or job arrays but with a simpler syntax. GLOST uses a wrapper called glost_launch and MPI commands srun, mpiexec and mpirun. Jobs are grouped into one text file, list_glost_tasks.txt, which is used as an argument for glost_launch.

GLOST can be used in the following situations:

  • large number of serial jobs with comparative runtime,
  • large number of short serial jobs,
  • serial jobs with different parameters (parameter sweep).

The idea behind using GLOST consists on bundling serial jobs and run them as an MPI job. It can use multiple cores (one or more nodes). This will reduce considerably the number of the jobs on the queue, and therefore, reduce the stress on the scheduler.

As an alternative, you may also want to consider the META software package developed by our staff, which has some important advantages over GLOST. In particular, with META the queue wait time may be significantly shorter than with GLOST, and META overheads are smaller (fewer wasted CPU cycles). In addition, META has a convenient mechanism for re-submitting all the computations that never ran or failed. Finally, unlike GLOST, META can be used for all kinds of jobs; serial, multi-threaded, MPI, GPU, or hybrid.

Note: please read this document until the end and if you think that your workflow can fit within this framework, contact Technical support to help you change your workflow.

Advantage of using GLOST[edit]

GLOST is used to bundle a set of serial jobs into one single or more MPI jobs depending on the duration of the jobs and their number.

Submitting a large number of serial jobs at once can slow down the scheduler leading in most cases to a slow response and frequent time out from sbatch or squeue requests. The idea is to put all the serial tasks into one single file, for example list_glost_tasks.txt, and submit an MPI job using the glost_launch wrapper. This will reduce considerably the number of the jobs on the queue leading to less requests to the scheduler compared to the situation if the jobs are submitted separately. Using GLOST to submit serial jobs reduces the stress experienced by the Slurm scheduler when a large number of jobs are submitted at the same time without any delay.

Using GLOST, the user will submit and handle few MPI jobs rather than hundreds or thousands serial jobs.

Modules[edit]

GLOST uses OpenMPI to run a set of serial tasks as an MPI job. For each OpenMPI version, a corresponding module of Glost is installed. To use it, make sure to load OpenMPI and Glost modules. For more information, please refer to the page using modules. To see the current installed modules on our systems, use module spider glost. Before submitting a job, make sure that you can load GLOST along with the other modules that are required to run your application.

$  module spider glost/0.3.1

--------------------------------------------------------------------------------------------------------------------------------------
  glost: glost/0.3.1
--------------------------------------------------------------------------------------------------------------------------------------
    Description:
      This is GLOST, the Greedy Launcher Of Small Tasks. 

    Properties:
      Tools for development / Outils de développement

    You will need to load all module(s) on any one of the lines below before the "glost/0.3.1" module is available to load.

      StdEnv/2023  gcc/12.3  openmpi/4.1.5
      StdEnv/2023  intel/2023.2.1  openmpi/4.1.5
 
    Help:
      
      Description
      ===========
      This is GLOST, the Greedy Launcher Of Small Tasks.
      
      
      More information
      ================
       - Homepage: https://github.com/cea-hpc/glost

If there is already an OpenMPI module in your environment, like the default environment, adding module load glost to your list of the modules needed for your application, is sufficient to activate GLOST. Use module list to make sure that GLOST module is loaded along with other modules before submitting your job.

How to use GLOST?[edit]

GLOST syntax[edit]

The general syntax of GLOST can take one of the following forms:

srun glost_launch list_glost_tasks.txt

mpiexec glost_launch list_glost_tasks.txt 

mpirun glost_launch list_glost_tasks.txt

Number of cores versus number of jobs[edit]

GLOST uses a cyclic distribution to distribute the serial jobs among the available cores for the job. The GLOST wrapper picks the first lines from the list of jobs and assign one processor to each job (or line from the list) and when one or more processors are done with the first tasks, GLOST will assign them the following lines on the list until the end of the list or until the job runs out of time. Therefore, the number of cores may not necessarily match the number of requested jobs in the list. However, in order to optimize the use of resources, one may need to make sure that the serial jobs have similar runtime and they can be distributed evenly among the cores asked for. Different situations can be treated:

  • If you have a large number of very short serial jobs to run (hundreds or thousands of jobs with a very short time, few minutes for example), you submit one or more GLOST jobs that will run a set of serial jobs using few cores. The jobs can be scheduled for short time and by node to take advantage of the back-filling and the scheduler.
  • If you have tens to hundreds of relatively short runtime jobs (an hour or so), you can bundle them into one or more GLOST jobs.
  • If you have many long serial jobs with similar runtimes, they can also be used as a GLOST job.

Estimation of the wall time for GLOST job[edit]

Before running a GLOST job, try to estimate the runtime for your serial jobs. It can be used to estimate the wall time for your GLOST job.

Let us suppose you want to run a GLOST job where you have a list of Njobs of similar jobs where each job take t0 as a runtime using 1 processor. The total runtime for all these jobs will be: t0*Njobs

Now, if you are going to use Ncores to run your GLOST job, the time required for this job will be: wt = t0*Njobs/Ncores.

Note: An MPI job is often designed so that MPI processes need to exchange information. Designs like this can spend a large fraction of time on communication, and so wind up doing less computation. Many, small, dependent communications can reduce the efficiency of the code. In contrast, GLOST uses MPI but only to start entirely serial jobs, which means that communication overhead is relatively infrequent. You could write the same program yourself, using MPI directly, but GLOST provides nearly the same efficiency, without the effort of writing MPI.

Choosing the memory[edit]

GLOST uses MPI to run serial jobs and the memory per core should be the same as the memory required for the serial job if it runs separately. Use --mem-per-cpu instead of --mem in your Slurm script.

Create the list of tasks[edit]

Before submitting a job using GLOST, create a text file,list_glost_tasks.txt, that contains all the commands needed to run the serial jobs: one job per line. Ideally, one has to choose jobs with similar runtime in order to optimize the use of resources asked for. The GLOST job can run all the tasks in one or multiple directories. If you run all the jobs in one directory, make sure that the output from the different jobs do not overlap or use the same temporary or output files. To do so, standard output may be redirected to a file with a variable indicating the argument or the option used to run the corresponding jobs. In case of the jobs use similar temporary or output files, you may need to create a directory for each task: one directory for each argument or option that correspond to a particular job.

Note: one job may contain one command or multiple commands executed one after another. The commands should be separated by &&.

Here is an example of the file list_glost_example.txt with 8 jobs:

File : run_glost_test.sh

#!/bin/bash

#SBATCH --nodes=1
#SBATCH --ntasks-per-node=2
#SBATCH --time=00-02:00
#SBATCH --mem-per-cpu=4000M

# Load GLOST module:

module load intel/2023.2.1  openmpi/4.1.5 glost/0.3.1

echo "Starting run at: `date`"

# Run GLOST with the argument: list_glost_example.txt

srun glost_launch list_glost_example.txt

echo "Program glost_launch finished with exit code $? at: `date`"


File : list_glost_example.txt

job01 and/or other commands related to job01 
job02 and/or other commands related to job02
job03 and/or other commands related to job03
job04 and/or other commands related to job04
job05 and/or other commands related to job05
job06 and/or other commands related to job06
job07 and/or other commands related to job07
job08 and/or other commands related to job08


Note: the above example cannot be executed. The commands are not defined. It shows only:

  • a simple syntax for a list of jobs, list_glost_tasks.txt that will serve as an argument for the glost_launch wrapper;
  • a typical script to submit the job.

Both the list of jobs and the script should be adapted to your workflow.

List of jobs to run in one directory[edit]

GLOST can be used to run a set or a list of serial jobs in one directory. To avoid the overlap of the results, one has to make sure that the different jobs will not use the same temporary or output file. This can be achieved by adding arguments to differentiate the different jobs. In the following example, we have a list of 10 tasks. Each task may contain one or more commands. In this example, each job runs three commands one after another:

  • First command: Fix a variable nargument. This could be a parameter or a variable to pass to the program for example.
  • Second command: run the program. For testing, we have used the command sleep 360. This should be replaced by the command line to run your application. For example: ./my_first_prog < first_input_file.txt > first_output_file.txt
  • Third command: If needed, add one or more commands that will be executed just after the previous ones. All the commands should be separated by &&. For testing, we have used the command: echo ${nargument}.`hostname` > log_${nargument}.txt. For this command, we print out the argument and the hostname to a file log_${nargument}.txt. Similarly to the second command, this line should be replaced by another command line to run an application just after the previous one if needed. For example: ./my_second_prog < second_input_file.txt > second_output_file.txt.
File : run_glost_test.sh

#!/bin/bash

#SBATCH --nodes=1
#SBATCH --ntasks-per-node=2
#SBATCH --time=00-02:00
#SBATCH --mem-per-cpu=4000M

# Load GLOST module along with the modules required to run your application:

module load intel/2023.2.1  openmpi/4.1.5 glost/0.3.1

echo "Starting run at: `date`"

# Run GLOST with the argument: list_glost_tasks.txt

srun glost_launch list_glost_tasks.txt

echo "Program glost_launch finished with exit code $? at: `date`"


File : list_glost_tasks.txt

nargument=20 && sleep 360 && echo ${nargument}.`hostname` > log_${nargument}.txt
nargument=21 && sleep 360 && echo ${nargument}.`hostname` > log_${nargument}.txt
nargument=22 && sleep 360 && echo ${nargument}.`hostname` > log_${nargument}.txt
nargument=23 && sleep 360 && echo ${nargument}.`hostname` > log_${nargument}.txt
nargument=24 && sleep 360 && echo ${nargument}.`hostname` > log_${nargument}.txt
nargument=25 && sleep 360 && echo ${nargument}.`hostname` > log_${nargument}.txt
nargument=26 && sleep 360 && echo ${nargument}.`hostname` > log_${nargument}.txt
nargument=27 && sleep 360 && echo ${nargument}.`hostname` > log_${nargument}.txt
nargument=28 && sleep 360 && echo ${nargument}.`hostname` > log_${nargument}.txt
nargument=29 && sleep 360 && echo ${nargument}.`hostname` > log_${nargument}.txt


Note: In the above example, we have used 2 cores and a list of 10 jobs. GLOST will assign the first two jobs (two first lines) to the available processors, and whenever one and/or both of them are done with the first set of jobs, they will continue with the following jobs until the end of the list.

List of jobs to run in separate directories[edit]

Similarly to the previous case, GLOST can be used to run multiple serial jobs where each one is executed in a dedicated directory. This could be useful to run a program that uses files (temporary, input and/or output) with the same names in order to avoid the crash of the jobs or an overlap of the results from the different jobs. To do so, one has to make sure to create the input files and a directory for each job before running GLOST. It can be also achieved if included within the line commands as shown in the following example:

File : run_glost_test.sh

#!/bin/bash

#SBATCH --nodes=1
#SBATCH --ntasks-per-node=3
#SBATCH --time=00-03:00
#SBATCH --mem-per-cpu=4000M

# Load GLOST module along with the modules required to run your application:

module load intel/2023.2.1  openmpi/4.1.5 glost/0.3.1

echo "Starting run at: `date`"

# Run GLOST with the argument: list_glost_tasks.txt

srun glost_launch list_glost_tasks.txt

echo "Program glost_launch finished with exit code $? at: `date`"


File : list_glost_tasks.txt

nargument=20 && mkdir -p RUN_${nargument} && cd RUN_${nargument} && sleep 360 && echo ${nargument}.`hostname` > log_run.txt
nargument=21 && mkdir -p RUN_${nargument} && cd RUN_${nargument} && sleep 360 && echo ${nargument}.`hostname` > log_run.txt
nargument=22 && mkdir -p RUN_${nargument} && cd RUN_${nargument} && sleep 360 && echo ${nargument}.`hostname` > log_run.txt
nargument=23 && mkdir -p RUN_${nargument} && cd RUN_${nargument} && sleep 360 && echo ${nargument}.`hostname` > log_run.txt
nargument=24 && mkdir -p RUN_${nargument} && cd RUN_${nargument} && sleep 360 && echo ${nargument}.`hostname` > log_run.txt
nargument=25 && mkdir -p RUN_${nargument} && cd RUN_${nargument} && sleep 360 && echo ${nargument}.`hostname` > log_run.txt
nargument=26 && mkdir -p RUN_${nargument} && cd RUN_${nargument} && sleep 360 && echo ${nargument}.`hostname` > log_run.txt
nargument=27 && mkdir -p RUN_${nargument} && cd RUN_${nargument} && sleep 360 && echo ${nargument}.`hostname` > log_run.txt
nargument=28 && mkdir -p RUN_${nargument} && cd RUN_${nargument} && sleep 360 && echo ${nargument}.`hostname` > log_run.txt
nargument=29 && mkdir -p RUN_${nargument} && cd RUN_${nargument} && sleep 360 && echo ${nargument}.`hostname` > log_run.txt
nargument=30 && mkdir -p RUN_${nargument} && cd RUN_${nargument} && sleep 360 && echo ${nargument}.`hostname` > log_run.txt
nargument=31 && mkdir -p RUN_${nargument} && cd RUN_${nargument} && sleep 360 && echo ${nargument}.`hostname` > log_run.txt


Restarting a GLOST job[edit]

If you underestimated the wall time for your GLOST job, it may require to be restarted to complete the list of the jobs that were inserted in the list of glost tasks. In this case, make sure to identify the jobs that are already done in order to not run them again. Once identified, remove the corresponding lines from the list of the tasks or create a new list of the jobs that contain the remaining jobs from the previous GLOST job and resubmit your script using the new list as an argument for the glost_launch wrapper.

More examples[edit]

If you are an advanced user and familiar with scripting, you may have a look at the examples by making a copy of the original scripts and adapting them to your workflow.

After loading GLOST module, the examples can be copied to your local directory by running the command:

cp -r $EBROOTGLOST/examples Glost_Examples

The copy of the examples will be saved under the directory: Glost_Examples

Related links[edit]