nf-core/configs: dkfz
Deutsches Krebsforschungszentrum (DKFZ) ODCF HPC cluster profile
nf-core/configs: DKFZ configuration
To use, run the pipeline with -profile dkfz. This will download and launch the dkfz.config, pre-configured for the Deutsches Krebsforschungszentrum (DKFZ) / ODCF LSF cluster in Heidelberg, Germany.
This configuration is tested with Nextflow 24.10.2 (available on the cluster as a module).
The profile only configures the cluster itself (LSF executor, dynamic queue selection, scratch, resource limits and the /omics bind-mount). Pick a container engine on the command line, e.g. -profile dkfz,apptainer or -profile dkfz,conda.
:warning: Use Apptainer/Singularity (or Conda), not Docker. On the ODCF cluster Docker is only available through LSF’s
docker-genericapplication profile. Nextflow’sdockerexecutor runsdocker rundirectly on the node, which this setup does not allow, so-profile dkfz,dockerwill not work. Use-profile dkfz,apptainerinstead.
Before you use this profile
-
Load Nextflow via the environment module system on a submission host. Check the pipeline’s README for the required Nextflow version:
module load Nextflow/<version> -
Submit from a submission host (
bsub01.lsf.dkfz.de/bsub02.lsf.dkfz.de). Do not run heavy work on the login/worker nodes. Wrap the Nextflow driver itself in absubjob (see below). -
The shared
/omicsfilesystem is bind-mounted into every container automatically. If your inputs or references live elsewhere, pointNXF_APPTAINER_CACHEDIR/NXF_SINGULARITY_CACHEDIRat a path under/omicsso images are cached on shared storage:export NXF_APPTAINER_CACHEDIR=/omics/groups/<your-group>/.../apptainer_cache
Queues
The profile selects an appropriate LSF queue automatically based on the task’s resource requirements. See the DKFZ Cluster Wiki for current queue and resource policies.
Resource limits, retries and containers
- Every task is capped to what the cluster can provide via
process.resourceLimits. Requests above these are capped automatically. - Unlabelled processes default to a safe minimal allocation; see the DKFZ Cluster Wiki for the current default.
- The shared
/omicsfilesystem is bound into every container viacontainerOptions, with--nvadded for accelerator tasks. If one of your modules sets its owncontainerOptions, re-add--bind /omicsthere.
Enable GPU support
This profile turns any task that requests a GPU through Nextflow’s standard accelerator directive into a correct DKFZ GPU submission. It selects the GPU queue, builds the LSF -gpu num=<n>:j_exclusive=yes[:gmem=<n>G] request, and adds --nv so the GPU is visible inside the container.
How a task acquires an accelerator request depends on the pipeline:
-
nf-core pipelines mark GPU-capable processes with the
process_gpulabel and only switch the accelerator on when the run includes thegpuprofile. So addgputo your profile list:nextflow run <pipeline> -profile dkfz,gpu,apptainer --input ... --outdir ... -
Custom / non-nf-core pipelines just declare
acceleratoron the GPU process:process MY_GPU_TASK { accelerator 1 container 'docker://nvcr.io/...' script: "my_gpu_tool ..." }nextflow run main.nf -profile dkfz,apptainer --outdir ...
Tasks without an accelerator request are unaffected and run on the normal CPU queues.
Choosing the GPU queue
The --dkfz_gpu_queue parameter selects which GPU queue all GPU jobs are submitted to (default gpu). For the current list of GPU queues, hardware, wall-time limits and access requirements, see the DKFZ Cluster Wiki.
Number of GPUs and GPU memory per process
The profile builds the LSF request as -gpu num=<n>:j_exclusive=yes[:gmem=<n>G] (DKFZ requires j_exclusive=yes and rejects mode=exclusive_process). Two things are tunable per process:
- Number of GPUs — the
acceleratordirective (default 1). - GPU memory (optional) — set
ext.gpu_memoryto a Nextflow memory value to pin the job to GPUs with at least that much VRAM. Whenext.gpu_memoryis unset,gmemis omitted and LSF assigns any free GPU.
For approximate ext.gpu_memory values to target specific GPU models and which queue each requires, see the DKFZ Cluster Wiki.
Set these directly on the process, or per process name from config (e.g. nf-core’s conf/modules.config):
process {
// 2 GPUs, any free GPU (no gmem constraint)
withName: 'FOO:BAR:ALIGN_GPU' {
accelerator = 2
}
// 1 big-memory GPU, needs gpu-pro - see DKFZ Cluster Wiki for current hardware tiers (https://wiki.odcf.dkfz.de/pub/cluster/lsf/gpu/start#gpu_queue_nodes)
withName: 'FOO:BAR:FOLD' {
accelerator = 1
ext.gpu_memory = 40.GB
}
}
:warning: A high
ext.gpu_memoryvalue may only be satisfiable on certain GPU queues - request too much on the wrong queue and the job hangs inPENDindefinitely. Check the DKFZ Cluster Wiki for current hardware/queue mapping and CPU/RAM-per-GPU usage limits before settingext.gpu_memory.
Running Nextflow on the cluster
Run the Nextflow driver inside an LSF job rather than on a submission host directly. Make a script and submit it with bsub < my_script.sh:
#!/bin/bash
#BSUB -J nf_pipeline
#BSUB -o nf_pipeline.%J.log
#BSUB -q long
#BSUB -n 2
#BSUB -R "rusage[mem=8G]"
#BSUB -W 10:00
# Load the Nextflow version required by the pipeline you are running:
# module load Nextflow/<version>
# Cache images on shared storage so worker nodes can reach them:
# export NXF_APPTAINER_CACHEDIR=/omics/groups/<your-group>/.../apptainer_cache
nextflow run <pipeline> \
-profile dkfz,apptainer \
--input samplesheet.csv \
--outdir results
Add gpu to -profile (e.g. -profile dkfz,gpu,apptainer) to send process_gpu tasks to a GPU queue.
Config file
// Institutional profile for the DKFZ / ODCF LSF cluster.
params { config_profile_description = 'Deutsches Krebsforschungszentrum (DKFZ) ODCF HPC cluster profile' config_profile_contact = 'Abid Abrar (abid.abrar@dkfz-heidelberg.de), Kübra Narcı (kuebra.narci@dkfz-heidelberg.de), Vithusan Suppiyar (vithusan.suppiyar@dkfz-heidelberg.de)' config_profile_name = 'DKFZ Cluster' config_profile_url = 'https://www.dkfz.de'
max_cpus = 64 max_memory = '3800.GB' max_time = '720.h'
// GPU queue for GPU jobs (options: gpu (default), gpu-lowprio, gpu-pro) dkfz_gpu_queue = 'gpu'}
apptainer { enabled = true autoMounts = true}
// Ignore the custom dkfz_gpu_queue param in nf-schema validationvalidation.ignoreParams = ['dkfz_gpu_queue']
process { executor = 'lsf' scratch = '$CLUSTER_SCRATCHDIR'
// Retry transient failures: no exit status, signals 130–145 (137 = OOM/preempt), 104/255 (I/O drops) errorStrategy = { (task.exitStatus == null || task.exitStatus == Integer.MAX_VALUE || task.exitStatus in ((130..145) + [104, 255])) ? 'retry' : 'finish' } maxRetries = 3 cache = 'lenient'
// Cap every task to the cluster ceiling: 64 cores, 3800 GB RAM, 720 h (30 day) wall time resourceLimits = [ cpus : 64, memory: 3800.GB, time : 720.h, ]
// Low defaults for unlabelled processes cpus = 1 memory = 6.GB time = 10.min
// GPU tasks go to a GPU queue; everything else to a CPU queue by time/memory. queue = { if (task.accelerator) { return params.dkfz_gpu_queue } else if (task.memory && task.memory > 250.GB) { return 'highmem' } else if (!task.time || task.time <= 10.min) { return 'short' } else if (task.time <= 1.h) { return 'medium' } else if (task.time <= 10.h) { return 'long' } else { return 'verylong' } }
// GPU request, depends on `accelerator`: a nf-core `process_gpu` task without // `-profile gpu` has no accelerator, so it stays on CPU. // j_exclusive=yes is mandatory // optional `ext.gpu_memory` pins to GPUs with at least that much VRAM. clusterOptions = { def opts = '-L /bin/bash' if (task.accelerator) { opts += " -gpu num=${task.accelerator.request}:j_exclusive=yes" if (task.ext.gpu_memory) { opts += ":gmem=${task.ext.gpu_memory.toGiga()}G" } } return opts }
// Bind /omics into every container; add --nv for GPU tasks. containerOptions = { task.accelerator ? '--bind /omics --nv' : '--bind /omics' }}
executor { name = 'lsf' perJobMemLimit = true perTaskReserve = false queueSize = 10 submitRateLimit = '1 sec' exitReadTimeout = '30 min'}