# Yeppp-package

**URL:** <https://discourse.julialang.org/t/yeppp-package/90866>\
**Category:** New to Julia\
**Tags:** package, linearalgebra\
**Created:** [November 26, 2022, 9:33pm UTC](https://discourse.julialang.org/t/yeppp-package/90866 "2022-11-26T21:33:07Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![ofk123](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ofk123/32/44670_2.png) [@ofk123](https://discourse.julialang.org/u/ofk123)\
**Post date:** [November 26, 2022, 9:33pm UTC](https://discourse.julialang.org/t/yeppp-package/90866/1 "2022-11-26T21:33:07Z")

</div>

Hi, I have seen the package Yeppp been mentioned here ([Fast logsumexp](https://discourse.julialang.org/t/fast-logsumexp/22827)). This might be an ignorant question but when adding Yeppp it wont install, and I get some errors telling me to Pkg.build instead, which also does not work, and I wonder why.  
Is it no longer preferred to use the package? Or maybe the performance is now included in LinearAlgebra?

New to Julia, using 1.8.3, and just want to check if using Yeppp makes a difference in improving parts of a numpy/scipy-based-computation , specifically the step `sum(log.(eigvals(Symmetric(A))))` where A is Matrix of Float64, different sizes every computation ranging from 2x2 to 400x400

Best,

---

<div class="post-metadata">

**Author:** ![gustaphe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gustaphe/32/18174_2.png) [@gustaphe](https://discourse.julialang.org/u/gustaphe)\
**Post date:** [November 26, 2022, 9:45pm UTC](https://discourse.julialang.org/t/yeppp-package/90866/2 "2022-11-26T21:45:34Z")

</div>

The repo for that package has been archived and has had no commits for four years, which is quite long in Julia time. I don’t know if it’s been superceded by something or just stopped being developed.

By the way, a simple improvement is to use `sum(log, x)` rather than `sum(log.(x))`. It should make a tiny difference compared to all those `eig`s, but a difference nonetheless.

---

<div class="post-metadata">

**Author:** ![Elrod](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elrod/32/22461_2.png) [@Elrod](https://discourse.julialang.org/u/Elrod)\
**Post date:** [November 27, 2022, 2:50am UTC](https://discourse.julialang.org/t/yeppp-package/90866/4 "2022-11-27T02:50:26Z")

</div>

I’d recommend LoopVectorization.jl for vectorizing functions like `log`.  
But I’d be surprised if even base `log` takes much time compared to `eigvals`.

---

<div class="post-metadata">

**Author:** ![ofk123](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ofk123/32/44670_2.png) [@ofk123](https://discourse.julialang.org/u/ofk123)\
**Post date:** [January 5, 2023, 4:32pm UTC](https://discourse.julialang.org/t/yeppp-package/90866/5 "2023-01-05T16:32:44Z")

</div>

@gustaphe @Elrod Thank you for the suggestions.

I see `sum(log, ex)` is better, at least it allocates less.  
Can I ask a follow-up question regarding `eigvals`? I wonder if there is an obvious code that could improve performance that I am missing. Would LoopVectorization.jl be something to look into for this operation too?

---

<div class="post-metadata">

**Author:** ![Elrod](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elrod/32/22461_2.png) [@Elrod](https://discourse.julialang.org/u/Elrod)\
**Post date:** [January 5, 2023, 5:25pm UTC](https://discourse.julialang.org/t/yeppp-package/90866/6 "2023-01-05T17:25:38Z")

</div>

> [@ofk123](#):
>
> I see `sum(log, ex)` is better, at least it allocates less.

If you want better performance of the log sum:

```julia
julia> using LoopVectorization

julia> x = rand(511);

julia> @btime vmapreduce(log, +, $x)
  277.449 ns (0 allocations: 0 bytes)
-487.3246594217604

julia> @btime sum(log, $x)
  2.490 μs (0 allocations: 0 bytes)
-487.3246594217602

```

Unfortunately, it won’t help eigvals just yet.

---

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [January 5, 2023, 6:58pm UTC](https://discourse.julialang.org/t/yeppp-package/90866/7 "2023-01-05T18:58:25Z")

</div>

Wow, that’s almost 10x!

---

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [January 5, 2023, 7:09pm UTC](https://discourse.julialang.org/t/yeppp-package/90866/8 "2023-01-05T19:09:50Z")

</div>

If you are dealing with very large sparse matrices A you might be interested in O(N) spectral methods, like the Kernel Polynomial Method and relatives. See e.g. [Rev. Mod. Phys. 78, 275 (2006) - The kernel polynomial method](https://journals.aps.org/rmp/abstract/10.1103/RevModPhys.78.275)

The basic idea is to express the function of `A` that you want to trace over (in this case log) as an expansion in Chebyshev polynomials `P_n(x)`, which end up giving you the sum you want in terms of `psi'*P_n(A)*psi`, where psi is a random vector. These methods are crazy efficient for very large sparse matrices.

Probably for 400x400 dense matrices this doesn’t make much sense though.

---

<div class="post-metadata">

**Author:** ![ofk123](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ofk123/32/44670_2.png) [@ofk123](https://discourse.julialang.org/u/ofk123)\
**Post date:** [January 5, 2023, 7:53pm UTC](https://discourse.julialang.org/t/yeppp-package/90866/9 "2023-01-05T19:53:33Z")

</div>

@pablosanjose@Elrod Thank you, I just tried `vmapreduce()` and it helps in this calculation, it seems awesome. As you mentioned earlier, it makes a tiny difference compared to the `eigvals!(Hermitian(A))`. Do you know if it is possible to improve this eigvals-computation?  
I forgot to mention the matrices are dense, otherwise I would try out the O(N) spectral method you mentioned above. Thanks alot for the suggestion.

---

<div class="post-metadata">

**Author:** ![Elrod](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elrod/32/22461_2.png) [@Elrod](https://discourse.julialang.org/u/Elrod)\
**Post date:** [January 5, 2023, 11:20pm UTC](https://discourse.julialang.org/t/yeppp-package/90866/10 "2023-01-05T23:20:15Z")

</div>

If you have an Intel or even an AMD CPU, `using MKL` should help.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [January 6, 2023, 12:03am UTC](https://discourse.julialang.org/t/yeppp-package/90866/11 "2023-01-06T00:03:05Z")

</div>

> [@ofk123](#):
>
> `sum(log.(eigvals(Symmetric(A))))`

Note that this is the **same thing as the log-determinant** `logdet(A)`, which is much faster than computing eigenvalues. Since it seems like you know that your matrix `A` is positive definite (as otherwise `log(λ)` will throw an error), you can often do even better still by using `logdet(cholesky(Symmetric(A)))`:

```julia
julia> using LinearAlgebra, BenchmarkTools

julia> BLAS.set_num_threads(1) # just a single core for benchmarking

julia> A = randn(1000,1000); A = A'A; # random SPD matrix;

julia> @btime sum(log, eigvals(Symmetric($A)))
  68.893 ms (11 allocations: 7.99 MiB)
5902.6715053545195

julia> @btime logdet($A)
  18.700 ms (3 allocations: 7.64 MiB)
5902.671505354289

julia> @btime logdet(cholesky(Symmetric($A)))
  11.704 ms (2 allocations: 7.63 MiB)
5902.671505354335

```

The log-determinant is a useful function with lots of beautiful properties!
