Skip to content

Preserve BFloat16 in ProjectTo - #719

Merged
devmotion merged 4 commits into
mainfrom
cl/bfloat16-projectto
Oct 20, 2026
Merged

devmotion merged 4 commits into
mainfrom
cl/bfloat16-projectto

Conversation

@CarloLucibello

@CarloLucibello CarloLucibello commented Oct 20, 2026 •

Copy link
Copy Markdown
Member

Closes #718.

ProjectTo(::BFloat16) fell back to ProjectTo{Real}. A Float32 cotangent reaching a bf16 array was therefore not converted back, and the whole backward pass of a bf16 model was promoted to Float32. This defines ProjectTo(::Core.BFloat16) = ProjectTo{Core.BFloat16}() on Julia ≥ 1.11, matching the existing Float16/Float32/Float64 methods. The existing AbstractFloat → convert methods do the rest.

BFloat16s.jl uses Core.BFloat16 as its BFloat16 where LLVM supports bf16 (x86_64 with LLVM ≥ 15, aarch64 with LLVM ≥ 19). On other platforms, and on Julia 1.10, it defines its own type, which is left to a ChainRulesCore extension in BFloat16s.jl.

Bumps the version to 1.26.4.

🤖 Generated with Claude Code

@codecov

codecov Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.41%. Comparing base (a1dbf0e) to head (6739074).

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #719   +/-   ##
=======================================
  Coverage   93.40%   93.41%           
=======================================
  Files          15       15           
  Lines        1001     1002    +1     
=======================================
+ Hits          935      936    +1     
  Misses         66       66           

☔ 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.

Comment thread ext/ChainRulesCoreBFloat16sExt.jl Outdated
Comment thread Project.toml Outdated
Comment thread Project.toml Outdated
CarloLucibello and others added 2 commits October 20, 2026 10:16
Add a BFloat16s extension defining ProjectTo(::BFloat16) = ProjectTo{BFloat16}(),
like Float16/Float32/Float64, instead of falling back to ProjectTo{Real}.

Closes #718.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@devmotion devmotion left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM. I guess the only remaining question is: Should this be part of ChainRulesCore or BFloat16s? I'm leaning a bit towards BFloat16s since the general policy of ChainRules and ChainRulesCore has been to require packages to define their derivative rules in extensions and only define rules for stdlibs in ChainRules and ChainRulesCore itself.

@CarloLucibello

Copy link
Copy Markdown
Member Author

I also would lean toward having it on BFloat16s, but I fear it would take months there to get merged... Since it fixes a pretty serious issue, i would prefer to have it merged soon.

@devmotion

Copy link
Copy Markdown
Member

but I fear it would take months there to get merged

Why is that? Tim seems to be one of the maintainers. Maybe open a PR in BFloat16s and let's see if you receive a timely response.

@CarloLucibello

Copy link
Copy Markdown
Member Author

Also, bfloat16 support has moved to base on recent Julia versions, so it actually makes more sense to have the extension here

@devmotion

devmotion commented Oct 20, 2026 •

Copy link
Copy Markdown
Member

Support for Base types and functions should be in ChainRulesCore/ChainRules, but an extension for a non-stdlib probably shouldn't.

If I also understood your comment above correctly, Base does only support bfloat16 on some architecture whereas BFloat16s supports all (standard) architectures?

@CarloLucibello

Copy link
Copy Markdown
Member Author

Maybe the best way forward is to have a no-extension PR here and another PR in BFloat16.jl. Claude agrees:

Core.BFloat16 is defined on every architecture since Julia 1.11, but Base gives it no conversions or arithmetic. BFloat16s.jl uses it as its BFloat16 only where LLVM supports bf16 (x86_64 with LLVM ≥ 15, aarch64 with LLVM ≥ 19). Everywhere else, and on all of Julia 1.10, it defines its own BFloat16s.BFloat16.

So I'll split it:

  • here: ProjectTo(::Core.BFloat16) = ProjectTo{Core.BFloat16}() in src, under @static if isdefined(Core, :BFloat16), with no extension or weakdep. This covers x86_64 on Julia ≥ 1.11.
  • in BFloat16s.jl: a ChainRulesCore extension for its own type, defined only when BFloat16 !== Core.BFloat16 so that the two packages never define the same method.

BFloat16s.jl's own BFloat16, used where LLVM lacks bf16 support, is left
to an extension in BFloat16s.jl.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comment thread test/Project.toml Outdated
Comment thread test/Project.toml Outdated
Comment thread test/projection.jl Outdated
Comment thread test/projection.jl Outdated
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@devmotion
devmotion merged commit 44772e9 into main Oct 20, 2026
27 checks passed
@devmotion
devmotion deleted the cl/bfloat16-projectto branch October 20, 2026 12:50
@CarloLucibello

Copy link
Copy Markdown
Member Author

thanks David!

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.

ProjectTo(::BFloat16) is ProjectTo{Real}, so BFloat16 cotangents get promoted to Float32

2 participants