Skip to content

Checkpointing

about 4 minutesStudents, Staffchecked 13 November 2024

Checkpointing a job means that you frequently save the job state so that you can resume computation from the last checkpoint in case of a crash. On this page we provide some useful information for making your own code checkpoint-able.

Imagine a job is already running for several hours when an event occurs which leads to the abortion of the job. Such events can be:

  • Exceeding the time limit
  • Exceeding allocated memory
  • Job gets preempted by another job (gpu partition only!)
  • Node failure

General recipe for checkpointing your own code

Section titled “General recipe for checkpointing your own code”

Introducing checkpointing logic in your code consists of 3 steps

  1. Look for a state file containing a previously saved state.
  2. If a state file exists, then restore the state. Else, start from scratch.
  3. Periodically save the state.

You can save the state of your job at specific points in time, after certain iterations, or at whatever event you choose to trigger a state saving. You can also trap specific UNIX signals and act as soon as the signal occurs. The following table lists common signals that you might want to trap in your program:

Signal NameSignal NumberDescriptionDefault Disposition
SIGTERM15SIGTERM initiates the termination of a processTerm - Terminate the process
SIGCONT18SIGCONT continues a stopped processCont - Continue the process if stopped
SIGUSR110User-defined signals. SIGUSR1/SIGUSR2 are never sent by the kernelTerm - Terminate the process
SIGUSR212User-defined signals. SIGUSR1/SIGUSR2 are never sent by the kernelTerm - Terminate the process

SLURM sends SIGCONT followed by SIGTERM just before a job is canceled. Trapping the signal (e.g. SIGTERM) gives you 60 seconds for housekeeping tasks, e.g. save current state. At the latest after that your job is canceled with SIGKILL. This is true for jobs canceled by the owner using scancel and jobs canceled by SLURM, e.g. because of exceeding time limit.

Register a signal handler for a UNIX signal

Section titled “Register a signal handler for a UNIX signal”

The following examples show how to register a signal handler in different languages, but omit the logic for creating a checkpoint and restart a job from an existing checkpoint. We will provide a working example further down below on this page.

Bash

bash
#!/bin/bash
function signal_handler {
# Save program state and exit
(...)
exit
}
trap signal_handler TERM
(...)

C/C++

c++
#include <signal.h> // C
#include <csignal> // C++
void signal_handler(int signal) {
// Save program state and exit
(...)
exit(0);
}
// Register signal handler for SIGTERM
signal(SIGTERM, signal_handler); // signal_handler: function to handle signal
(...)

Python

python
#! /usr/bin/env python
import signal
import sys
def signal_handler(sig, frame):
# Save program state and exit
(...)
sys.exit(0)
signal.signal(signal.SIGTERM, signal_handler)
(...)

Signaling checkpoint creation without canceling the job

Section titled “Signaling checkpoint creation without canceling the job”

SLURM distinguishes between the job script, its child processes and job steps. Job steps are launched using srun.

All applications which should reveive more signals than the default SIGERM at the end of the job, does need to be started using srun. Then signals (here SIGUSR1) can be send using:

bash
scancel --signal=USR1 <jobID>

If you need/want to handle signals with the batch script, add --batch (signals only to the batch script) or --full (signal to all steps and the batch script), e.g.

bash
scancel --full --signal=USR1 <jobid>

Therewith, you can use a UNIX signal to trigger the creation of a checkpoint of a running job. For example, consider a job that traps SIGUSR1 and saves intermediate results as soon as the signal occurs. You can then create a checkpoint by signaling SIGUSR1 to the job.