Skip to content

Add a launcher that runs FastSurfer in its container image - #948

Merged
m-reuter merged 18 commits into
Deep-MI:devfrom
m-reuter:launcher
Oct 13, 2026
Merged

m-reuter merged 18 commits into
Deep-MI:devfrom
m-reuter:launcher

Conversation

@m-reuter

@m-reuter m-reuter commented Oct 12, 2026 •

Copy link
Copy Markdown
Member

Running FastSurfer in a container means writing a long command: mounting every input, output and license path, running as the user, passing the GPU, and choosing the right image for the GPU and driver. Most support questions come from this, not from installing.

tools/fastsurfer_container.py takes the flags of run_fastsurfer.sh (or, with --brun, of brun_fastsurfer.sh) and does the container part. It uses only the Python standard library and runs with Python 3.8 or newer, so it works with a cluster's system Python and is meant to be downloaded as a single file.

Image

  • Without --image, it runs the FastSurfer release image installed on the machine that runs there (also of an earlier release or CUDA version). Several such images stop it with a list, newest first; none downloads the newest release. A newer release is announced, and --update switches to it.
  • --image takes a release tag (cu132-v2.6.0, the way to pin a study, since the image type matters as well as the version), a version (2.6.0), any Docker image, or an Apptainer .sif file.
  • One request to Docker Hub per run (5 s timeout) decides about versions. A release image whose digest differs from Docker Hub, e.g. a local build tagged like a release, stops it; --update replaces it.
  • For an older version, it says how many releases it is behind, and recommends the newest release on the CPU over an old image used only because newer images do not support the GPU.
  • .sif files are built atomically (no half-built image for parallel jobs), with the source digest recorded next to them. They are built from the local Docker when the release is already pulled there, and otherwise from Docker Hub without stored logins, so an expired Docker Hub token cannot make the download of the public image fail.
  • --update_launcher replaces the launcher with the one on the stable branch; it also stops when its table of CUDA images is out of date.

GPU

  • Picks cu132, cu126 or cpu from nvidia-smi (capability, driver, memory). Without a named GPU, it uses the newest supported GPU with enough memory and shows only that one to the container (with --brun, all GPUs the image supports); the same applies to a release image named with --image, among the GPUs its type supports. Named GPUs (--device, --viewagg_device; lists and ranges with --brun) are used as named.
  • CUDA_DEVICE_ORDER=PCI_BUS_ID makes GPU numbers match nvidia-smi.

Container

  • Apptainer, Singularity (3.7 or newer) or Docker, whichever has the image or is installed.
  • Every path flag becomes absolute and its directory is mounted at the same path, also through symbolic links (e.g. DataLad datasets) and for the paths in a brun_fastsurfer.sh subjects list.
  • Runs as the calling user and passes the FreeSurfer license from $FS_LICENSE. With Docker, it uses --init, so Ctrl-C and cancelled cluster jobs stop FastSurfer, and on Linux shares the host's time zone, so logs show local time.
  • On a Mac with Apple silicon, points to the macOS package instead, unless Docker is requested explicitly.

Tested on a Linux server (Turing GPU, Docker and Apptainer, six older FastSurfer images installed): GPU selection with and without --image, the choice among installed images, the digest check against the pulled images, Ctrl-C with both runtimes, building the .sif from the local Docker, and from Docker Hub with a wrong stored login. Unit tests in test/utils/test_fastsurfer_container.py cover the image and GPU decisions, path handling and generated commands with real inputs; test/lint/test_launcher_builds.py keeps the launcher's CUDA table in sync with gpu_support.py and pyproject.toml.

The container page (doc/overview/CONTAINERS.md) gets a section on the launcher. Its download link points to the stable branch, so it works from the next release on.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Device parsing and several runtime/image combinations can currently crash or produce unusable commands.

6 open findings
What changed in this PR

Adds a standalone launcher that configures and runs FastSurfer container images across supported runtimes.

Changes:

  • Adds runtime, image, GPU, path, license, and platform handling.
  • Adds launcher and CUDA-configuration tests.
  • Documents launcher installation and usage.
File Description
tools/​fastsurfer_container.py Implements the container launcher.
test/​utils/​test_fastsurfer_container.py Tests image selection, paths, and commands.
test/​lint/​test_launcher_builds.py Guards duplicated CUDA configuration.
doc/​overview/​CONTAINERS.md Documents launcher usage.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread tools/fastsurfer_container.py Outdated
Comment thread tools/fastsurfer_container.py Outdated
Comment thread tools/fastsurfer_container.py Outdated
Comment thread tools/fastsurfer_container.py Outdated
Comment thread tools/fastsurfer_container.py Outdated
Comment thread tools/fastsurfer_container.py

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread tools/fastsurfer_container.py
Comment thread tools/fastsurfer_container.py Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

GPU request planning has unresolved cases that can select an incompatible image or omit required GPU access.

0 open findings

2 resolved since last review
Previously missed (1)

In code that hasn't changed since last review

Medium severity Reject multi-device forms for regular FastSurfer runs

tools/​fastsurfer_container.py:339

Lists and ranges are accepted only by brun_fastsurfer.sh; regular run_fastsurfer.sh supports one cuda:<n> device and its GPU check immediately converts the entire suffix to int. Consequently, without --brun, values such as --device cuda:0,1 or cuda:0-3 pass this launcher validation and then fail inside FastSurfer. Reject multi-device forms for regular runs, or limit this advertised support to --brun.

This issue also appears in the following locations of the same file:

  • line 370
  • line 372
  • line 700

🧠 Review effort: Balanced

@m-reuter
m-reuter merged commit 6dcd0e9 into Deep-MI:dev Oct 13, 2026
4 checks passed
@m-reuter
m-reuter deleted the launcher branch October 13, 2026 13:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants