Skip to content

Fix gemm/gemv fusion under cast_policy=numpy+floatX and make tests policy-aware#2276

Open
maresb wants to merge 5 commits into
pymc-devs:mainfrom
maresb:cast-policy-numpy-floatx
Open

Fix gemm/gemv fusion under cast_policy=numpy+floatX and make tests policy-aware#2276
maresb wants to merge 5 commits into
pymc-devs:mainfrom
maresb:cast-policy-numpy-floatx

Conversation

@maresb

@maresb maresb commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator

I had some expiring Fable credits last night, so I wanted to see if it could fix the cast policy. I honestly can't say I really understand much myself. Feel free to close in case it's garbage. I suspect it didn't run all the tests, we'll see how far the CI gets.


Description

Bugfix + test hardening, so that the test suite now passes if we were to flip cast_policy. No default change here.

The bugfix: under cast_policy="numpy+floatX", _gemm_from_factored_list autocasts the ±1.0 canonicalization scale to float64, fails the upcast check, and silently discards the gemm/gemv candidate — v2 + dot(v1, m) keeps a separate Add instead of folding β into Gemv. Literal scales now adopt the matrix dtype (same idiom as #2245/#2247). No-op under the default custom policy; test_gemv2 is parametrized on cast_policy and fails without the fix.

The rest is tests/docs: policy-aware expectations or pinned literals so every test passes under both policies while still exercising the same behavior; multi-output fusion cases assert the honest per-policy out_dtype (the #2248 dict convention); the autocast_float_as doctest scopes itself to custom, the only policy where it exists.

Verified green under both custom and numpy+floatX: test_math+test_elemwise 355 passed each; gradient/scalar/loop/blas 142; scan benchmarks, pytorch ScalarLoop, and numba rv-param tests all pass both ways.

Related Issue

Type of change

  • Bug fix
  • Maintenance

🤖 Generated with Claude Code

https://claude.ai/code/session_01FWXc59vTjFTLDybuDBypB5

claude added 3 commits July 7, 2026 07:54
Under cast_policy="numpy+floatX" the +/-1.0 scale seeded by
_gemm_canonicalize autocasts to float64, fails the upcast check in
_gemm_from_factored_list, and the whole gemm/gemv candidate is silently
discarded (e.g. v2 + dot(v1, m) keeps a separate Add instead of folding
beta into Gemv). Build literal scales with the matrix dtype instead.
No-op under the default custom policy; test_gemv2 is parametrized on
cast_policy to cover both.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FWXc59vTjFTLDybuDBypB5
Add a _autocast_int_dtype() helper and use it for the TestExpLog/
TestSqrSqrt switch-constant expectations, drop the now-obsolete
("int8", 0, 1) case from the bitwise-or test, and pin the float32
literals in the two sigmoid rewrite tests. Green under both policies.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FWXc59vTjFTLDybuDBypB5
Pin the +2.0 and /2 fusion constants to np.float32 so the fused output
stays float32, and assert the honest per-policy out_dtype for the
multi-output cases 72/74 via the {"custom": ..., "numpy+floatX": ...}
convention.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FWXc59vTjFTLDybuDBypB5
@maresb maresb force-pushed the cast-policy-numpy-floatx branch from 2b8430b to 7d860d8 Compare July 7, 2026 11:20
claude added 2 commits July 7, 2026 12:23
Pin the inner-graph integer literals that would otherwise promote under
numpy+floatX (scan 2*x, scalar loop ** 2 / + 1, gradient x * 2, pytorch
Elemwise-ScalarLoop x * 2 / x1 * 3), and make the scalar test_constant
and numba float-param dtype expectations derive from the active
cast_policy.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FWXc59vTjFTLDybuDBypB5
The hessian benchmark's inner W**2 and cyclical reduction's step_num + 1
promote under numpy+floatX (float32 -> float64 and int32 -> int64), so
scan rejects the state dtype and IfElse rejects the branches; pin both
literals to int8. The autocast_float_as doctest only makes sense under
custom, so scope it with change_flags.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FWXc59vTjFTLDybuDBypB5
@maresb maresb force-pushed the cast-policy-numpy-floatx branch 2 times, most recently from aa7a1e0 to 3f5795d Compare July 7, 2026 13:14
@maresb maresb changed the title Change default cast_policy to numpy+floatX Fix gemm/gemv fusion under cast_policy=numpy+floatX and make tests policy-aware Jul 7, 2026
@maresb

maresb commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator Author

Tests all pass with numpy+floatX as default cast policy. (However, codecov fails with error - 2026-07-07 13:07:48,208 -- Upload queued for processing failed: {"message":"Token required - not valid tokenless upload"}.)

I have popped the numpy+floatX policy change commit to rewrite this as a bugfix so that we can do the flip independently.

@maresb maresb requested a review from ricardoV94 July 7, 2026 13:22
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