Running batch jobs at TACC

Running batch jobs at TACC

Compute cluster overview

When you SSH into ls6, your session is assigned to one of a small set of login nodes (also called head nodes). These are separate from the cluster compute nodes that will run your jobs.

Think of a TACC node as a computer, like your laptop, but probably with more cores and memory. Now multiply that computer a thousand or more, and you have a cluster.

The small set of login nodes are a shared resource – type the users command to see everyone currently logged in. Login nodes are not meant for running interactive programs – for that you submit a description of what you want done to a batch system, which distributes the work to one or more compute nodes.

On the other hand, the login nodes are intended for copying files to and from TACC, so they have a lot of network bandwidth while compute nodes have limited network bandwidth.

So follow these guidelines:

  • Do not perform substantial computation on the login nodes.

    • They are closely monitored, and you will get warnings – or worse – from the TACC admin folks!

  • Do not perform significant network access from your batch jobs.

    • Instead, stage your data from a login node onto $SCRATCH before submitting your job.

So what about developing and testing your code and workflows? Initial code development is often performed elsewhere, then migrated to TACC once is is relatively stable. But for local testing and troubleshooting, TACC offers interactive development (idev) nodes. We'll be taking advantage of idev nodes later on.

Lonestar6 and Stampede3 overview and comparison

Here is a comparison of the configurations and ls6 and stampede3. stampede3 is the newer (and larger) cluster, launched in 2024; ls6 was launched in 2022.



ls6

stampede3



ls6

stampede3

login nodes

3

128 cores each
256 GB memory

4

96 cores each
250 GB memory

standard compute nodes

560 AMD Epyc 7763 "Milan" nodes

  • 128 cores per node

  • 256 GB system memory

  • 288 GB local storage on /tmp

560 Intel Xeon "Sapphire Rapids" nodes

  • 112 cores per node

  • 128 GB memory

1060 Intel Platinum 8160 "Skylake" nodes

  • 48 cores per node

  • 192 GB memory

224 Intel Xenon Platinum 8380 "Ice Lake" nodes

  • 80 cores per node

  • 256 GB memory

GPU nodes

88 AMD Epyc 7763 "Milan" nodes

  • 128 cores per node

  • 256 GB memory

84 GPU nodes have

  • 3x NVIDIA A100 GPUs
    w/40GB RAM each

4 GPU nodes have

  • 2x NVIDIA H100 GPUs
    w/40GB RAM each

20 GPU Max 1550 "Ponte Vecchio" nodes

  • 96 cores per node

  • 512 GB memory

  • 4x Intel GPU Max 1550 GPUs w/128GB RAM each

batch system

SLURM

SLURM

maximum job run time

48 hours, normal queue

2 hours, development queue

48 hours on GPU nodes

24 hours on other nodes, normal queue

2 hours, development queue

User guides for ls6 and stampede3 can be found at:

Unfortunately, the TACC user guides are aimed towards a different user community – the weather modelers and aerodynamic flow simulators who need very fast matrix manipulation and other High Performance Computing (HPC) features. The usage patterns for bioinformatics – generally running 3rd party tools on many different datasets – is rather a special case for HPC. TACC calls our type of processing "parameter sweep jobs" and has a special process for running them, using their launcher module.

Software at TACC

Programs and your $PATH

When you type in the name of an arbitrary program (ls for example), how does the shell know where to find that program? The answer is your $PATH. $PATH is a predefined environment variable whose value is a list of directories.The shell looks for program names in that list, in the order the directories appear.

To determine where the shell will find a particular program, use the which command. Note that which tells you where it looked if it cannot find the program.

Using which to search $PATH
which rsync which cat which bwa # not yet available to you

The module system

The module system is an incredibly powerful way to have literally thousands of software packages available, some of which are incompatible with each other, without causing complete havoc. The TACC staff stages packages in well-known locations that are NOT on your $PATH. Then, when a module is loaded, its binaries are added to your $PATH.

For example, the following module load command makes the apptainer container management system available to you:

How module load affects $PATH
# first type "apptainer" to show that it is not present in your environment: apptainer # it's not on your $PATH either: which apptainer # now add biocontainers to your environment and try again: module load biocontainers # and see how apptainer is now on your $PATH: which apptainer # you can see the new directory at the front of $PATH echo $PATH # to remove it, use "unload" module unload biocontainers apptainer # gone from $PATH again... which apptainer

Note that apptainer is another name for singularity.

TACC BioContainers modules

