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

stricter buffers in SparseMatrixCSC #40523

Merged
merged 5 commits into from
Apr 24, 2021
Merged

Conversation

abraunst
Copy link
Contributor

This is a rebase of #30676, without the addition of a capacity-querying function.

The general idea is about making length(nonzeros(A))==nnz(A) in SparseMatrixCSC, with strict buffer checking on exported functions (a few internal functions still return illegal buffers because the construction is done in several places, in that cases we create an empty matrix and resize the buffers afterwards. They should be clearly marked by comments)

Adresses #30662. See also: #26560, #30435.

Still WIP.

@abraunst
Copy link
Contributor Author

rebasing

@abraunst
Copy link
Contributor Author

Test errors seem unrelated, rebasing.

@abraunst
Copy link
Contributor Author

I'd say the failing check is unrelated. Could we run nanosoldier to look for performance regressions?

@KristofferC
Copy link
Member

@nanosoldier runbenchmarks(ALL, vs=":master")

@nanosoldier
Copy link
Collaborator

Something went wrong when running your job:

NanosoldierError: failed to run benchmarks against comparison commit: failed process: Process(`sudo /run/media/system/data/nanosoldier/cset/bin/cset shield -e su nanosoldier -- -c /run/media/system/data/nanosoldier/workdir/jl_CZM7oH/benchscript.sh`, ProcessExited(1)) [1]

Logs and partial data can be found here
cc @christopher-dG

@abraunst
Copy link
Contributor Author

Is he on strike?

@abraunst
Copy link
Contributor Author

can we uhh... retry?

@KristofferC
Copy link
Member

Looking at https://github.com/JuliaCI/NanosoldierReports/blob/master/benchmark/by_hash/421a07f_vs_d998c7e/logs/d998c7e74c84bb6f78916e71bf4efab936347170_against.out it seems it gets stuck at

loading group "sort"... done (took 0.30277937 seconds)
loading group "sparse"... 

That's a bit suspicious since this code touches the sparse stuff.

@abraunst
Copy link
Contributor Author

Looking at https://github.com/JuliaCI/NanosoldierReports/blob/master/benchmark/by_hash/421a07f_vs_d998c7e/logs/d998c7e74c84bb6f78916e71bf4efab936347170_against.out it seems it gets stuck at

loading group "sort"... done (took 0.30277937 seconds)
loading group "sparse"... 

That's a bit suspicious since this code touches the sparse stuff.

ah ... I'll have a look at that

@KristofferC
Copy link
Member

I tried it locally and it had no problem...

loading group "scalar"... done (took 32.864596103 seconds)
loading group "sort"... done (took 2.51484769 seconds)
loading group "sparse"... done (took 9.814697974 seconds)
loading group "collection"... done (took 13.754587869 seconds)

Let's try again then

@nanosoldier runbenchmarks(ALL, vs=":master")

@nanosoldier
Copy link
Collaborator

Something went wrong when running your job:

NanosoldierError: failed to run benchmarks against comparison commit: failed process: Process(`sudo /run/media/system/data/nanosoldier/cset/bin/cset shield -e su nanosoldier -- -c /run/media/system/data/nanosoldier/workdir/jl_2biAVI/benchscript.sh`, ProcessExited(1)) [1]

Logs and partial data can be found here
cc @christopher-dG

@vtjnash
Copy link
Member

vtjnash commented Apr 22, 2021

Ah, sorry, master is broken right now ("comparison commit") because we need this PR.

@nanosoldier runbenchmarks("sparse" || "problem" || "broadcast" || "linalg", vs="@671bccba27e69b40dabe73409df2b1feba25944c")

@nanosoldier
Copy link
Collaborator

Your benchmark job has completed - possible performance regressions were detected. A full report can be found here. cc @christopher-dG

@abraunst
Copy link
Contributor Author

If I understand correctly the only things that do not seem noise are 2 memory regressions in broadcast ["broadcast", "sparse", ("(1000, 1000)", 1)] and ["broadcast", "sparse", ("(10000000,)", 1)] (possibly fault of the PR) and one of performance ["sparse", "index", ("spmat", "col", "array", 1000)], but this seems a fluke (it is just getindex, that should not be affected)

@vtjnash
Copy link
Member

vtjnash commented Apr 22, 2021

Yeah, LGTM

