# Determinant of CUDA matrix?

**URL:** https://discourse.julialang.org/t/determinant-of-cuda-matrix/77245
**Category:** GPU
**Tags:** cuda, linearalgebra
**Created:** [March 1, 2022, 2:54pm UTC](https://discourse.julialang.org/t/determinant-of-cuda-matrix/77245 "2022-03-01T14:54:03Z")
**Posts on this page:** 9
**Page:** 1

<div class="post-metadata">

### Author: ![HenriDeh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrideh/32/8316_2.png) [@HenriDeh](https://discourse.julialang.org/u/HenriDeh)
#### Post date: [March 1, 2022, 2:54pm UTC](https://discourse.julialang.org/t/determinant-of-cuda-matrix/77245/1 "2022-03-01T14:54:03Z")

</div>

Hello,

I have so far been able to use CUDA without having to dig into the actual package api (besides `cu(m)`) just thanks to multiple dispatch. Today I need to compute the determinant of a matrix and I would like my code to work both on the GPU and the CPU. However, the `det` function from LinearAlgebra is not specialized for `CuArray` and throws a CPU address error. I guess this is because `det` calls a function from a `C` library (BLAS ?).

I have been searching for a bit now and I just can’t find a CUDA implementation of det. So, I’d like to know if there exists a linear algebra package for CUDA that I don’t know of, or if I’ll have to learn how to efficiently compute a determinant to implement it myself and learn the internals of CUDA.jl.  
I’m not sure I have the skills to do that.

MWE:

```julia
using CUDA
m = rand(10,10) |> cu
det(m)

```

---

<div class="post-metadata">

### Author: ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)
#### Post date: [March 1, 2022, 3:27pm UTC](https://discourse.julialang.org/t/determinant-of-cuda-matrix/77245/2 "2022-03-01T15:27:25Z")

</div>

You can try computing the LU factorization and then taking the product of the diagonal elements:

```julia
julia> M = rand(10,10);

julia> Mgpu = cu(M);

julia> det(M) # cpu
-0.10243723110926993

julia> prod(diag(LinearAlgebra.LAPACK.getrf!(M)[1])) # cpu
-0.10243723110926993

julia> prod(diag(CUSOLVER.getrf!(Mgpu)[1])) # gpu
-0.10243723f0

```

(Might be necessary to think more carefully about the sign though!)

---

<div class="post-metadata">

### Author: ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)
#### Post date: [March 1, 2022, 3:32pm UTC](https://discourse.julialang.org/t/determinant-of-cuda-matrix/77245/3 "2022-03-01T15:32:25Z")

</div>

Also, there is an open issue about determinant calculation on GPU here: [https://github.com/JuliaGPU/CUDA.jl/issues/110](https://github.com/JuliaGPU/CUDA.jl/issues/110)

Perhaps worth figuring out the details and making a PR.

---

<div class="post-metadata">

### Author: ![HenriDeh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrideh/32/8316_2.png) [@HenriDeh](https://discourse.julialang.org/u/HenriDeh)
#### Post date: [March 1, 2022, 4:34pm UTC](https://discourse.julialang.org/t/determinant-of-cuda-matrix/77245/4 "2022-03-01T16:34:42Z")

</div>

> [@carstenbauer](#):
>
> `prod(diag(CUSOLVER.getrf!(Mgpu)[1]))`  
> (Might be necessary to think more carefully about the sign though!)

Thanks, that’s what I was hoping for!  
Seems to work as far as I can tell. What sign issue are you referring to?  
I could open a PR in CUDA.jl, if this implementation suffice, so I won’t have to commit type piracy 😬

---

<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: [March 1, 2022, 5:50pm UTC](https://discourse.julialang.org/t/determinant-of-cuda-matrix/77245/5 "2022-03-01T17:50:03Z")

</div>

> [@HenriDeh](#):
>
> Today I need to compute the determinant of a matrix

Out of curiosity, for what application do you need the determinant?

(Note, by the way, that for a large matrix the determinant can easily overflow the maximum floating-point value; you might consider using `logdet` instead.)

---

<div class="post-metadata">

### Author: ![HenriDeh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrideh/32/8316_2.png) [@HenriDeh](https://discourse.julialang.org/u/HenriDeh)
#### Post date: [March 1, 2022, 6:36pm UTC](https://discourse.julialang.org/t/determinant-of-cuda-matrix/77245/6 "2022-03-01T18:36:19Z")

</div>

I’m trying to implement a multivariate gaussian neural network for a deep reinforcement learning algorithm. It will output a mean vector and a vector containing the elements of a lower triangular Cholesky decomposition. I then reconstruct the covariance matrix from the latter vector.

During training I need to take the gradient of the `logpdf` of the approximated MvNormal, which requires the `logdet` indeed. The sign issue is not a problem for me since the covariance matrix is PSD so I can simply take the `abs` of the implementation proposed by @carstenbauer.

Since it’s for a deep learning application, I need the `logpdf` function to be differentiable and preferably gpu compatible. It’s unfortunately not the case with `Distributions.jl` so I have to implement it from scratch. I’m making progress but now my next issue is that `CUSOLVER.getrf!` has no adjoint for Zygote to differentiate - that’s a problem for another post.

---

<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: [March 1, 2022, 7:34pm UTC](https://discourse.julialang.org/t/determinant-of-cuda-matrix/77245/7 "2022-03-01T19:34:08Z")

</div>

> [@HenriDeh](#):
>
> I’m making progress but now my next issue is that `CUSOLVER.getrf!` has no adjoint for Zygote to differentiate - that’s a problem for another post.

You can easily differentiate the determinant (or log determinant) directly. See [these slides](https://rawcdn.githack.com/mitmath/matrixcalc/c97512521a9ff63802454ee258f1759c45f7d8b6/determinant_and_inverse.html) from our [matrix calculus course](https://github.com/mitmath/matrixcalc).

---

<div class="post-metadata">

### Author: ![rejuvyesh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rejuvyesh/32/91_2.png) [@rejuvyesh](https://discourse.julialang.org/u/rejuvyesh)
#### Post date: [March 1, 2022, 7:42pm UTC](https://discourse.julialang.org/t/determinant-of-cuda-matrix/77245/8 "2022-03-01T19:42:57Z")

</div>

Should probably also checkout [TuringLang/DistributionsAD.jl: Automatic differentiation of Distributions using Tracker, Zygote, ForwardDiff and ReverseDiff (github.com)](https://github.com/TuringLang/DistributionsAD.jl)

---

<div class="post-metadata">

### Author: ![HenriDeh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrideh/32/8316_2.png) [@HenriDeh](https://discourse.julialang.org/u/HenriDeh)
#### Post date: [March 1, 2022, 8:38pm UTC](https://discourse.julialang.org/t/determinant-of-cuda-matrix/77245/9 "2022-03-01T20:38:36Z")

</div>

Oh, glad I didn’t go all the way through the trouble before knowing about this, thanks!

@stevengj Thank you for the resources, I sure could use a more advanced Linear Algebra / Matrix Calculus course some time soon.
