-
Notifications
You must be signed in to change notification settings - Fork 119
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
Update set method for sparse to only add non-zero elements #145
base: SNAPSHOT
Are you sure you want to change the base?
Conversation
@Lundez thanks for the PR! Going to need to put some thought into this and make sure there are no unintended consequences. This might have also come up once before but I can't seem to find the PR or discussion. For example a potential negative is that, maybe someone wants to pre-initialize the sparse structure and now they need to jump through hoops and this is an unexpected behavior. In my personal real-world applications this isn't useful since I'm not assigning values unless it's non-zero (e.g Jacobian of a large sparse system). As an example of untended consequences, libraries which mark matrices as transposed instead of transposing them to save time/memory basically just end up with much more complex slower code and dubious memory saving. Are there any more established sparse linear algebra libraries which have this as their default behavior? E.g. SuiteSparse @FlorentinD @szarnyasg Any thoughts on this as well? |
@lessthanoptimal I think this is related to an earlier discussion in the SuiteSparse:GraphBLAS repository: GraphBLAS/LAGraph#28 It's quite a lengthy one, so the issue of explicit zeros is not a trivial one. SuiteSparse:GraphBLAS can yield explicit zeros in some cases and there are also ways to drop them (e.g. with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is going to work as intended. Once a non-zero element is already in the graph structure you want to assign it the new value no matter what. If the element is not in the graph structure and the value being assigned is zero you can safely not add it.
@@ -169,7 +171,7 @@ public void unsafe_set( int row, int col, double value ) { | |||
int index = nz_index(row, col); | |||
if (index < 0) | |||
addItem(row, col, value); | |||
else { | |||
else if (value != 0.0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Already in the graph structure so you want to update the value.
@@ -169,7 +171,7 @@ public void unsafe_set( int row, int col, double value ) { | |||
int index = nz_index(row, col); | |||
if (index < 0) | |||
addItem(row, col, value); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not in the graph structure so you could check to see if it's zero here and not add it.
@@ -231,7 +231,9 @@ public void set( int row, int col, double val ) { | |||
if (row < 0 || row >= numRows || col < 0 || col >= numCols) | |||
throw new IllegalArgumentException("Outside of matrix bounds"); | |||
|
|||
unsafe_set(row, col, val); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
see comments for triplet below.
@szarnyasg Thanks for linking to that discussion! Thanks to @FlorentinD you can remove zero elements too using |
Greetings to Lund @Lundez Personally, for a graph context, I favor having the possibility of Maybe we could provide another method that does not set zero elements, instead of changing existing behavior? |
Could make sense, or doing it the other way around. Thanks for everyones input, as soon as I know which direction I should take I'll fix the comments 👍 |
I'll chime in here as well. I've tried this optimization a few times, but for my use cases the extra branching always ended up costing more than I got from any subsequent benefits. There may be cases where it's worth it, but I'd vote against making it the default behavior. |
@ennerf thanks for that insight! What matrix size are you dealing with again? Curious if this could be replicated in a benchmark. |
@Lundez Right now I'm leaning towards having a distinctive setter that filters out zeros. That will also have a lower bar for being added as it can't potentially break a ton of code. Also forgot to mention in the PR, unit tests are missing. Unrelated to this PR are you a contributor to |
For what it's worth, it looks like Matlab and Octave filter out and remove 0 when assigning.
Octave Outputs:
|
@lessthanoptimal makes sense 👍 I'm not a contributor, but I guess I could get a PR up. |
@lessthanoptimal I think the largest CSC I used to benchmark in the polynomial spline trajectory project was 9k squared with 15k entries (1k segments), but I assume that the ratio of zeros probably matters more than the raw size. As far as I remember there were very few actual zeros, but unfortunately I'm not using CSC in that project anymore and can't easily reproduce the benchmark data. For a filtering setter it may be useful to have a minimum threshold for values that can be considered effectively zero, e.g., |
For more intuitive filtering based on the threshold idea by @ennerf , we could provide a 'filter(matrix, threshold)' method which delegates to select with a partly fixed lambda ('x-> |x| > threshold') |
I think it makes sense to disregard irrelevant values for the sparse matrices. I first noticed this issue when using another library (
kmath
) which has abuildMatrix
method they yet have to specialize for sparse structures.This
buildMatrix
would be much better off if theset
method never applied "0" elements. They risk of doubling the array-size way larger than required would still exist, but at least we wouldn't make sure that it happens 😉The best approach forward is for
kmath
to better support sparse structures, but this step in the right direction would be helpful for not onlykmath
-user but alsoejml
ones 😄Before submitting this PR, please make sure:
./gradlew spotlessJavaApply