@@ -1970,4 +1957,58 @@ end
(*)(A::SparseVecOrMat{Float64,Ti},
B::Hermitian{Float64,SparseMatrixCSC{Float64,Ti}}) where {Ti} = sparse(Sparse(A)*Sparse(B))

# Sort all the indices in each column for the construction of a CSC sparse matrix
# sortBuffers!(A, sortindices = :sortcols) # Sort each column with sort()
function sortBuffers!(m, n, colptr::Vector{Ti}, rowval::Vector{Ti}, nzval::Vector{Tv}) where {Ti <: Integer, Tv}
Copy link
Member

@KristofferC KristofferC Apr 22, 2021

Choose a reason for hiding this comment

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

Nit, but this looks a bit non-standard to me, any special reason for the camel case?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You're right, this comes from sortSparseMatrixCSC that was in sparsematrix.jl (which I didn't even remove for the moment), I'll rename it (it should not be exported though).

@vtjnash vtjnash added triage This should be discussed on a triage call and removed triage This should be discussed on a triage call labels Apr 22, 2021
@vtjnash
Copy link
Member

vtjnash commented Apr 22, 2021

I think this can be merged, once the reviewer comments are addressed. Any objections?

@abraunst
Copy link
Contributor Author

the memory regression should not be there, I'll investigate...

* Add sizehint!(::SparseMatrixCSC, args...),
* Fix illegal SparseMatrixCSC construction in cholmod and linalg.
* Remove tests targetting now illegal buffers
* Fix invalid buffer creation in kron and more
@abraunst
Copy link
Contributor Author

Should be fixed. The problem was that by removing the capacity function from the PR, we lose track of what is the target length of the buffers (which were sizehinted appropriately, but the allocated length was inaccessible). So I resorted to returning invalid buffers from _allocres (which is internal). Can we do another round of benchmarking?

@KristofferC
Copy link
Member

@nanosoldier runbenchmarks("sparse" || "problem" || "broadcast" || "linalg", vs="@671bccba27e69b40dabe73409df2b1feba25944c")

@nanosoldier
Copy link
Collaborator

Your benchmark job has completed - possible performance regressions were detected. A full report can be found here. cc @christopher-dG

@vtjnash vtjnash changed the title WIP: stricter buffers in SparseMatrixCSC stricter buffers in SparseMatrixCSC Apr 23, 2021
@vtjnash vtjnash added the merge me PR is reviewed. Merge when all tests are passing label Apr 23, 2021
@abraunst
Copy link
Contributor Author

The memory stuff seems gone. The other performance stuff that appeared seems funky...

