Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

kaiser performance: use Bessels.jl? #506

Closed
anowacki opened this issue Aug 22, 2023 · 4 comments · Fixed by #538
Closed

kaiser performance: use Bessels.jl? #506

anowacki opened this issue Aug 22, 2023 · 4 comments · Fixed by #538

Comments

@anowacki
Copy link
Contributor

When resampling signals with a very low or high arbitrary rate, the call to kaiser is what dominates. Profiling this, it seems like most of the time here is taken up by the call to SpecialFunctions.besseli. This allocates but also the computation is just fundamentally slow for these arguments.

Using DSP v0.7.8:

julia> @btime resample(x, rate) setup=(x=rand(1000); rate=1/50) seconds=3;
  37.353 ms (58055 allocations: 4.02 MiB)

However, I see that Bessels.jl aims to provide Bessel functions in pure Julia which are faster than SpecialFunctions.jl's, and as accurate.

Using the following version of DSP.Windows.kaiser which uses Bessels.besseli we get an 8-fold improvement in runtime for this particular signal length and resampling rate:

julia> function DSP.kaiser(n::Integer, α::Real; padding::Integer=0, zerophase::Bool=false)
           pf = 1.0/Bessels.besseli(0,pi*α)
           DSP.Windows.makewindow(n, padding, zerophase) do x
               pf*Bessels.besseli(0, pi*α*(sqrt(1 - (2x)^2)))
           end
       end

julia> @btime resample(x, rate) setup=(x=rand(1000); rate=1/50) seconds=3;
  4.444 ms (37 allocations: 3.14 MiB)

If you are happy to add an extra dependency on Bessels.jl, and you feel it is stable enough to rely on in the future, then I would be happy to open a PR so long as this passes tests.

@ViralBShah
Copy link
Contributor

@oscardssmith Is Bessels.jl stable enough and in good shape for DSP.jl to rely upon?

@oscardssmith
Copy link

IMO Bessels.jl at this point is pretty stable. Nice to see a 10x improvement. You could probably get a little more by using Bessels.besseli0 instead.

@ViralBShah
Copy link
Contributor

@martinholters Would it be ok to add a dependency on Bessels.jl?

@martinholters
Copy link
Member

Fine with me.

anowacki added a commit to anowacki/DSP.jl that referenced this issue Feb 18, 2024
Replace calls to `SpecialFunctions.besseli(0, ...)` with calls to
`Bessels.besseli0(...)`, adding Bessels.jl
(https://github.com/JuliaMath/Bessels.jl) as a dependency.

When resampling signals with a very low or high arbitrary rate, the call
to `Windows.kaiser` is what dominates.  Profiling this, most of the time
is taken up by the call to `SpecialFunctions.besseli`. This allocates,
but also the computation is just fundamentally slow for these arguments.

Replacing these calls with those to `Bessels.besseli0` gives a factor
of 17 speedup when resampling a 1000-point random trace to a rate of
0.02.

Closes JuliaDSP#506.
anowacki added a commit to anowacki/DSP.jl that referenced this issue Feb 19, 2024
Replace calls to `SpecialFunctions.besseli(0, ...)` with calls to
`Bessels.besseli0(...)`, adding Bessels.jl
(https://github.com/JuliaMath/Bessels.jl) as a dependency.

When resampling signals with a very low or high arbitrary rate, the call
to `Windows.kaiser` is what dominates.  Profiling this, most of the time
is taken up by the call to `SpecialFunctions.besseli`. This allocates,
but also the computation is just fundamentally slow for these arguments.

Replacing these calls with those to `Bessels.besseli0` gives a factor
of 17 speedup when resampling a 1000-point random trace to a rate of
0.02.

Closes JuliaDSP#506.
anowacki added a commit to anowacki/DSP.jl that referenced this issue Feb 19, 2024
Replace calls to `SpecialFunctions.besseli(0, ...)` with calls to
`Bessels.besseli0(...)`, adding Bessels.jl
(https://github.com/JuliaMath/Bessels.jl) as a dependency.

When resampling signals with a very low or high arbitrary rate, the call
to `Windows.kaiser` is what dominates.  Profiling this, most of the time
is taken up by the call to `SpecialFunctions.besseli`. This allocates,
but also the computation is just fundamentally slow for these arguments.

Replacing these calls with those to `Bessels.besseli0` gives a factor
of 17 speedup when resampling a 1000-point random trace to a rate of
0.02.

Closes JuliaDSP#506.
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 a pull request may close this issue.

4 participants