Skip to content

Resource Management

Exercises

  1. Configure a GPU GRES

Add a new GPU node gpu09 with 2 NVIDIA A100 GPUs to the cluster. Define the GRES in both slurm.conf and gres.conf. Use AutoDetect=nvml in gres.conf if gpu09 is a persistent node; show the explicit form you would need if it were a State=CLOUD node.

Hint / Solution
# In slurm.conf, add the node definition:
#   NodeName=gpu09 CPUs=64 RealMemory=512000 Gres=gpu:a100:2

# In gres.conf (on gpu09 or globally):
#   AutoDetect=nvml
# Or explicitly:
#   Name=gpu Type=a100 File=/dev/nvidia0 Cores=0-31
#   Name=gpu Type=a100 File=/dev/nvidia1 Cores=32-63

# Restart slurmctld (new node requires restart)
systemctl restart slurmctld

# Start slurmd on the new node
ssh gpu09 systemctl start slurmd
Expected output: Validated 2026-10-19 on slurm-training-val (Slurm 25.11.8, ParallelCluster 3.16.1).
$ echo 'NodeName=batch-dy-compute-1 CPUs=8 RealMemory=31129 State=CLOUD Feature=dynamic,t3.2xlarge,compute Weight=1000 Gres=val_fpga:2'
NodeName=batch-dy-compute-1 CPUs=8 RealMemory=31129 State=CLOUD Feature=dynamic,t3.2xlarge,compute Weight=1000 Gres=val_fpga:2

$ echo 'NodeName=batch-dy-compute-1 Name=val_fpga Count=2'
NodeName=batch-dy-compute-1 Name=val_fpga Count=2

$ ssh batch-dy-compute-1 'sudo systemctl restart slurmd'
Warning: Permanently added 'batch-dy-compute-1' (ED25519) to the list of known hosts.

$ grep val_fpga /opt/slurm/etc/pcluster/slurm_parallelcluster_batch_partition.conf /opt/slurm/etc/pcluster/slurm_parallelcluster_batch_gres.conf
/opt/slurm/etc/pcluster/slurm_parallelcluster_batch_gres.conf:NodeName=batch-dy-compute-1 Name=val_fpga Count=2

$ scontrol show node batch-dy-compute-1 | grep -E '(NodeName|Gres|CfgTRES)'
NodeName=batch-dy-compute-1 Arch=x86_64 CoresPerSocket=1 
   Gres=(null)
   CfgTRES=cpu=8,mem=31129M,billing=8
  1. Verify GRES with scontrol show node

Inspect a GPU node to confirm the GRES are correctly detected and available. Check both the configured GRES count and how many are currently allocated.

Hint / Solution
# Show full node details including GRES
scontrol show node gpu01

# Look for these fields in the output:
#   Gres=gpu:a100:4
#   CfgTRES=cpu=64,mem=512000M,billing=64,gres/gpu=4
#   AllocTRES=              (empty if no jobs running)
#   GresUsed=gpu:a100:0(IDX:)

# Check all GPU nodes at once
scontrol show nodes gpu[01-08] | grep -E "NodeName|Gres|AllocTRES"
Expected output: Validated 2026-10-19 on slurm-training-val (Slurm 25.11.8, ParallelCluster 3.16.1).
$ scontrol show node gpu-dy-t4-1 | grep -E '(NodeName|Gres|CfgTRES|AllocTRES)'
NodeName=gpu-dy-t4-1 CoresPerSocket=1 
   Gres=gpu:t4:1
   CfgTRES=cpu=4,mem=15564M,billing=4,gres/gpu=1
   AllocTRES=
  1. Add a license resource

Add 20 Schrodinger Glide licenses as a cluster-wide resource. Submit a test job requesting one license and verify that Slurm tracks the allocation.

Hint / Solution
# In slurm.conf, add or update the Licenses line:
#   Licenses=schrodinger_glide:20

scontrol reconfigure

# Verify the licenses are registered
scontrol show licenses
# Should show: LicenseName=schrodinger_glide Total=20 Used=0 Free=20

# Submit a test job requesting a license
sbatch --licenses=schrodinger_glide:1 --wrap="sleep 60"

# Check that the license is allocated
scontrol show licenses
# Used should now be 1, Free should be 19
Expected output: Validated 2026-10-19 on slurm-training-val (Slurm 25.11.8, ParallelCluster 3.16.1).
$ scontrol show licenses
LicenseName=val_glide
    Total=5 Used=0 Free=5 Reserved=0 Remote=no

