Skip to content

Conversation

judober
Copy link
Contributor

@judober judober commented Jan 13, 2019

PR to add the /-Operator for LU-Types refering to this.
I'm fairly new to julia, so it is likely that there is a better way to calculate pivot (line 146/147 of lu.jl).
The PR also includes a testset for the division with LU.
Feel free to suggest improvements.

Fixes #582

@coveralls
Copy link

coveralls commented Jan 13, 2019

Coverage Status

Coverage increased (+0.03%) to 81.614% when pulling c1325ba on judober:LuForRdiv into 1c53f4a on JuliaArrays:master.

src/lu.jl Outdated
\(F::LU, B::AbstractMatrix) = F.U \ (F.L \ B[F.p,:])

function /(B::AbstractMatrix, F::LU)
pivot = similar(F.p)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will this allocation be elided?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By elided you mean omitted? (Sorry, I'm not familiar with the technical terms).
If that's the case, than I think no. It is needed for the next step to be accessed at the indices F.p.
The problem is that the pivot indices cannot be used the same was as in \. I wrote down the whole operation with matrices and the difference is that in case of / the P-matrix is multiplied from the right, while it is normally from the left (as is case of \). So the p-indices (F.p) have to be ordered differently. There might exist a smarter way to do this but I don't know it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, in this context, "elided" means "optimized away".

This operation with the indices looks like Base.invperm(). I'd suggest adding the following utility function:

Base.@propagate_inbounds function Base.invperm(p::StaticVector)
     ip = similar(p)
     ip[p] = 1:length(p)
     similar_type(p)(ip)
end

Checking with @code_native indicates that the MVector which is created here by similar is optimized away :-D And so is the range object, which is very cool and kind of surprising.

Then inside your function, use pivot = @inbounds invperm(F.p) (we can use @inbounds because we know that F.p is a permutation).

Copy link
Contributor Author

@judober judober Jan 22, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I was not aware of this function.
I added your suggestion to util. The performance increases a bit by using @inbounds.
However, in Base invperm also checks if p is a valid pivot vector (by checking if every value is unique). This might be worth implementing though it probably adds computation time.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we just have to assume the data in the LU is correct (that the pivot vector is a valid permutation).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@c42f I'm not sure when to "trust" the optimizer - my understanding is that once the function is inlined into a more complex one, these optimizations may or may not occur (I'd love to know what is guaranteed...).

src/util.jl Outdated
@inline drop_sdims(a::StaticArrayLike) = TrivialView(a)
@inline drop_sdims(a) = a

Base.@propagate_inbounds function Base.invperm(p::StaticVector)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you need to make this just an internal-facing static arrays utility function (not an overload of Base.invperm because I feel that one should check the permutation is valid).

@judober
Copy link
Contributor Author

judober commented May 5, 2019

I found the time to remove the overloading of Base.invperm. Not sure why the checks are failing though. Probably due to incompatibility to code changes from the last months?

@c42f
Copy link
Member

c42f commented May 6, 2019

The test errors look like they might be real. At least, they're related to the LU tests and fail on all julia versions.

@c42f
Copy link
Member

c42f commented Jul 31, 2019

I'd love to merge this but we need to understand / fix the test failures. Do you have any time to investigate?

@c42f c42f added linear-algebra performance runtime performance labels Aug 1, 2019
@judober
Copy link
Contributor Author

judober commented Sep 29, 2019

I found some time and I think I know the problem and possibly a solution:

  • The error occurs only when the size of A is 2x2 or 3x3. This is related to the special case treatment in solve.jl for these kinds of matrices. This treatment is only applied, when lu() is not used und has slightly different results.
  • When I change the test from int to float, it passes. I think that this is due to the different value range of rand() for int and float.

So for now I changed the type of the test to float. Maybe a different kind of test would be advisable?

@judober
Copy link
Contributor Author

judober commented Oct 24, 2019

Just curious: is there something left to do?
I think the difference in the values of int vs float is a problem for \approx. It does only check for the absolute error which increases for big values, while the (in this case more relevant) relative error stays as small as expected.
So I think this ready.

@c42f
Copy link
Member

c42f commented Oct 25, 2019

Thanks for bumping this, I must have missed your previous update.

It does only check for the absolute error which increases for big values, while the (in this case more relevant) relative error stays as small as expected.

Actually isapprox uses relative tolerance rtol=√eps and absolute tolerance atol=0 by default. It could be something to do with the distribution of random integer matrices being poorly behaved in some way though I find this a bit surprising.

It would be nice to understand why that was failing but it's hard to imagine it's related to this PR.

@c42f c42f merged commit 973a709 into JuliaArrays:master Oct 25, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Performance of Matrix Division

4 participants