It is quite a large systems administration task to install software at TACC and configure it for the module system. As a result, TACC was always behind in making important bioinformatics software available. To address this problem, TACC moved to providing bioinformatics software via containers, which are similar to virtual machines like VMware and Virtual Box, but are lighter weight: they require less disk space because they rely more on the host's base Linux environment. Specifically, TACC (and many other HPC/High Performance Computing clusters) use Apptainer containers, which are similar to Docker containers but are more suited to the HPC environment – in fact one can build a Docker container then easily convert it to Apptainer for use at TACC.

TACC obtains its containers from BioContainers (https://biocontainers.pro/ and https://github.com/BioContainers/containers), a large public repository of bioinformatics tool Apptainer containers. This has allowed TACC to easily provision thousands of such tools!

These BioContainers are not visible in TACC's "standard" module system, but only after the master biocontainers module is loaded. Once it has been loaded, you can search for your favorite bioinformatics program using module spider.

# Verify that samtools is not available samtools # and cannot be found in the standard module system module spider samtools # Load the BioContainers master module (this takes a while) module load biocontainers # Now look for these programs module spider samtools module spider Rstats module spider kallisto module spider bowtie2 module spider minimap2 module spider multiqc module spider gatk module spider velvet

Notice how the BioContainers module names have "ctr" in their names, version numbers, and other identifying information.

The standard TACC module system has been phased out for bioinformatics programs, so always look for your application in BioContainers.

While it's great that there are now hundreds of programs available through BioContainers, the one drawback is that they can only be run on cluster compute nodes, not on login nodes.

To test BioContainer program interactively – or even to ask the program for its usage – you will need to use TACC's idev command to obtain an interactive cluster node. More on this shortly...

loading a biocontainer module

Once the biocontainers module has been loaded, you can just module load the desired tool, as with the kallisto pseudo-aligner program below.

# Load the Biocontainers master module module load biocontainers # Verify kallisto is not yet available kallisto # Load the default kallisto biocontainer module load kallisto # Verify kallisto is available -- but not on login nodes kallisto

Note that loading a BioContainer does not add anything to your $PATH. Instead, it defines an alias, which is just a shortcut for executing the command using its container. You can see the alias definition using the type command. And you can ensure the program is available using the command -v utility.

# Note that kallisto has not been added to your $PATH, but instead has an alias which kallisto # Ensure kallisto is available with command -v command -v kallisto # To see how TACC calls the kallisto container: type kallisto

installing custom software

Even with all the tools available at TACC, inevitably you'll need something they don't have. In this case you can build the tool yourself and install it in a local TACC directory. While building 3rd party tools is beyond the scope of this course, it's really not that hard. The trick is keeping it all organized.

For one thing, remember that your $HOME directory quota is fairly small (10 GB on ls6), and that can fill up quickly if you install many programs. We recommend creating an installation area in your $WORK directory and installing programs there. You can then make symbolic links to the binaries you need in your ~/local/bin directory (which was added to your $PATH in your .bashrc).

See how we used a similar trick to make the launcher_creator.py program available to you. Using the ls -l option shows you where symbolic links point to:

Real location of launcher_creator.py
ls -l ~/local/bin # this will tell you the real location of the launcher_creator.py script is # /work/projects/BioITeam/common/bin/launcher_creator.py

$PATH caveat

Remember that the order of locations in the $PATH environment variable is the order in which the locations will be searched.

Job Execution

Job execution is controlled by the SLURM batch system on both stampede3 and ls6.

To run a job you prepare 2 files:

  1. a commands file file containing the commands to run, one task per line (<job_name>.cmds)

  2. a job control file that describes how to run the job (<job_name>.slurm)

The process of running the job involves these steps:

  1. Create a commands file containing exactly one task per line.

  2. Prepare a job control file for the commands file that describes how the job should be run.

  3. You submit the job control file to the batch system.

    1. The job is then said to be queued to run.

  4. The batch system prioritizes the job based on the number of compute nodes needed and the job run time requested.

  5. When compute nodes become available, the job tasks (command lines in the <job_name>.cmds file) are assigned to one or more compute nodes and begin to run in parallel.

  6. The job completes when either:

    1. you cancel the job manually

    2. all job tasks complete (successfully or not!)

    3. the requested job run time has expired

SLURM at a glance

Here are the main components of the SLURM batch system.



ls6, stampede3



ls6, stampede3

batch system

SLURM

batch control file name

<job_name>.slurm

job submission command

sbatch <job_name>.slurm

job monitoring command

showq -u

job stop command

scancel -n <job name>

Simple example

Let's go through a simple example. Execute the following commands to copy a premade simple.cmds commands file:

Copy simple commands
cds mkdir -p core_ngs/slurm/simple cd core_ngs/slurm/simple cp $CORENGS/tacc/simple.cmds .

What are the tasks we want to do? Each task corresponds to one line in the simple.cmds commands file, so let's take a look at it using the cat (concatenate) command that simply reads a file and writes each line of content to standard output (here, your Terminal):

View simple commands
cat simple.cmds

The tasks we want to perform look like this:

simple.cmds commands file
sleep 5; echo "Command 1 on `hostname` - `date`" > cmd1.log 2>&1 sleep 5; echo "Command 2 on `hostname` - `date`" > cmd2.log 2>&1 sleep 5; echo "Command 3 on `hostname` - `date`" > cmd3.log 2>&1 sleep 5; echo "Command 4 on `hostname` - `date`" > cmd4.log 2>&1 sleep 5; echo "Command 5 on `hostname` - `date`" > cmd5.log 2>&1 sleep 5; echo "Command 6 on `hostname` - `date`" > cmd6.log 2>&1 sleep 5; echo "Command 7 on `hostname` - `date`" > cmd7.log 2>&1 sleep 5; echo "Command 8 on `hostname` - `date`" > cmd8.log 2>&1

There are 8 tasks. Each task sleeps for 5 seconds, then uses the echo command to output a string containing the task number and date to a log file named for the task number. Notice that we can put two commands on one line if they are separated by a semicolon ( ; ).

You can count the number of lines in the simple.cmds file using the wc (word count) command with the -l (lines) option:

Count file lines
wc -l simple.cmds

Use the handy launcher_creator.py program to create the job control file.

Set up ~/local/bin directory
mkdir -p ~/local/bin cd ~/local/bin ln -s -f /work/projects/BioITeam/common/bin/launcher_creator.py
Create batch submission script for simple commands
launcher_creator.py -j simple.cmds -n simple -t 00:01:00 -a OTH21164

You should see output something like the following, and you should see a simple.slurm batch submission file in the current directory.

Project simple. Using job file simple.cmds. Using normal queue. For 00:01:00 time. Using OTH21164 allocation. Not sending start/stop email. Launcher successfully created. Type "sbatch simple.slurm" to queue your job.

Submit your batch job then check the batch queue to see the job's status.

Submit simple job to batch queue
sbatch simple.slurm showq -u # Output looks something like this: ------------------------------------------------------------- Welcome to the Lonestar6 Supercomputer ------------------------------------------------------------- --> Verifying valid submit host (login2)...OK --> Verifying valid jobname...OK --> Verifying valid ssh keys...OK --> Verifying access to desired queue (normal)...OK --> Checking available allocation (OTH21164)...OK Submitted batch job 2411919

The queue status will initially show your job as WAITING until a node becomes available:

SUMMARY OF JOBS FOR USER: <abattenh> ACTIVE JOBS-------------------- JOBID JOBNAME USERNAME STATE NODES REMAINING STARTTIME ================================================================================ WAITING JOBS------------------------ JOBID JOBNAME USERNAME STATE NODES WCLIMIT QUEUETIME ================================================================================ 2411919 simple abattenh Waiting 1 0:01:00 Wed May 28 15:39:24 Total Jobs: 1 Active Jobs: 0 Idle Jobs: 1 Blocked Jobs: 0

Once your job is ACTIVE (running) you'll see something like this:

SUMMARY OF JOBS FOR USER: <abattenh> ACTIVE JOBS-------------------- JOBID JOBNAME USERNAME STATE NODES REMAINING STARTTIME ================================================================================ 1722779 simple abattenh Running 1 0:00:39 Sat Jun 1 21:55:28 WAITING JOBS------------------------ JOBID JOBNAME USERNAME STATE NODES WCLIMIT QUEUETIME ================================================================================ Total Jobs: 1 Active Jobs: 1 Idle Jobs: 0 Blocked Jobs: 0

If you don't see your simple job in either the ACTIVE or WAITING sections of your queue, it probably already finished – it should only run for a few seconds!

Notice in my queue status, where the STATE is Running, there is only one node assigned. Why is this, since there were 8 tasks?

Every job, no matter how few tasks requested, will be assigned at least one node. Each lonestar6 node has 128 physical cores, so each of the 8 tasks can be assigned to a different core.

Exercise: What files were created by your job?

ls should show you something like this:

cmd1.log cmd3.log cmd5.log cmd7.log simple.cmds simple.o924965 cmd2.log cmd4.log cmd6.log cmd8.log simple.e924965  simple.slurm

The newly created files are the .log files, as well as error and output logs simple.e924965 and simple.o924965.

filename wildcarding

You can look at one of the output log files like this:

cat cmd1.log

But here's a cute trick for viewing the contents all your output files at once, using the cat command and filename wildcarding.

Multi-character filename wildcarding
cat cmd*.log

The cat command can take a list of one or more files. The asterisk ( * ) in cmd*.log is a multi-character wildcard that matches any filename starting with cmd then ending with .log.

You can also specify single-character matches inside brackets ( [ ] ) in either of the ways below, this time using the ls command so you can better see what is matching:

Single character filename wildcarding
ls cmd[1234].log ls cmd[2-6].log

This technique is sometimes called filename globbing, and the pattern a glob. Don't ask me why – it's a Unix thing. Globbing – translating a glob pattern into a list of files – is one of the handy thing the bash shell does for you. (Read more about Pathname wildcards)

Exercise: How would you list all files starting with "simple"?

ls simple*

Here's what my cat output looks like. Notice the times are all nearly the same because all the tasks ran in parallel. That's the power of cluster computing!

Command 1 on c304-005.ls6.tacc.utexas.edu - Sat Jun 1 21:55:47 CDT 2024 Command 2 on c304-005.ls6.tacc.utexas.edu - Sat Jun 1 21:55:47 CDT 2024 Command 3 on c304-005.ls6.tacc.utexas.edu - Sat Jun 1 21:55:51 CDT 2024 Command 4 on c304-005.ls6.tacc.utexas.edu - Sat Jun 1 21:55:48 CDT 2024 Command 5 on c304-005.ls6.tacc.utexas.edu - Sat Jun 1 21:55:45 CDT 2024 Command 6 on c304-005.ls6.tacc.utexas.edu - Sat Jun 1 21:55:49 CDT 2024 Command 7 on c304-005.ls6.tacc.utexas.edu - Sat Jun 1 21:55:51 CDT 2024 Command 8 on c304-005.ls6.tacc.utexas.edu - Sat Jun 1 21:55:48 CDT 2024

echo

Lets take a closer look at a typical task in the simple.cmds file.

A simple.cmds task line
sleep 5; echo "Command 3 `date`" > cmd3.log 2>&1

The echo command is like a print statement in the bash shell.  echo takes its arguments and writes them to standard output. While not always required, it is a good idea to put echo's output string in double quotes ( " ).

backtick evaluation

So what is this funny looking `date` bit doing? Well, date is just another Linux command (try just typing it in) that just displays the current date and time. Here we don't want the shell to put the string "date" in the output, we want it to execute the date command and put the result text into the output. The backquotes ( ` ` ) also called backticks, around the date command tell the shell we want that command executed and its standard output substituted into the string. (Read more about Quoting in the shell)

Backtick evaluation
# These are equivalent: date echo `date` # But different from this: echo date

output redirection

There's still more to learn from one of our simple tasks, something called output redirection.

Every command and Unix program has three "built-in" streams: standard input, standard output and standard error, each with a name, a number, and a redirection syntax.



Normally echo writes its string to standard output, but it could encounter an error and write an error message to standard error. We want both standard output and standard error for each task stored in a log file named for the command number.

A simple.cmds task line
sleep 5; echo "Command 3 `date`" > cmd3.log 2>&1

So in the above example the first '>' says to redirect the standard output of the echo command to the cmd3.log file.

The '2>&1' part says to redirect standard error to the same place. Technically, it says to redirect standard error (built-in Linux stream 2) to the same place as standard output (built-in Linux stream 1). Since standard output is going to cmd3.log, any standard error will go there also. (Read more about Standard streams and redirection)

When the TACC batch system runs a job, all outputs generated by tasks in the batch job are directed to one output and error file per job. Here they have names like simple.e2411919 and simple.o24119195.

  • simple.o2411919 contains all standard output generated by your task that was not redirected elsewhere

  • simple.e2411919 contains all standard error generated by your tasks that was not redirected elsewhere

  • both also contain information relating to running your job and its tasks

For large jobs with complex tasks, it is not easy to troubleshoot execution problems using these files.

So a best practice is to separate the outputs of each of the tasks into an individual log file, one per task, as we do here. Why is this important? Suppose we run a job with 100 commands, each one a whole pipeline (alignment, for example). 88 finish fine but 12 do not. Just try figuring out which ones had the errors, and where the errors occurred, if all the standard output is in one intermingled file and all standard error in the other intermingled file!

Job parameters

Now that we've executed a really simple job, let's take a look at some important job submission parameters. These correspond to arguments to the launcher_creator.py script.