$ scontrol show licenses
LicenseName=val_glide
    Total=5 Used=0 Free=5 Reserved=0 Remote=no
  1. Test cgroup memory enforcement

Verify that ConstrainRAMSpace=yes is set in cgroup.conf. Submit a job that intentionally tries to allocate more memory than requested and confirm that Slurm kills it with an OOM exit code.

Hint / Solution
# Verify cgroup settings on a compute node
ssh cpu001 cat /etc/slurm/cgroup.conf | grep ConstrainRAMSpace
# Should show: ConstrainRAMSpace=yes

# Submit a job requesting 100 MB but trying to allocate 500 MB
sbatch --mem=100M --wrap="python3 -c \"x = bytearray(500 * 1024 * 1024); import time; time.sleep(60)\""

# Wait for it to be killed, then check
sacct -j <jobid> --format=JobID,State,ExitCode,MaxRSS
# State should be OUT_OF_MEMORY
# ExitCode shows 0:125 for a cgroup OOM kill (see the validated output below);
# a program inside the script killed by SIGKILL shows 137:0 instead
Expected output: Validated 2026-10-19 on slurm-training-val (Slurm 25.11.8, ParallelCluster 3.16.1).
$ cat /opt/slurm/etc/cgroup.conf 2>/dev/null || echo '(cgroup.conf not at /opt/slurm/etc/)'
###
# Slurm cgroup support configuration file
###
ConstrainCores=yes
#
# WARNING!!! The slurm_parallelcluster_cgroup.conf file included below can be updated by the pcluster process.
# Please do not edit it.
include slurm_parallelcluster_cgroup.conf

$ sbatch --mem=100M --time=00:05:00 --output=/dev/null        --job-name=val_oom --wrap='/shared/python/3.12/bin/python3 -c "x = bytearray(500 * 1024 * 1024); import time; time.sleep(60)"'
Submitted batch job 42

$ sacct -j 42 --format=JobID,JobName%-12,State%-20,ExitCode,MaxRSS
JobID        JobName      State                ExitCode     MaxRSS 
------------ ------------ -------------------- -------- ---------- 
42          val_oom      OUT_OF_MEMORY           0:125            
42.batch    batch        OUT_OF_MEMORY           0:125    102196K 
  1. Verify node features and test constraint matching

Check which features are configured on the GPU nodes. Submit a job that requires the a100 feature using --constraint and verify it lands on an A100 node.

Hint / Solution
# Check features on GPU nodes
scontrol show nodes gpu[01-08] | grep -E "NodeName|AvailableFeatures|ActiveFeatures"

# Submit a job requiring a100 feature
sbatch --constraint=a100 --gres=gpu:1 --wrap="nvidia-smi; hostname" -o feature_test.out

# After completion, check which node it ran on
sacct -j <jobid> --format=JobID,NodeList,State
# Should show one of the A100 GPU nodes
Expected output: Validated 2026-10-19 on slurm-training-val (Slurm 25.11.8, ParallelCluster 3.16.1).
$ scontrol show nodes | grep -E '(NodeName|AvailableFeatures)' | head -20
NodeName=batch-dy-compute-1 Arch=x86_64 CoresPerSocket=1 
   AvailableFeatures=dynamic,t3.2xlarge,compute
NodeName=batch-dy-compute-2 CoresPerSocket=1 
   AvailableFeatures=dynamic,t3.2xlarge,compute
NodeName=batch-dy-compute-3 CoresPerSocket=1 
   AvailableFeatures=dynamic,t3.2xlarge,compute
NodeName=batch-dy-compute-4 CoresPerSocket=1 
   AvailableFeatures=dynamic,t3.2xlarge,compute
NodeName=debug-dy-small-1 CoresPerSocket=1 
   AvailableFeatures=dynamic,t3.medium,small
NodeName=debug-dy-small-2 CoresPerSocket=1 
   AvailableFeatures=dynamic,t3.medium,small
NodeName=gpu-dy-t4-1 CoresPerSocket=1 
   AvailableFeatures=dynamic,g4dn.xlarge,t4,gpu
NodeName=highmem-dy-large-1 CoresPerSocket=1 
   AvailableFeatures=dynamic,t3.2xlarge,large
  1. Classify a cluster as enforcing or non-enforcing

Read the five signature settings from the running config and decide whether memory and CPU limits are enforced.

Hint / Solution
scontrol show config | grep -E 'SelectTypeParameters|DefMemPerNode|TaskPlugin|ProctrackType|JobAcctGatherType'
# Not enforcing:  CR_CPU, DefMemPerNode=UNLIMITED, task/affinity only,
#                 proctrack/linuxproc, jobacct_gather/none
# Enforcing:      CR_*_Memory, task/cgroup,task/affinity, proctrack/cgroup,
#                 jobacct_gather/cgroup (and ConstrainRAMSpace=yes in cgroup.conf)
# Mixed output is still "not enforcing" for whichever layer is missing.
Expected output: Validated 2026-10-19 on slurm-training-val (Slurm 25.11.8, ParallelCluster 3.16.1).
$ scontrol show config | grep -E 'SelectTypeParameters|DefMemPerNode|TaskPlugin|ProctrackType|JobAcctGatherType'
DefMemPerNode           = UNLIMITED
JobAcctGatherType       = jobacct_gather/cgroup
ProctrackType           = proctrack/cgroup
SelectTypeParameters    = CR_CPU_MEMORY
TaskPlugin              = task/cgroup,task/affinity
TaskPluginParam         = (null type)
  1. Compare nproc with the pinned CPU set

Inside a 2-CPU step, compare the CPU count the OS reports with the width of Cpus_allowed_list. Explain which one os.cpu_count() follows.

Hint / Solution
srun -c 2 bash -c 'nproc; grep Cpus_allowed_list /proc/self/status; echo "SLURM_CPUS_ON_NODE=$SLURM_CPUS_ON_NODE"'
# nproc honours the affinity mask (glibc sched_getaffinity), so it should equal the
# width of Cpus_allowed_list (e.g. 0-1 -> 2). Python os.cpu_count() and R
# parallel::detectCores() ignore the mask and report the whole node.
srun -c 2 python3 -c 'import os; print(os.cpu_count(), len(os.sched_getaffinity(0)))'
Expected output: Validated 2026-10-19 on slurm-training-val (Slurm 25.11.8, ParallelCluster 3.16.1).
$ srun -J val_rm_e7 --chdir=/tmp -c 2 bash -c 'nproc; grep Cpus_allowed_list /proc/self/status; echo SLURM_CPUS_ON_NODE=$SLURM_CPUS_ON_NODE'
2
Cpus_allowed_list:   0,42
SLURM_CPUS_ON_NODE=2

$ srun -J val_rm_e7 --chdir=/tmp -c 2 python3 -c 'import os; print(os.cpu_count(), len(os.sched_getaffinity(0)))'
8 2
  1. Make ParallelCluster track gres/gpu

Enable accounting on a stock ParallelCluster, add gres/gpu to AccountingStorageTRES, apply the change, and show that a GPU job's AllocTRES now contains the GPU.

Hint / Solution
# cluster YAML (HeadNode and external MySQL/RDS details omitted)
#   Scheduling:
#     SlurmSettings:
#       Database:
#         Uri: <rds-endpoint>:3306
#         UserName: <db-user>
#         PasswordSecretArn: <secret-arn>
#       CustomSlurmSettings:
#         - AccountingStorageTRES: gres/gpu
pcluster update-cluster --cluster-name <name> --cluster-configuration cluster.yaml

# After the update completes, on the head node:
sacctmgr show tres                      # gres/gpu must be listed
sbatch --gres=gpu:1 --wrap="nvidia-smi -L; sleep 5"
sacct -j <jobid> --format=JobID,ReqTRES%40,AllocTRES%60   # AllocTRES contains gres/gpu=1
# Tracking starts at the change; earlier jobs stay without gres/gpu.
# gres/gpumem and gres/gpuutil stay empty on cloud nodes (no NVML data source).
Expected output: Validated 2026-10-19 on slurm-training-val (Slurm 25.11.8, ParallelCluster 3.16.1).
$ sacctmgr show tres
    Type            Name     ID 
-------- --------------- ------ 
     cpu                      1 
     mem                      2 
  energy                      3 
    node                      4 
 billing                      5 
      fs            disk      6 
    vmem                      7 
   pages                      8 
    gres             gpu   1001 
    gres          gpumem   1002 
    gres         gpuutil   1003 

References