Skip to content

fix(cli): make the gpumask test use a positive mask instead of upstream's -1 - #1368

Draft
lusoris wants to merge 3 commits into
masterfrom
fix/cli-gpumask-negative-contract
Draft

fix(cli): make the gpumask test use a positive mask instead of upstream's -1#1368
lusoris wants to merge 3 commits into
masterfrom
fix/cli-gpumask-negative-contract

Conversation

@lusoris

@lusoris lusoris commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Summary

Follows #1363 (now merged). Rebased onto master; supersedes the auto-closed #1365.

test_vmaf_cuda_gpumask failed on every host that actually has an NVIDIA GPU. The script — inherited verbatim from upstream — documents --gpumask -1 as "use cpu" and invokes it twice under set -e, but the fork's CLI rejects negative values:

Invalid argument "-1" for option --gpumask; should be a non-negative integer

It looked green in CI only because the script exits 77 (meson SKIP) when nvidia-smi -L finds no device — which is every hosted runner. I hit it while running the full suite for #1363.

This is not a fork regression. Upstream's -1 works by accident: POSIX strtoul silently converts "-1" to ULONG_MAX without setting errno, and this fork's parse_unsigned deliberately rejects a leading '-' before calling strtoul, with an inline comment saying exactly that. The hardening is right; the script is the stale side.

A positive mask is the documented spelling — libvmaf.h says any non-zero value disables the GPU feature-extractor selection ... falls back to the CPU implementation. Measured on an RTX 4090 over the Netflix 576x324 pair, 4 frames:

invocation pooled VMAF
--gpumask 0 88.80022305138327
--gpumask 1 88.8002154453433
--no_cuda --no_sycl 88.8002154453433

--gpumask 1 is byte-identical to an explicit CPU run — exactly what the original -1 was reaching for.

The --gpumask row in docs/usage/cli.md said "Mask out specific GPU ops", describing a per-op bitmask the option has never been. Corrected here.

Type

  • fix — bug fix
  • docs — documentation
  • test — test-only

Checklist

  • Commits follow Conventional Commits.
  • make format && make lint is green locally (pre-commit run --files clean, including shfmt and shellcheck on the changed script).
  • Unit tests pass: meson test -C build — the target this PR fixes, test_vmaf_cuda_gpumask, now exits 0 on the GPU workstation where it previously failed.
  • If I touched any SIMD/GPU code path, I ran /cross-backend-diff — no SIMD or GPU code changed; this is a shell script plus docs.
  • If I touched a feature extractor with SIMD/GPU twins — no extractor touched.
  • If I added a new .c / .h — no new source files.
  • If this is a breaking change — not a breaking change. --gpumask -1 has already been rejected by this fork for as long as parse_unsigned has been hardened; this PR documents that rather than changing it.
  • If this PR adds an ADR, the row lives in docs/adr/_index_fragments/concat-adr-index.sh --check is in sync.

Bug-status hygiene (ADR-0165)

Netflix golden-data gate (ADR-0024)

  • I did not modify any assertAlmostEqual(...) score in the Netflix golden Python tests.
  • If I believe a golden value must change — none does; no scoring code is touched.

Deep-dive deliverables (ADR-0108)

  • Research digest — no digest needed: the investigation is two git show upstream/master reads and one three-row measurement, all recorded in ADR-1209's Context section; a separate digest would just restate it.
  • Decision matrix## Alternatives considered in ADR-1209, including why special-casing --gpumask to accept negatives and why relaxing parse_unsigned globally were both rejected.
  • AGENTS.md invariant note — added to core/tools/AGENTS.md.
  • Reproducer / smoke-test command — below.
  • CHANGELOG fragmentchangelog.d/fixed/cli-gpumask-negative-contract.md.
  • Rebase notedocs/rebase-notes.md, "ADR-1209 — --gpumask and upstream's negative-value accident", so a future sync does not revert the two lines back to -1.

Reproducer

Needs a host with an NVIDIA GPU — without one the script skips and reports green, which is the whole point.

meson setup build -Denable_cuda=true
ninja -C build
meson test -C build test_vmaf_cuda_gpumask

On master this fails at the second invocation with Invalid argument "-1" for option --gpumask; on this branch it exits 0.

Known follow-ups

  • The usage string still calls the argument $bitmask. Left alone deliberately: changing help text is a user-visible string change with its own compatibility surface, and the reference table in docs/usage/cli.md now carries the accurate contract.

🤖 Generated with Claude Code

lusoris pushed a commit that referenced this pull request Sep 6, 2026
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
lusoris pushed a commit that referenced this pull request Sep 7, 2026
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@lusoris
lusoris force-pushed the fix/cli-gpumask-negative-contract branch from 782ac3b to 4e46c80 Compare September 7, 2026 06:54
lusoris pushed a commit that referenced this pull request Sep 7, 2026
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@lusoris
lusoris force-pushed the fix/cli-gpumask-negative-contract branch from 4e46c80 to c70595c Compare September 7, 2026 09:14
lusoris pushed a commit that referenced this pull request Sep 7, 2026
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@lusoris
lusoris force-pushed the fix/cli-gpumask-negative-contract branch 2 times, most recently from 8124b97 to 823c6fb Compare September 7, 2026 10:18
lusoris pushed a commit that referenced this pull request Sep 7, 2026
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
lusoris pushed a commit that referenced this pull request Sep 7, 2026
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@lusoris
lusoris force-pushed the fix/cli-gpumask-negative-contract branch from 823c6fb to 7e0d16c Compare September 7, 2026 12:16
Lusoris and others added 3 commits September 7, 2026 15:16
…am's -1

`test_vmaf_cuda_gpumask` failed on every host that actually has an NVIDIA GPU.
The script — inherited verbatim from upstream — documents `--gpumask -1` as
"use cpu" and invokes it twice under `set -e`, but the fork's CLI rejects
negative values. It looked green in CI only because the script exits 77 (meson
SKIP) when `nvidia-smi -L` finds no device, which is every hosted runner.

Not a fork regression. Upstream's `-1` works by accident: POSIX strtoul
silently converts "-1" to ULONG_MAX without setting errno, and this fork's
`parse_unsigned` deliberately rejects a leading '-' before calling strtoul,
with an inline comment saying exactly that. The stale side was the script.

`gpumask` is documented in libvmaf.h as "any non-zero value disables the GPU
feature-extractor selection ... falls back to the CPU implementation", so a
positive mask is the correct spelling. Measured on an RTX 4090 over the
Netflix 576x324 pair (4 frames): --gpumask 0 = 88.80022305138327,
--gpumask 1 = 88.8002154453433, --no_cuda --no_sycl = 88.8002154453433 — a
non-zero mask is byte-identical to an explicit CPU run, exactly the intent of
the original -1.

Also corrects the `--gpumask` row in docs/usage/cli.md, which described a
per-op bitmask the option has never been, and records the divergence in
docs/rebase-notes.md so a future sync does not revert it.

Verified: the script now exits 0 on the GPU workstation where it failed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@lusoris
lusoris force-pushed the fix/cli-gpumask-negative-contract branch from 7e0d16c to 0488269 Compare September 7, 2026 13:16
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.

1 participant