# Does this lose the benefit of QR decomposition?

**URL:** https://discourse.julialang.org/t/does-this-lose-the-benefit-of-qr-decomposition/58324
**Category:** Performance
**Tags:** linearalgebra, qr
**Created:** [March 31, 2021, 7:37pm UTC](https://discourse.julialang.org/t/does-this-lose-the-benefit-of-qr-decomposition/58324 "2021-03-31T19:37:30Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![Ross\_Boylan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ross_boylan/32/9210_2.png) [@Ross\_Boylan](https://discourse.julialang.org/u/Ross_Boylan)
#### Post date: [March 31, 2021, 7:37pm UTC](https://discourse.julialang.org/t/does-this-lose-the-benefit-of-qr-decomposition/58324/1 "2021-03-31T19:37:30Z")

</div>

My understanding is that one can do fast multiplies by the Q matrix of the QR decomposition because it is represented as a sequence of Householder reflections. I want to compute

```julia
    deltai = 3:size(T, 1)
    δ = Q[:, deltai] * fp[deltai]

```

(not self-containted; `fp` is one dimensional) where `Q` is the result of a call to `qr().Q`. I’m concerned that, since I subset `Q` explicitly this loses the benefit.

Should I be concerned? If so, what can I do about it?

I don’t think `(Q*fp)[deltai]` yields the same result.

I guess I could force the first 2 values of `fp` to 0; then I think `Q*fp` does give the result I want.

---

<div class="post-metadata">

### Author: ![simonbyrne](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simonbyrne/32/19_2.png) [@simonbyrne](https://discourse.julialang.org/u/simonbyrne)
#### Post date: [March 31, 2021, 9:32pm UTC](https://discourse.julialang.org/t/does-this-lose-the-benefit-of-qr-decomposition/58324/2 "2021-03-31T21:32:50Z")

</div>

> [@Ross\_Boylan](#):
>
> I guess I could force the first 2 values of `fp` to 0; then I think `Q*fp` does give the result I want.

I think padding the first two entries to be zero would be the most efficient option here: otherwise it has to form `Q`, which requires applying the reflectors of `Q` to an identity matrix:

> <https://github.com/JuliaLang/julia/blob/637f52b8eb836bda45bdb282ff3dd3d347bef439/stdlib/LinearAlgebra/src/qr.jl#L518>

---

<div class="post-metadata">

### Author: ![Ross\_Boylan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ross_boylan/32/9210_2.png) [@Ross\_Boylan](https://discourse.julialang.org/u/Ross_Boylan)
#### Post date: [April 1, 2021, 11:49pm UTC](https://discourse.julialang.org/t/does-this-lose-the-benefit-of-qr-decomposition/58324/3 "2021-04-01T23:49:29Z")

</div>

Thank you. After overcoming the fact that my code became [so optimized it wouldn’t run at all](https://discourse.julialang.org/t/forwarddiff-and-lapack-dont-get-along/58397), I got it to work. The difference was very large, ~8x faster based on the means, considering that is only one part of the calculations. Memory use shows similar improvements.

# Before

```julia-auto
   julia> @benchmark RBSilly.fit(yx, 2)
    BenchmarkTools.Trial:
      memory estimate: 3.17 MiB
      allocs estimate: 602
      --------------
      minimum time: 71.913 μs (0.00% GC)
      median time: 168.027 μs (0.00% GC)
      mean time: 241.267 μs (41.50% GC)
      maximum time: 2.101 ms (89.42% GC)
      --------------
      samples: 10000
      evals/sample: 1

```

# After

```julia-auto
    julia> @benchmark RBSilly.fit(yx, 2)
    BenchmarkTools.Trial:
      memory estimate: 59.86 KiB
      allocs estimate: 190
      --------------
      minimum time: 23.335 μs (0.00% GC)
      median time: 24.966 μs (0.00% GC)
      mean time: 29.430 μs (11.89% GC)
      maximum time: 3.025 ms (94.90% GC)
      --------------
      samples: 10000
      evals/sample: 1

```
