diff --git a/docs.it4i/anselm/capacity-computing.md b/docs.it4i/anselm/capacity-computing.md index 2f7d0cb006540a50f990625026de582bd3fef4e2..4b191d815f60c55da8facc68533ece9721a6c578 100644 --- a/docs.it4i/anselm/capacity-computing.md +++ b/docs.it4i/anselm/capacity-computing.md @@ -2,14 +2,14 @@ ## Introduction -In many cases, it is useful to submit huge (>100+) number of computational jobs into the PBS queue system. Huge number of (small) jobs is one of the most effective ways to execute embarrassingly parallel calculations, achieving best runtime, throughput and computer utilization. +In many cases, it is useful to submit a huge (>100+) number of computational jobs into the PBS queue system. A huge number of (small) jobs is one of the most effective ways to execute embarrassingly parallel calculations, achieving the best runtime, throughput, and computer utilization. -However, executing huge number of jobs via the PBS queue may strain the system. This strain may result in slow response to commands, inefficient scheduling and overall degradation of performance and user experience, for all users. For this reason, the number of jobs is **limited to 100 per user, 1000 per job array** +However, executing a huge number of jobs via the PBS queue may strain the system. This strain may result in slow response to commands, inefficient scheduling, and overall degradation of performance and user experience, for all users. For this reason, the number of jobs is **limited to 100 per user, 1000 per job array** !!! note Please follow one of the procedures below, in case you wish to schedule more than 100 jobs at a time. -* Use [Job arrays](capacity-computing/#job-arrays) when running huge number of [multithread](capacity-computing/#shared-jobscript-on-one-node) (bound to one node only) or multinode (multithread across several nodes) jobs +* Use [Job arrays](capacity-computing/#job-arrays) when running a huge number of [multithread](capacity-computing/#shared-jobscript-on-one-node) (bound to one node only) or multinode (multithread across several nodes) jobs * Use [GNU parallel](capacity-computing/#gnu-parallel) when running single core jobs * Combine [GNU parallel with Job arrays](capacity-computing/#job-arrays-and-gnu-parallel) when running huge number of single core jobs @@ -21,7 +21,7 @@ However, executing huge number of jobs via the PBS queue may strain the system. ## Job Arrays !!! note - Huge number of jobs may be easily submitted and managed as a job array. + A huge number of jobs may easily be submitted and managed as a job array. A job array is a compact representation of many jobs, called subjobs. The subjobs share the same job script, and have the same values for all attributes and resources, with the following exceptions: @@ -29,15 +29,15 @@ A job array is a compact representation of many jobs, called subjobs. The subjob * job Identifiers of subjobs only differ by their indices * the state of subjobs can differ (R,Q,...etc.) -All subjobs within a job array have the same scheduling priority and schedule as independent jobs. Entire job array is submitted through a single qsub command and may be managed by qdel, qalter, qhold, qrls and qsig commands as a single job. +All subjobs within a job array have the same scheduling priority and schedule as independent jobs. An entire job array is submitted through a single qsub command and may be managed by qdel, qalter, qhold, qrls, and qsig commands as a single job. ### Shared Jobscript -All subjobs in job array use the very same, single jobscript. Each subjob runs its own instance of the jobscript. The instances execute different work controlled by $PBS_ARRAY_INDEX variable. +All subjobs in a job array use the very same, single jobscript. Each subjob runs its own instance of the jobscript. The instances execute different work controlled by the $PBS_ARRAY_INDEX variable. Example: -Assume we have 900 input files with name beginning with "file" (e. g. file001, ..., file900). Assume we would like to use each of these input files with program executable myprog.x, each as a separate job. +Assume we have 900 input files with the name of each beginning with "file" (e. g. file001, ..., file900). Assume we would like to use each of these input files with program executable myprog.x, each as a separate job. First, we create a tasklist file (or subjobs list), listing all tasks (subjobs) - all input files in our example: @@ -45,7 +45,7 @@ First, we create a tasklist file (or subjobs list), listing all tasks (subjobs) $ find . -name 'file*' > tasklist ``` -Then we create jobscript: +Then we create the jobscript: ```bash #!/bin/bash @@ -70,9 +70,9 @@ cp $PBS_O_WORKDIR/$TASK input ; cp $PBS_O_WORKDIR/myprog.x . cp output $PBS_O_WORKDIR/$TASK.out ``` -In this example, the submit directory holds the 900 input files, executable myprog.x and the jobscript file. As input for each run, we take the filename of input file from created tasklist file. We copy the input file to local scratch /lscratch/$PBS_JOBID, execute the myprog.x and copy the output file back to the submit directory, under the $TASK.out name. The myprog.x runs on one node only and must use threads to run in parallel. Be aware, that if the myprog.x **is not multithreaded**, then all the **jobs are run as single thread programs in sequential** manner. Due to allocation of the whole node, the accounted time is equal to the usage of whole node, while using only 1/16 of the node! +In this example, the submit directory holds the 900 input files, the executable myprog.x, and the jobscript file. As an input for each run, we take the filename of the input file from the created tasklist file. We copy the input file to the local scratch memory /lscratch/$PBS_JOBID, execute the myprog.x and copy the output file back to the submit directory, under the $TASK.out name. The myprog.x runs on one node only and must use threads to run in parallel. Be aware, that if the myprog.x **is not multithreaded**, then all the **jobs are run as single thread programs in a sequential** manner. Due to the allocation of the whole node, the accounted time is equal to the usage of the whole node, while using only 1/16 of the node! -If huge number of parallel multicore (in means of multinode multithread, e. g. MPI enabled) jobs is needed to run, then a job array approach should also be used. The main difference compared to previous example using one node is that the local scratch should not be used (as it's not shared between nodes) and MPI or other technique for parallel multinode run has to be used properly. +If running a huge number of parallel multicore (in means of multinode multithread, e. g. MPI enabled) jobs is needed, then a job array approach should be used. The main difference as compared to previous examples using one node is that the local scratch memory should not be used (as it's not shared between nodes) and MPI or other techniques for parallel multinode processing has to be used properly. ### Submit the Job Array @@ -83,9 +83,9 @@ $ qsub -N JOBNAME -J 1-900 jobscript 12345[].dm2 ``` -In this example, we submit a job array of 900 subjobs. Each subjob will run on full node and is assumed to take less than 2 hours (please note the #PBS directives in the beginning of the jobscript file, dont' forget to set your valid PROJECT_ID and desired queue). +In this example, we submit a job array of 900 subjobs. Each subjob will run on one full node and is assumed to take less than 2 hours (please note the #PBS directives in the beginning of the jobscript file, don't forget to set your valid PROJECT_ID and desired queue). -Sometimes for testing purposes, you may need to submit only one-element array. This is not allowed by PBSPro, but there's a workaround: +Sometimes for testing purposes, you may need to submit a one-element only array. This is not allowed by PBSPro, but there's a workaround: ```console $ qsub -N JOBNAME -J 9-10:2 jobscript @@ -95,7 +95,7 @@ This will only choose the lower index (9 in this example) for submitting/running ### Manage the Job Array -Check status of the job array by the qstat command. +Check status of the job array using the qstat command. ```console $ qstat -a 12345[].dm2 @@ -107,8 +107,8 @@ Job ID Username Queue Jobname SessID NDS TSK Memory Time S Time 12345[].dm2 user2 qprod xx 13516 1 16 -- 00:50 B 00:02 ``` -The status B means that some subjobs are already running. -Check status of the first 100 subjobs by the qstat command. +When the status is B it means that some subjobs are already running. +Check the status of the first 100 subjobs using the qstat command. ```console $ qstat -a 12345[1-100].dm2 @@ -152,7 +152,7 @@ Read more on job arrays in the [PBSPro Users guide](../pbspro/). !!! note Use GNU parallel to run many single core tasks on one node. -GNU parallel is a shell tool for executing jobs in parallel using one or more computers. A job can be a single command or a small script that has to be run for each of the lines in the input. GNU parallel is most useful in running single core jobs via the queue system on Anselm. +GNU parallel is a shell tool for executing jobs in parallel using one or more computers. A job can be a single command or a small script that has to be run for each of the lines in the input. GNU parallel is most useful when running single core jobs via the queue system on Anselm. For more information and examples see the parallel man page: @@ -175,7 +175,7 @@ First, we create a tasklist file, listing all tasks - all input files in our exa $ find . -name 'file*' > tasklist ``` -Then we create jobscript: +Then we create a jobscript: ```bash #!/bin/bash @@ -203,11 +203,11 @@ cat input > output cp output $PBS_O_WORKDIR/$TASK.out ``` -In this example, tasks from tasklist are executed via the GNU parallel. The jobscript executes multiple instances of itself in parallel, on all cores of the node. Once an instace of jobscript is finished, new instance starts until all entries in tasklist are processed. Currently processed entry of the joblist may be retrieved via $1 variable. Variable $TASK expands to one of the input filenames from tasklist. We copy the input file to local scratch, execute the myprog.x and copy the output file back to the submit directory, under the $TASK.out name. +In this example, tasks from the tasklist are executed via the GNU parallel. The jobscript executes multiple instances of itself in parallel, on all cores of the node. Once an instace of the jobscript is finished, a new instance starts until all entries in the tasklist are processed. Currently processed entries of the joblist may be retrieved via $1 variable. The variable $TASK expands to one of the input filenames from the tasklist. We copy the input file to local scratch memory, execute the myprog.x and copy the output file back to the submit directory, under the $TASK.out name. ### Submit the Job -To submit the job, use the qsub command. The 101 tasks' job of the [example above](capacity-computing/#gp_example) may be submitted like this: +To submit the job, use the qsub command. The 101 task job of the [example above](capacity-computing/#gp_example) may be submitted as follows: ```console $ qsub -N JOBNAME jobscript @@ -217,25 +217,25 @@ $ qsub -N JOBNAME jobscript In this example, we submit a job of 101 tasks. 16 input files will be processed in parallel. The 101 tasks on 16 cores are assumed to complete in less than 2 hours. !!! hint - Use #PBS directives in the beginning of the jobscript file, dont' forget to set your valid PROJECT_ID and desired queue. + Use #PBS directives at the beginning of the jobscript file, don't forget to set your valid PROJECT_ID and desired queue. ## Job Arrays and GNU Parallel !!! note - Combine the Job arrays and GNU parallel for best throughput of single core jobs + Combine the Job arrays and GNU parallel for the best throughput of single core jobs -While job arrays are able to utilize all available computational nodes, the GNU parallel can be used to efficiently run multiple single-core jobs on single node. The two approaches may be combined to utilize all available (current and future) resources to execute single core jobs. +While job arrays are able to utilize all available computational nodes, the GNU parallel can be used to efficiently run multiple single-core jobs on a single node. The two approaches may be combined to utilize all available (current and future) resources to execute single core jobs. !!! note Every subjob in an array runs GNU parallel to utilize all cores on the node ### GNU Parallel, Shared jobscript -Combined approach, very similar to job arrays, can be taken. Job array is submitted to the queuing system. The subjobs run GNU parallel. The GNU parallel shell executes multiple instances of the jobscript using all cores on the node. The instances execute different work, controlled by the $PBS_JOB_ARRAY and $PARALLEL_SEQ variables. +A combined approach, very similar to job arrays, can be taken. A job array is submitted to the queuing system. The subjobs run GNU parallel. The GNU parallel shell executes multiple instances of the jobscript using all of the cores on the node. The instances execute different work, controlled by the $PBS_JOB_ARRAY and $PARALLEL_SEQ variables. Example: -Assume we have 992 input files with name beginning with "file" (e. g. file001, ..., file992). Assume we would like to use each of these input files with program executable myprog.x, each as a separate single core job. We call these single core jobs tasks. +Assume we have 992 input files with each name beginning with "file" (e. g. file001, ..., file992). Assume we would like to use each of these input files with program executable myprog.x, each as a separate single core job. We call these single core jobs tasks. First, we create a tasklist file, listing all tasks - all input files in our example: @@ -243,13 +243,13 @@ First, we create a tasklist file, listing all tasks - all input files in our exa $ find . -name 'file*' > tasklist ``` -Next we create a file, controlling how many tasks will be executed in one subjob +Next we create a file, controlling how many tasks will be executed in one subjob: ```console $ seq 32 > numtasks ``` -Then we create jobscript: +Then we create a jobscript: ```bash #!/bin/bash @@ -279,34 +279,34 @@ cat input > output cp output $PBS_O_WORKDIR/$TASK.out ``` -In this example, the jobscript executes in multiple instances in parallel, on all cores of a computing node. Variable $TASK expands to one of the input filenames from tasklist. We copy the input file to local scratch, execute the myprog.x and copy the output file back to the submit directory, under the $TASK.out name. The numtasks file controls how many tasks will be run per subjob. Once an task is finished, new task starts, until the number of tasks in numtasks file is reached. +In this example, the jobscript executes in multiple instances in parallel, on all cores of a computing node. The variable $TASK expands to one of the input filenames from the tasklist. We copy the input file to local scratch memory, execute the myprog.x and copy the output file back to the submit directory, under the $TASK.out name. The numtasks file controls how many tasks will be run per subjob. Once a task is finished, a new task starts, until the number of tasks in the numtasks file is reached. !!! note Select subjob walltime and number of tasks per subjob carefully -When deciding this values, think about following guiding rules: +When deciding this values, keep in mind the following guiding rules: -1. Let n=N/16. Inequality (n+1) \* T < W should hold. The N is number of tasks per subjob, T is expected single task walltime and W is subjob walltime. Short subjob walltime improves scheduling and job throughput. -1. Number of tasks should be modulo 16. +1. Let n=N/16. Inequality (n+1) \* T < W should hold. N is the number of tasks per subjob, T is expected single task walltime and W is subjob walltime. Short subjob walltime improves scheduling and job throughput. +1. The number of tasks should be modulo 16. 1. These rules are valid only when all tasks have similar task walltimes T. ### Submit the Job Array (-J) -To submit the job array, use the qsub -J command. The 992 tasks' job of the [example above](capacity-computing/#combined_example) may be submitted like this: +To submit the job array, use the qsub -J command. The 992 task job of the [example above](capacity-computing/#combined_example) may be submitted like this: ```console $ qsub -N JOBNAME -J 1-992:32 jobscript 12345[].dm2 ``` -In this example, we submit a job array of 31 subjobs. Note the -J 1-992:**32**, this must be the same as the number sent to numtasks file. Each subjob will run on full node and process 16 input files in parallel, 32 in total per subjob. Every subjob is assumed to complete in less than 2 hours. +In this example, we submit a job array of 31 subjobs. Note the -J 1-992:**32**, this must be the same as the number sent to numtasks file. Each subjob will run on one full node and process 16 input files in parallel, 32 in total per subjob. Every subjob is assumed to complete in less than 2 hours. !!! hint - Use #PBS directives in the beginning of the jobscript file, dont' forget to set your valid PROJECT_ID and desired queue. + Use #PBS directives at the beginning of the jobscript file, don't forget to set your valid PROJECT_ID and desired queue. ## Examples -Download the examples in [capacity.zip](capacity.zip), illustrating the above listed ways to run huge number of jobs. We recommend to try out the examples, before using this for running production jobs. +Download the examples in [capacity.zip](capacity.zip), illustrating the above listed ways to run a huge number of jobs. We recommend trying out the examples before using this for running production jobs. Unzip the archive in an empty directory on Anselm and follow the instructions in the README file