@vtjnash vtjnash merged commit 248c02f into JuliaLang:master Apr 24, 2021
@dkarrasch dkarrasch removed the merge me PR is reviewed. Merge when all tests are passing label Apr 24, 2021
ElOceanografo pushed a commit to ElOceanografo/julia that referenced this pull request May 4, 2021
Make length(A.nzval)==nnz(A) and add strict buffer checking (#30662)

* Add sizehint!(::SparseMatrixCSC, args...),
* Fix illegal SparseMatrixCSC construction in cholmod and linalg.
* Remove tests targetting now illegal buffers
* Fix invalid buffer creation in kron and more
* use widelength in sizehint! to cope with large matrices in 32 bit systems
jarlebring pushed a commit to jarlebring/julia that referenced this pull request May 4, 2021
Make length(A.nzval)==nnz(A) and add strict buffer checking (#30662)

* Add sizehint!(::SparseMatrixCSC, args...),
* Fix illegal SparseMatrixCSC construction in cholmod and linalg.
* Remove tests targetting now illegal buffers
* Fix invalid buffer creation in kron and more
* use widelength in sizehint! to cope with large matrices in 32 bit systems
antoine-levitt pushed a commit to antoine-levitt/julia that referenced this pull request May 9, 2021
Make length(A.nzval)==nnz(A) and add strict buffer checking (#30662)

* Add sizehint!(::SparseMatrixCSC, args...),
* Fix illegal SparseMatrixCSC construction in cholmod and linalg.
* Remove tests targetting now illegal buffers
* Fix invalid buffer creation in kron and more
* use widelength in sizehint! to cope with large matrices in 32 bit systems
johanmon pushed a commit to johanmon/julia that referenced this pull request Jul 5, 2021
Make length(A.nzval)==nnz(A) and add strict buffer checking (#30662)

* Add sizehint!(::SparseMatrixCSC, args...),
* Fix illegal SparseMatrixCSC construction in cholmod and linalg.
* Remove tests targetting now illegal buffers
* Fix invalid buffer creation in kron and more
* use widelength in sizehint! to cope with large matrices in 32 bit systems
fredrikekre added a commit to JuliaSparse/SparseArrays.jl that referenced this pull request Dec 9, 2022
With this patch the output buffers to `sparse!` are resized in order to
satisfy the buffer length checks in the `SparseMatrixCSC` constructor
that were introduced in JuliaLang/julia#40523. Previously `csccolptr`
was never resized, and  `cscrowval` and `cscnzval` were only resized if
the buffers were too short (i.e. never truncated).

The requirement `length(csccolptr) >= n + 1` could be kept, but seems
unnecessary since all buffers need to be resized anyway (to pass the
constructor checks).

In particular this fixes calling `sparse!` with `I`, `J`, `V` as both
input and output buffers: `sparse!(I, J, V, m, n, ..., I, J, V)`.

Fixes #313.
fredrikekre added a commit to JuliaSparse/SparseArrays.jl that referenced this pull request Dec 9, 2022
With this patch the output buffers to `sparse!` are resized in order to
satisfy the buffer length checks in the `SparseMatrixCSC` constructor
that were introduced in JuliaLang/julia#40523. Previously `csccolptr`
was never resized, and  `cscrowval` and `cscnzval` were only resized if
the buffers were too short (i.e. never truncated).

The requirement `length(csccolptr) >= n + 1` could be kept, but seems
unnecessary since all buffers need to be resized anyway (to pass the
constructor checks).

In particular this fixes calling `sparse!` with `I`, `J`, `V` as both
input and output buffers: `sparse!(I, J, V, m, n, ..., I, J, V)`.

Fixes #313.
fredrikekre added a commit to JuliaSparse/SparseArrays.jl that referenced this pull request Dec 12, 2022
…314)

With this patch the output buffers to `sparse!` are resized in order to
satisfy the buffer length checks in the `SparseMatrixCSC` constructor
that were introduced in JuliaLang/julia#40523. Previously `csccolptr`
was never resized, and  `cscrowval` and `cscnzval` were only resized if
the buffers were too short (i.e. never truncated).

The requirement `length(csccolptr) >= n + 1` could be kept, but seems
unnecessary since all buffers need to be resized anyway (to pass the
constructor checks).

In particular this fixes calling `sparse!` with `I`, `J`, `V` as both
input and output buffers: `sparse!(I, J, V, m, n, ..., I, J, V)`.

Fixes #313.
fredrikekre added a commit to JuliaSparse/SparseArrays.jl that referenced this pull request Dec 12, 2022
…314)

With this patch the output buffers to `sparse!` are resized in order to
satisfy the buffer length checks in the `SparseMatrixCSC` constructor
that were introduced in JuliaLang/julia#40523. Previously `csccolptr`
was never resized, and  `cscrowval` and `cscnzval` were only resized if
the buffers were too short (i.e. never truncated).

The requirement `length(csccolptr) >= n + 1` could be kept, but seems
unnecessary since all buffers need to be resized anyway (to pass the
constructor checks).

In particular this fixes calling `sparse!` with `I`, `J`, `V` as both
input and output buffers: `sparse!(I, J, V, m, n, ..., I, J, V)`.

Fixes #313.

(cherry picked from commit 85a381b)
fredrikekre added a commit to JuliaSparse/SparseArrays.jl that referenced this pull request Dec 12, 2022
…314)

With this patch the output buffers to `sparse!` are resized in order to
satisfy the buffer length checks in the `SparseMatrixCSC` constructor
that were introduced in JuliaLang/julia#40523. Previously `csccolptr`
was never resized, and  `cscrowval` and `cscnzval` were only resized if
the buffers were too short (i.e. never truncated).

The requirement `length(csccolptr) >= n + 1` could be kept, but seems
unnecessary since all buffers need to be resized anyway (to pass the
constructor checks).

In particular this fixes calling `sparse!` with `I`, `J`, `V` as both
input and output buffers: `sparse!(I, J, V, m, n, ..., I, J, V)`.

Fixes #313.

(cherry picked from commit 85a381b)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
sparse Sparse arrays
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants