Skip to content

Remove Metal warning, align default tol, and improve Metal gather - #91

Merged
eloualiche merged 7 commits into
FixedEffects:mainfrom
matthieugomez:metal-allowscalar-warning
Nov 3, 2026
Merged

eloualiche merged 7 commits into
FixedEffects:mainfrom
matthieugomez:metal-allowscalar-warning

Conversation

@matthieugomez

@matthieugomez matthieugomez commented Nov 2, 2026 •

Copy link
Copy Markdown
Member

Remove Metal.allowscalar(false) in ext/MetalExt.jl, which creates a warning and does nothing useful. Metal arrays now use default shared storage, where scalar indexing is always allowed. Remove CUDA.allowscalar(false) in ext/CUDAExt.jl too: as a top-level call it runs during precompilation rather than when the package loads, and a package should not set this global for its users anyway. Also make the prebuilt solver methods use the documented default tol (1e-8 for Float64, 1e-6 for Float32, instead of sqrt(eps(T)), which is 3.5e-4 for Float32). Float32 callers that do not pass tol now run more iterations; FixedEffectModels passes it explicitly and is unaffected. Finally, run every benchmark at tol = 1e-6 so that CPU and Metal timings are comparable, and update the timings, measured on Metal 1.12.0.

Finally, choose the Metal gather from group sizes and row order. The old rule looked only at the number of levels, so it could use atomic adds where threads keep hitting the same coefficient. Atomics are now used only when no group exceeds 0.005% of rows and rows are not clustered by group. Otherwise each group gets a threadgroup, with a width set by the largest group relative to the number of levels. CUDA is unchanged; the constants were calibrated on an M1 Max.

Also remove the per-block forward scatter kernel: the forward mul!, which runs once per solve, now calls the fused kernel that bidiag_forward! uses.

Metal, 6 columns, tol = 1e-6 Before After CPU, 10 threads
Simple (N=10M) 0.34s 0.34s 0.60s
Hard (N=800k) 9.2s 2.5s 3.1s
Interacted (N=800k) 22s 3.9s 5.4s
3-way (N=800k) 12s 3.5s 4.1s
Large (N=10M) 2.8s 1.3s 2.7s
Metal, ms per iteration Before After
Skewed groups (N=1M, 100k levels, plus year) 257 3.7
Sorted panel (N=1M, plus year) 15.6 3.8
Sorted panel, skewed firm (N=10M) 34 17
Simple (N=1k) 1.76 1.74

Small problems are still slower on Metal than on the CPU because each iteration has a fixed cost of about 1.7 ms.

@codecov

codecov Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
⚠️ Please upload report for BASE (main@c1ebcf9). Learn more about missing BASE report.

Additional details and impacted files
@@           Coverage Diff           @@
##             main      #91   +/-   ##
=======================================
  Coverage        ?   74.85%           
=======================================
  Files           ?       12           
  Lines           ?     1233           
  Branches        ?        0           
=======================================
  Hits            ?      923           
  Misses          ?      310           
  Partials        ?        0           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@matthieugomez matthieugomez changed the title Remove Metal.allowscalar call that warns at precompile Remove Metal.allowscalar call and use the documented default tol Nov 2, 2026
@matthieugomez matthieugomez changed the title Remove Metal.allowscalar call and use the documented default tol Remove Metal warning, align default tol, and improve Metal gather Nov 2, 2026
@eloualiche
eloualiche merged commit 0bc88c8 into FixedEffects:main Nov 3, 2026
6 checks passed
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