# Base.accumulate! seems slow due to keyword argument handling, can it be sped up?

**URL:** https://discourse.julialang.org/t/base-accumulate-seems-slow-due-to-keyword-argument-handling-can-it-be-sped-up/93650
**Category:** Performance
**Created:** [January 27, 2023, 5:10pm UTC](https://discourse.julialang.org/t/base-accumulate-seems-slow-due-to-keyword-argument-handling-can-it-be-sped-up/93650 "2023-01-27T17:10:01Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![taotree](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/taotree/32/31982_2.png) [@taotree](https://discourse.julialang.org/u/taotree)
#### Post date: [January 27, 2023, 5:10pm UTC](https://discourse.julialang.org/t/base-accumulate-seems-slow-due-to-keyword-argument-handling-can-it-be-sped-up/93650/1 "2023-01-27T17:10:01Z")

</div>

Before I found accumulate, I had written a simple implementation. Then I was informed about accumulate! and tried using that. @btime’ing it showed allocations and that it took nearly twice as long to run as the implementation I wrote. Further investigation indicated that the extra time appeared to be in the argument handling. If I bypassed accumulate! to call Base.\_accumulate!, it would run at the same speed as the one I wrote:

```julia
f1(a, x) = (a[2], a[2]+x);
v1 = rand(100);
buf1 = Vector{NTuple{2,Float64}}(undef, length(v1));
init = (0.0, 0.0);
r1 = @btime accumulate!($f1, $buf1, $v1; init=$init);
> 103.814 ns (3 allocations: 96 bytes)
r2 = @btime Base._accumulate!($f1, $buf1, $v1, nothing, Some($init));
> 57.447 ns (0 allocations: 0 bytes)
r1 == r2
> true

```

[Examining the code](https://github.com/JuliaLang/julia/blob/99225ab1d11925b8e904b0b12f1ee8b0f6946660/base/accumulate.jl#L337), it’s doing some conditionals around the keyword arguments. I understand this is to support nothing as a valid value for init. This seems to be a high performance cost for that generality. I tried various attempts in that single method to speed this up while keeping that, but couldn’t find anything that resolved the performance issue. Requiring the user to pass in Some(nothing) if they needed that to be the init could work, but changing the signature or adding a new one is probably undesirable at this point.

However, I think I found a solution. Would it work to use a special private value to signify nothing so the argument default would work? Something like this:

```julia
struct _DefinitelyNothingThisTime end
function test_accumulate!(op, B, A; dims::Union{Integer, Nothing} = nothing, init = _DefinitelyNothingThisTime)
    Base._accumulate!(op, B, A, dims, init === _DefinitelyNothingThisTime ? nothing : Some(init))
end

```

It seems to work (with init, without init, and for init=nothing) and performs well. Is there any issue with that approach?

---

<div class="post-metadata">

### Author: ![gbaraldi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gbaraldi/32/22101_2.png) [@gbaraldi](https://discourse.julialang.org/u/gbaraldi)
#### Post date: [January 27, 2023, 6:19pm UTC](https://discourse.julialang.org/t/base-accumulate-seems-slow-due-to-keyword-argument-handling-can-it-be-sped-up/93650/2 "2023-01-27T18:19:20Z")

</div>

Could you open an issue for this?

---

<div class="post-metadata">

### Author: ![uniment](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/uniment/32/24532_2.png) [@uniment](https://discourse.julialang.org/u/uniment)
#### Post date: [January 28, 2023, 12:48am UTC](https://discourse.julialang.org/t/base-accumulate-seems-slow-due-to-keyword-argument-handling-can-it-be-sped-up/93650/3 "2023-01-28T00:48:47Z")

</div>

Nice fix, definitely better than the existing code. The allocations and inefficiencies in the current implementation appear to be (1) due to `accumulate!` not specializing, and (2) the call to `isempty`.

Not to be _too_ picky, but it’s a bit more idiomatic to use a singleton _instance_, rather than the type itself. To illustrate:

```julia
julia> nothing ≡ Nothing()
true

```

Note that your approach is used for `mapfoldl` (reduce.jl line 170), which uses the singleton object `Base._InitialValue()` (reduce.jl line 67).

---

<div class="post-metadata">

### Author: ![taotree](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/taotree/32/31982_2.png) [@taotree](https://discourse.julialang.org/u/taotree)
#### Post date: [February 3, 2023, 2:11pm UTC](https://discourse.julialang.org/t/base-accumulate-seems-slow-due-to-keyword-argument-handling-can-it-be-sped-up/93650/4 "2023-02-03T14:11:22Z")

</div>

Thank you for the replies. I have created [Performance improvement for accumulate! · Issue #48439 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/48439) for this.
