Skip to content

Accumulate mean in floating point and divide afterwards - #825

Open
maleadt wants to merge 1 commit into
mainfrom
tb/mean-accumulate
Open

maleadt wants to merge 1 commit into
mainfrom
tb/mean-accumulate

Conversation

@maleadt

@maleadt maleadt commented Oct 19, 2026

Copy link
Copy Markdown
Member

Accumulate mean in floating point and divide afterwards

mean on GPU arrays had three separate bugs, all from not following what Statistics.jl does:

This PR does what Statistics.jl does: convert each mapped element to the floating-point type of
the result, sum, then divide. Statistics.jl takes that type from f(first(A)), which would need
scalar indexing here, so the PR infers it with promote_op instead. The conversion closure takes
f as a static parameter when f is a type, so the closure stays isbits. Empty inputs return
sum(f, A; dims) / 0, as in Statistics.jl.

#453 as written moves the division after the sum, but keeps summing in the input type. That
brings the integer overflow to the dims case too. This PR replaces it.

The two-argument _mean(A, dims) methods are removed. Statistics has only called
_mean(f, A, dims) since 1.9, and the package requires Julia 1.10.

Fixes #819, fixes #611, closes #453.

Summing integers before dividing overflowed for the whole-array mean
(`mean(fill(typemax(Int)÷2, 4))` gave -1.0), while the `dims` variant
pre-scaled every term by 1/n, which loses precision (a mean of ones that
is not one) and captured `f` in a `ComposedFunction`, so a type like
`mean(Float32, A; dims=1)` could not be passed to the kernel.

Follow Statistics.jl instead: convert each mapped element to the result's
floating-point type, sum, then divide. The type is inferred rather than
taken from `first(A)` to avoid scalar indexing, and the conversion closure
keeps `f` as a static parameter when it is a type, so it stays isbits.
The two-argument `_mean` methods are dropped: Statistics has only called
`_mean(f, A, dims)` since 1.9.

Fixes #819, fixes #611, supersedes #453.

This branch has not been deployed

No deployments
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.

mean can overflow on integer inputs Statistics.mean(Float32, arr, dims=1) throws KernelError

1 participant