Skip to content

fix(strategy): validate dtype in the public subspace_matmul() API (Fixes #222)#223

Merged
zeokin merged 1 commit into
zeokin:mainfrom
joaovictor91123:fix/strategy-subspace-matmul-dtype-validation
Jul 14, 2026
Merged

fix(strategy): validate dtype in the public subspace_matmul() API (Fixes #222)#223
zeokin merged 1 commit into
zeokin:mainfrom
joaovictor91123:fix/strategy-subspace-matmul-dtype-validation

Conversation

@joaovictor91123

Copy link
Copy Markdown
Contributor

Fixes #222.

PR kind

  • fix
  • feat

PR kind: fix

Summary

strategy.subspace_matmul() had the same dtype gap matmul.matmul() had before
#209 — and since the strategy package is deliberately standalone (it shares no
code with matmul/), the fix had to be made separately here:

>>> from strategy import _dtype_name; _dtype_name(np.int32)
'fp32'

_dtype_name silently returned "fp32" for any unrecognized dtype, so
subspace_matmul on integer arrays built a fp32 Config while the operands
went to the GPU at their native dtype and died deep inside torch.matmul. It also
never checked that A and B share a dtype, so subspace_matmul(fp16, fp32)
crashed the same opaque way.

The fix

Resolve/validate the dtype at the top of subspace_matmul(), before the backend
exists
(so the error is clear and GPU-independent): raise ValueError on
A.dtype != B.dtype, and make _dtype_name raise a ValueError listing DTYPES
instead of mislabelling an unsupported dtype as fp32. This completes the
dtype-validation pattern across both public multiply APIs, exactly as #201
completed the clean-CLI-error pattern across all three CLIs. fp16/fp32/fp64
are unchanged.

subspace_matmul(int64, int64)  → ValueError: unsupported dtype int64; the subspace strategy supports ['fp16', 'fp32', 'fp64']
subspace_matmul(fp16, fp32)    → ValueError: A and B must have the same dtype; got float16 vs float32

Validation

  • uv run --extra test python -m pytest tests/ strategy/tests/ eval/tests/ -v
    263 passed, 24 skipped.
  • uv run python -m strategy.smoke1/1 transforms passed.
  • Validation runs before Backend(...), so it raises on a no-GPU machine (the new
    tests are pure CPU). The three reject tests fail on the pre-fix code.

New strategy/tests/test_subspace_matmul_dtype.py: unsupported dtypes
(int32/int64/uint8/complex128) and A/B mismatch raise ValueError with a
clear message; the three supported dtypes map correctly; and the pre-existing
square-shape guard still fires first.

No protected paths touched (strategy/, strategy/tests/ are Open per
CONTRIBUTING.md). This changes strategy/__init__.py, a file the matmul #209
fix never touched — the two packages are intentionally separate.

GPU Result (required for feat PRs only)

N/A — fix PR (input validation in the public API). No scorecard required; the
result of a valid multiply is unchanged.

Checklist

  • CPU-safe validation passed (strategy.smoke, plus pytest tests/ strategy/tests/ eval/tests/).
  • My commits do not include Co-authored-by footers for coding agents such as Cursor, Codex, Claude, Copilot, or similar tools.
  • If this is a feat PR, I ran the scorer on unseen couples. (N/A — fix PR.)
  • If this is a feat PR, accuracy and latency come from the same run. (N/A — fix PR.)
  • If this is a feat PR, this is an improvement. (N/A — fix PR; input validation.)
  • Correctness gates pass (CPU-safe suite above; GPU-gated files skip without a device).
  • If this is a feat PR, I named the device and dtype. (N/A — fix PR.)

strategy.subspace_matmul() had the same dtype gap matmul.matmul() had before
zeokin#209 (the strategy package is deliberately standalone and shares no code with
matmul): _dtype_name silently returned "fp32" for any unrecognized dtype, so
subspace_matmul on integer arrays built a fp32 Config while the operands went to
the GPU at their native dtype and died deep inside torch.matmul. It also never
checked that A and B share a dtype, so subspace_matmul(fp16, fp32) crashed the
same opaque way.

Resolve/validate the dtype at the top of subspace_matmul(), before the backend
exists (so the error is clear and GPU-independent): raise ValueError on
A.dtype != B.dtype, and make _dtype_name raise a ValueError listing DTYPES
instead of mislabelling an unsupported dtype as fp32. Completes the
dtype-validation pattern across both public multiply APIs, as zeokin#201 did for the
three CLIs. fp16/fp32/fp64 are unchanged.

Add CPU-only tests (validation runs before the GPU backend): unsupported dtypes
(int32/int64/uint8/complex128) and A/B mismatch raise ValueError with a clear
message, the three supported dtypes map correctly, and the pre-existing
square-shape guard still fires first. Three fail on the pre-fix code.

Fixes zeokin#222
@github-actions github-actions Bot added area:strategy Smart strategies / transforms (strategy/) area:tests Correctness gates and test suites (tests/) status:needs-review Awaiting maintainer review type:bug Something is incorrect or broken status:ready-non-gpu Fix/docs PR cleared non-GPU triage; maintainer review only labels Jul 13, 2026

@zeokin zeokin left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Validates A/B dtype match and rejects unsupported dtypes before the GPU; narrow, tested.

@zeokin zeokin merged commit e30c055 into zeokin:main Jul 14, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:strategy Smart strategies / transforms (strategy/) area:tests Correctness gates and test suites (tests/) status:needs-review Awaiting maintainer review status:ready-non-gpu Fix/docs PR cleared non-GPU triage; maintainer review only type:bug Something is incorrect or broken

Projects

None yet

2 participants