Singularity Recipes and Hints¶
Example Definitions¶
Basic Example¶
A usual workflow to create Singularity Definition consists of the following steps:
- Start from base image
- Install dependencies
- Package manager
- Other sources
- Build and install own binaries
- Provide entry points and metadata
An example doing all this:
Bootstrap: docker
From: alpine
%post
. /.singularity.d/env/10-docker*.sh
apk add g++ gcc make wget cmake
wget https://github.com/fmtlib/fmt/archive/5.3.0.tar.gz
tar -xf 5.3.0.tar.gz
mkdir build && cd build
cmake ../fmt-5.3.0 -DFMT_TEST=OFF
make -j$(nproc) install
cd ..
rm -r fmt-5.3.0*
cat <<'EOF' >> hello.cpp
#include <fmt/format.h> // literal
int main(int argc, char** argv){
if(argc == 1) fmt::print("No arguments passed!\n");
else fmt::print("Hello {}!\n", argv[1]);
}
EOF
g++ hello.cpp -o hello -lfmt
mv hello /usr/bin/hello
%runscript
hello "$@"
%labels
Author Alexander Grund
Version 1.0.0
%help
Display a greeting using the fmt library
Usage:
./hello
Distributed memory¶
MPICH¶
Ubuntu+MPICH definition file:
Bootstrap: docker
From: ubuntu:20.04
%files
mpitest.c /opt
%environment
export MPICH_DIR=/opt/mpich
export SINGULARITY_MPICH_DIR=${MPICH_DIR}
export SINGULARITYENV_APPEND_PATH=${MPICH_DIR}/bin
export SINGULAIRTYENV_APPEND_LD_LIBRARY_PATH=${MPICH_DIR}/lib
%post
echo "Installing required packages..."
apt-get update && apt-get install -y wget git bash gcc gfortran g++ make file
# required for F90 bindings
apt-get install -y python3
echo "Installing MPICH"
export MPICH_DIR=/opt/mpich
export MPICH_VERSION=4.1
export MPICH_URL="https://www.mpich.org/static/downloads/${MPICH_VERSION}/mpich-${MPICH_VERSION}.tar.gz"
mkdir -p /tmp/mpich
mkdir -p /opt
# Download
cd /tmp/mpich && wget -O mpich-${MPICH_VERSION}.tar.gz ${MPICH_URL} && tar -xf mpich-${MPICH_VERSION}.tar.gz
# Configure and compile/install
cd /tmp/mpich/mpich-${MPICH_VERSION}
./configure --prefix=${MPICH_DIR} && make install
# Set env variables so we can compile our application
export PATH=${MPICH_DIR}/bin:${PATH}
export LD_LIBRARY_PATH=${MPICH_DIR}/lib:${LD_LIBRARY_PATH}
export MANPATH=${MPICH_DIR}/share/man:${MANPATH}
echo "Compiling the MPI application..."
cd /opt && mpicc -o mpitest mpitest.c
At your local machine:
marie@local$ sudo singularity build ubuntu_mpich.sif ubuntu_mpich.def
This will create the ubuntu_mpich.sif
file that you have to copy to HPC system.
At the HPC system run as following:
marie@login$ srun ---nodes=4 --ntasks-per-node=2 --time=00:10:00 singularity exec ubuntu_mpich.sif /opt/mpitest
CUDA + CuDNN + Open MPI¶
- Chosen CUDA version depends on installed driver of host
- Open MPI needs PMI for Slurm integration
- Open MPI needs CUDA for GPU copy-support
- Open MPI needs
ibverbs
library for InfiniBand openmpi-mca-params.conf
required to avoid warnings on fork (OK on ZIH systems)- Environment variables
SLURM_VERSION
andOPENMPI_VERSION
can be set to choose different version when building the container
Bootstrap: docker
From: nvidia/cuda-ppc64le:10.1-cudnn7-devel-ubuntu18.04
%labels
Author ZIH
Requires CUDA driver 418.39+.
%post
. /.singularity.d/env/10-docker*.sh
apt-get update
apt-get install -y cuda-compat-10.1
apt-get install -y libibverbs-dev ibverbs-utils
# Install basic development tools
apt-get install -y gcc g++ make wget python
apt-get autoremove; apt-get clean
cd /tmp
: ${SLURM_VERSION:=17-02-11-1}
wget https://github.com/SchedMD/slurm/archive/slurm-${SLURM_VERSION}.tar.gz
tar -xf slurm-${SLURM_VERSION}.tar.gz
cd slurm-slurm-${SLURM_VERSION}
./configure --prefix=/usr/ --sysconfdir=/etc/slurm --localstatedir=/var --disable-debug
make -C contribs/pmi2 -j$(nproc) install
cd ..
rm -rf slurm-*
: ${OPENMPI_VERSION:=3.1.4}
wget https://download.open-mpi.org/release/open-mpi/v${OPENMPI_VERSION%.*}/openmpi-${OPENMPI_VERSION}.tar.gz
tar -xf openmpi-${OPENMPI_VERSION}.tar.gz
cd openmpi-${OPENMPI_VERSION}/
./configure --prefix=/usr/ --with-pmi --with-verbs --with-cuda
make -j$(nproc) install
echo "mpi_warn_on_fork = 0" >> /usr/etc/openmpi-mca-params.conf
echo "btl_openib_warn_default_gid_prefix = 0" >> /usr/etc/openmpi-mca-params.conf
cd ..
rm -rf openmpi-*
Hints¶
GUI (X11) Applications¶
Running GUI applications inside a singularity container is possible out of the box. Check the following definition:
Bootstrap: docker
From: centos:7
%post
yum install -y xeyes
This image may be run with
singularity exec xeyes.sif xeyes.
This works because all the magic is done by Singularity already like setting ${DISPLAY}
to the
outside display and mounting ${HOME}
so ${HOME}/.Xauthority
(X11 authentication cookie) is
found. When you are using --contain
or --no-home
you have to set that cookie yourself or
mount/copy it inside the container. Similar for --cleanenv
you have to set ${DISPLAY}
, e.g., via
export SINGULARITY_DISPLAY=${DISPLAY}
When you run a container as root (via sudo
) you may need to allow root for your local display
port: xhost +local:root\
Hardware Acceleration¶
If you want hardware acceleration, you may need VirtualGL. An example definition file is as follows:
Bootstrap: docker
From: centos:7
%post
yum install -y glx-utils # for glxgears example app
yum install -y curl
VIRTUALGL_VERSION=2.6.2 # Replace by required (e.g. latest) version
curl -sSL https://downloads.sourceforge.net/project/virtualgl/"${VIRTUALGL_VERSION}"/VirtualGL-"${VIRTUALGL_VERSION}".x86_64.rpm -o VirtualGL-"${VIRTUALGL_VERSION}".x86_64.rpm
yum install -y VirtualGL*.rpm
/opt/VirtualGL/bin/vglserver_config -config +s +f -t
rm VirtualGL-*.rpm
# Install video drivers AFTER VirtualGL to avoid them being overwritten
yum install -y mesa-dri-drivers # for e.g. intel integrated GPU drivers. Replace by your driver
You can now run the application with vglrun
:
singularity exec vgl.sif vglrun glxgears
Warning
Using VirtualGL may not be required at all and could even decrease the performance.
To check install, e.g., glxgears
as above and your graphics driver (or use the VirtualGL image
from above) and disable vsync
:
vblank_mode=0 singularity exec vgl.sif glxgears
Compare the FPS output with the glxgears
prefixed by vglrun
(see above) to see which produces more
FPS (or runs at all).
NVIDIA GPUs need the --nv
parameter for the Singularity command:
singularity exec --nv vgl.sif glxgears
Singularity Temporary and Cache Directories¶
Singularity uses /tmp
to store temporary data, e. g., when you use pull
or build
. Because
there are also diskless nodes, you may use the environment variable SINGULARITY_TMPDIR
to change
the storage place for temporary data. You can use the following line to indicate a different
location for temporary data:
export SINGULARITY_TMPDIR=$SOME_WORKSPACE/singularity_tmp
Singularity commands invoked afterwards store temporary data at the indicated location.
Singularity caches data in your home directory by default
Another location where Singularity stores data is your home directory! This is problematic when Singularity caches too many containers, because you cannot start Slurm jobs if you are over a certain limit. To prevent that from happening, indicate a different location for cache space, e. g., a workspace:
export SINGULARITY_CACHEDIR=$SOME_WORKSPACE/singularity_cache
Further information on both environment variables can be found on the official Singularity documentation.