From b55d6c1d91536f480b604c40dd8affe3d44307d8 Mon Sep 17 00:00:00 2001 From: Dawn Date: Tue, 18 Aug 2026 11:07:12 +0200 Subject: [PATCH] Split careless into CPU module and careless-gpu using cuda/12.8.1 module careless installs plain careless (CPU). careless-gpu also installs plain careless but declares cuda/12.8.1 as build_requires/runtime_deps (jfjoch_viewer pattern) instead of pip-bundling CUDA via the [cuda] extra. Both builds honor UV_CACHE_DIR to share one download cache. Co-Authored-By: Claude Fable 5 --- careless-gpu/README.md | 28 ++++++++++++++++++++++++++++ careless-gpu/build | 26 ++++++++++++++++++++++++++ careless-gpu/files/config.yaml | 13 +++++++++++++ careless-gpu/modulefile | 16 ++++++++++++++++ careless/README.md | 11 ++++++++--- careless/build | 16 +++++++++------- careless/modulefile | 5 ++--- 7 files changed, 102 insertions(+), 13 deletions(-) create mode 100644 careless-gpu/README.md create mode 100755 careless-gpu/build create mode 100644 careless-gpu/files/config.yaml create mode 100644 careless-gpu/modulefile diff --git a/careless-gpu/README.md b/careless-gpu/README.md new file mode 100644 index 0000000..fab39aa --- /dev/null +++ b/careless-gpu/README.md @@ -0,0 +1,28 @@ +# careless-gpu + +GPU build of careless (see `../careless/` for the CPU module and the full +background). Scaling and merging of X-ray diffraction data with approximate +Bayesian inference (variational merging), built on TensorFlow. + +- Upstream: https://github.com/rs-station/careless +- License: MIT + +## How it differs from the careless module + +- CUDA is not pip-installed (no `[cuda]` extra, saves several GB): the + cluster `cuda/12.8.1` module provides it instead, declared as + `build_requires`/`runtime_deps` (same pattern as `jfjoch_viewer`). + `runtime_deps` matters because TensorFlow dlopens the CUDA libraries + when careless runs, so cuda must auto-load with this module. +- If careless reports missing cuDNN at runtime, the cuda module does not + ship it; the fallback is installing `careless[cuda]` in `build` instead. + +The venv layout, uv usage, and cache handling are identical to `careless`. +To share one download cache between both builds, run each with +`UV_CACHE_DIR= modbuild build ` — a cache outside +PREFIX is kept, an in-PREFIX cache is removed after a successful install. + +## Adding a new version + +Add the version under `versions:` in `files/config.yaml`, then on a Ra +login node: `modbuild build ` (modbuild/2.1.2). diff --git a/careless-gpu/build b/careless-gpu/build new file mode 100755 index 0000000..49cb4e9 --- /dev/null +++ b/careless-gpu/build @@ -0,0 +1,26 @@ +#!/usr/bin/env modbuild + +pbuild::prep() { + : +} + +pbuild::configure() { + # same uv pattern as the careless (CPU) module; see that build for the whys + UV="${UV:-$HOME/.local/bin/uv}" + export UV_CACHE_DIR="${UV_CACHE_DIR:-$PREFIX/.uv-cache}" + export UV_PYTHON_INSTALL_DIR="$PREFIX/python" + "$UV" venv --python 3.12 "$PREFIX/venv" +} + +pbuild::compile() { + : +} + +pbuild::install() { + UV="${UV:-$HOME/.local/bin/uv}" + export UV_CACHE_DIR="${UV_CACHE_DIR:-$PREFIX/.uv-cache}" + # no [cuda] extra: CUDA comes from the cuda/12.8.1 module + # (build_requires/runtime_deps in files/config.yaml), not from pip wheels + "$UV" pip install --python "$PREFIX/venv/bin/python" "careless==${V_PKG}" + [[ "$UV_CACHE_DIR" == "$PREFIX"* ]] && rm -rf "$UV_CACHE_DIR" || : +} diff --git a/careless-gpu/files/config.yaml b/careless-gpu/files/config.yaml new file mode 100644 index 0000000..1a7f199 --- /dev/null +++ b/careless-gpu/files/config.yaml @@ -0,0 +1,13 @@ +--- +format: 1 +careless-gpu: + defaults: + group: MX + overlay: base + relstage: unstable + versions: + 0.5.4: + config: + relstage: unstable + build_requires: ["cuda/12.8.1"] + runtime_deps: ["cuda/12.8.1"] diff --git a/careless-gpu/modulefile b/careless-gpu/modulefile new file mode 100644 index 0000000..486cb39 --- /dev/null +++ b/careless-gpu/modulefile @@ -0,0 +1,16 @@ +#%Module1.0 + +module-whatis "careless (GPU) - merging crystallography data with variational inference" +module-url "https://github.com/rs-station/careless" +module-license "MIT" +module-maintainer "MX Data " + +module-help " +careless: scaling and merging of X-ray diffraction data using +approximate Bayesian inference (TensorFlow). GPU build: CUDA is +provided by the cuda/12.8.1 module, auto-loaded as a runtime dep. +Use on nodes with an NVIDIA GPU; for CPU nodes load careless instead. +" + +setenv CARELESS_ENV $PREFIX/venv +prepend-path PATH $PREFIX/venv/bin diff --git a/careless/README.md b/careless/README.md index b2df471..757adc9 100644 --- a/careless/README.md +++ b/careless/README.md @@ -11,9 +11,14 @@ inference (variational merging), built on TensorFlow. Upstream recommends a fresh conda env, but repo.anaconda.com is not reachable from Ra, so the build uses uv instead: it fetches a standalone Python 3.12 into `$PREFIX/python` (upstream supports >=3.9,<3.13), creates -`$PREFIX/venv`, and runs `uv pip install careless[cuda]==` into -it. The `[cuda]` extra pulls the NVIDIA libraries as pip wheels, so the -same install works on GPU and CPU-only Ra nodes. +`$PREFIX/venv`, and runs `uv pip install careless==` into it. +This is the CPU build; the GPU build (with the `[cuda]` extra and the +cluster `cuda/12.8.1` module) is the separate `careless-gpu` module. + +To share one uv download cache between the careless and careless-gpu +builds, run each with `UV_CACHE_DIR= modbuild build ` +— a cache outside PREFIX is kept, an in-PREFIX cache is removed after a +successful install. `uv` must be on PATH on the build host (e.g. `pip install --user uv`). diff --git a/careless/build b/careless/build index 189d84a..d13569d 100755 --- a/careless/build +++ b/careless/build @@ -8,10 +8,11 @@ pbuild::configure() { # repo.anaconda.com is unreachable from Ra (GnuTLS error), so no conda. # uv fetches a standalone CPython instead; keep it inside PREFIX so the # venv's interpreter symlinks don't depend on the builder's home cache. - # modbuild's shell strips ~/.local/bin from PATH; override with UV=/path/to/uv if needed UV="${UV:-$HOME/.local/bin/uv}" - # ~/.cache/uv hits the home disk quota; cache under PREFIX (removed after install) - export UV_CACHE_DIR="$PREFIX/.uv-cache" + # ~/.cache/uv hits the home disk quota; default the cache into PREFIX. + # Overridable so careless and careless-gpu can share one cache: + # UV_CACHE_DIR= modbuild build + export UV_CACHE_DIR="${UV_CACHE_DIR:-$PREFIX/.uv-cache}" export UV_PYTHON_INSTALL_DIR="$PREFIX/python" "$UV" venv --python 3.12 "$PREFIX/venv" } @@ -22,8 +23,9 @@ pbuild::compile() { pbuild::install() { UV="${UV:-$HOME/.local/bin/uv}" - export UV_CACHE_DIR="$PREFIX/.uv-cache" - # [cuda] extra ships the NVIDIA libs via pip wheels; works on CPU-only nodes too - "$UV" pip install --python "$PREFIX/venv/bin/python" "careless[cuda]==${V_PKG}" - rm -rf "$UV_CACHE_DIR" + export UV_CACHE_DIR="${UV_CACHE_DIR:-$PREFIX/.uv-cache}" + # CPU version; the GPU build with the [cuda] extra is the careless-gpu module + "$UV" pip install --python "$PREFIX/venv/bin/python" "careless==${V_PKG}" + # only auto-remove the cache if it lives inside this PREFIX (never a shared one) + [[ "$UV_CACHE_DIR" == "$PREFIX"* ]] && rm -rf "$UV_CACHE_DIR" || : } diff --git a/careless/modulefile b/careless/modulefile index 54ec7d0..852264c 100644 --- a/careless/modulefile +++ b/careless/modulefile @@ -7,9 +7,8 @@ module-maintainer "MX Data " module-help " careless: scaling and merging of X-ray diffraction data using -approximate Bayesian inference (TensorFlow). Installed with the -[cuda] extra, so it uses NVIDIA GPUs when available and falls -back to CPU otherwise. +approximate Bayesian inference (TensorFlow). CPU build; for +NVIDIA GPU nodes load careless-gpu instead. " setenv CARELESS_ENV $PREFIX/venv