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

[SPARK-20687][MLLIB] mllib.Matrices.fromBreeze may crash when converting from Breeze sparse matrix #17940

Closed
wants to merge 6 commits into from

Conversation

ghoto
Copy link
Contributor

@ghoto ghoto commented May 10, 2017

What changes were proposed in this pull request?

When two Breeze SparseMatrices are operated, the result matrix may contain provisional 0 values extra in rowIndices and data arrays. This causes an incoherence with the colPtrs data, but Breeze get away with this incoherence by keeping a counter of the valid data.

In spark, when this matrices are converted to SparseMatrices, Sparks relies solely on rowIndices, data, and colPtrs, but these might be incorrect because of breeze internal hacks. Therefore, we need to slice both rowIndices and data, using their counter of active data

This method is at least called by BlockMatrix when performing distributed block operations, causing exceptions on valid operations.

See http://stackoverflow.com/questions/33528555/error-thrown-when-using-blockmatrix-add

How was this patch tested?

Added a test to MatricesSuite that verifies that the conversions are valid and that code doesn't crash. Originally the same code would crash on Spark.

Bugfix for https://issues.apache.org/jira/browse/SPARK-20687

ghoto added 2 commits May 9, 2017 21:31
…ng breeze CSCMatrix

In an operation of two A, B CSCMatrices the resulting C matrix may have some extra 0s
in rowIndices and data which are created for performance improvement by Breeze.
This causes problems on converting back to mllib.Matrix because it relies on
rowIndices and data being coherent with colPtrs. Therefore it is necessary to truncate
rowIndices and data to the active number of elements hold by the C matrix, before
creating a Spark's SparseMatrix.
@srowen
Copy link
Member

srowen commented May 10, 2017

Please fix up the title and description per http://spark.apache.org/contributing.html

@ghoto ghoto changed the title Bug fix/spark 20687 [SPARK-20687][MLLIB] mllib.Matrices.fromBreeze may crash when converting from Breeze sparse matrix May 11, 2017
@ghoto
Copy link
Contributor Author

ghoto commented May 11, 2017

Sorry about that. I added more context in the description and updated the title.

@srowen
Copy link
Member

srowen commented May 11, 2017

CC @hhbyyh for #9520
Looks credible to me.

@SparkQA
Copy link

SparkQA commented May 11, 2017

Test build #3710 has finished for PR 17940 at commit dbbd391.

  • This patch fails Scala style tests.
  • This patch merges cleanly.
  • This patch adds no public classes.

@ghoto
Copy link
Contributor Author

ghoto commented May 11, 2017

Need to fix line in the test because it's too long.

Copy link
Contributor

@hhbyyh hhbyyh left a comment

Choose a reason for hiding this comment

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

Thanks for the PR. also cc @yanboliang . Looks like the issue is still present.

// despite sm being a valid CSCMatrix.
// We need to truncate both arrays (rowIndices, data)
// to the real size of the vector sm.activeSize to allow valid conversion

Copy link
Contributor

@hhbyyh hhbyyh May 12, 2017

Choose a reason for hiding this comment

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

Maybe we can add if (sm.activeSize != sm.rowIndices.length) here, since this is only needed when necessary.
Please refer to https://github.com/scalanlp/breeze/blob/master/math/src/main/scala/breeze/linalg/CSCMatrix.scala#L130

// to the real size of the vector sm.activeSize to allow valid conversion

val truncRowIndices = sm.rowIndices.slice(0, sm.activeSize)
val truncData = sm.data.slice(0, sm.activeSize)
Copy link
Contributor

@hhbyyh hhbyyh May 12, 2017

Choose a reason for hiding this comment

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

This is the same as calling compact(). To make it less sensitive to the breeze internal implementation, how about:

val matCopy = sm.copy
matCopy.compact()

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm implementing both suggestions, however, wouldn't be the sm.copy more expensive than just doing those 2 slices?

@@ -46,6 +46,26 @@ class MatricesSuite extends SparkFunSuite {
}
}

test("Test Breeze Conversion Bug - SPARK-20687") {
Copy link
Contributor

Choose a reason for hiding this comment

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

specific name: Test FromBreeze when Breeze.CSCMatrix.rowIndices has trailing zeros.

And move the test after another unit test "fromBreeze with sparse matrix"

Copy link
Contributor

@hhbyyh hhbyyh left a comment

Choose a reason for hiding this comment

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

Thanks for the update. Looks good to me.

@@ -992,7 +992,24 @@ object Matrices {
new DenseMatrix(dm.rows, dm.cols, dm.data, dm.isTranspose)
case sm: BSM[Double] =>
// There is no isTranspose flag for sparse matrices in Breeze
new SparseMatrix(sm.rows, sm.cols, sm.colPtrs, sm.rowIndices, sm.data)

// Some Breeze CSCMatrices may have extra trailing zeros in
Copy link
Contributor

@hhbyyh hhbyyh May 13, 2017

Choose a reason for hiding this comment

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

minor: make this comment more compact in fewer lines.

@SparkQA
Copy link

SparkQA commented May 16, 2017

Test build #3714 has started for PR 17940 at commit b40a706.

@SparkQA
Copy link

SparkQA commented May 19, 2017

Test build #3727 has started for PR 17940 at commit b40a706.

@SparkQA
Copy link

SparkQA commented May 19, 2017

Test build #3733 has finished for PR 17940 at commit b40a706.

  • This patch passes all tests.
  • This patch merges cleanly.
  • This patch adds no public classes.

smC.compact()
new SparseMatrix(smC.rows, smC.cols, smC.colPtrs, smC.rowIndices, smC.data)
} else {
new SparseMatrix(sm.rows, sm.cols, sm.colPtrs, sm.rowIndices, sm.data)
Copy link
Member

Choose a reason for hiding this comment

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

@hhbyyh what do you think of the current state? I wasn't clear if you were requesting a specific change to the comment.

Here, if you're going to change it again, you could simplify by not repeating the new SparseMatrix(...) call. Just pick which sparse matrix you're copying in the if statement (original or compacted) and then return the result of converting that.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hey, I shortened the comment and I removed repeating the new SparseMatrix.

Give it a look now.

Copy link
Contributor

@hhbyyh hhbyyh left a comment

Choose a reason for hiding this comment

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

LGTM

@@ -992,7 +992,16 @@ object Matrices {
new DenseMatrix(dm.rows, dm.cols, dm.data, dm.isTranspose)
case sm: BSM[Double] =>
// There is no isTranspose flag for sparse matrices in Breeze
new SparseMatrix(sm.rows, sm.cols, sm.colPtrs, sm.rowIndices, sm.data)
val nsm = if (sm.rowIndices.length > sm.activeSize) {
// This sparse matrix has trainling zeros.
Copy link
Contributor

Choose a reason for hiding this comment

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

trailing

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ups.

@SparkQA
Copy link

SparkQA commented May 21, 2017

Test build #3746 has finished for PR 17940 at commit 18ce388.

  • This patch passes all tests.
  • This patch merges cleanly.
  • This patch adds no public classes.

asfgit pushed a commit that referenced this pull request May 22, 2017
…ing from Breeze sparse matrix

## What changes were proposed in this pull request?

When two Breeze SparseMatrices are operated, the result matrix may contain provisional 0 values extra in rowIndices and data arrays. This causes an incoherence with the colPtrs data, but Breeze get away with this incoherence by keeping a counter of the valid data.

In spark, when this matrices are converted to SparseMatrices, Sparks relies solely on rowIndices, data, and colPtrs, but these might be incorrect because of breeze internal hacks. Therefore, we need to slice both rowIndices and data, using their counter of active data

This method is at least called by BlockMatrix when performing distributed block operations, causing exceptions on valid operations.

See http://stackoverflow.com/questions/33528555/error-thrown-when-using-blockmatrix-add

## How was this patch tested?

Added a test to MatricesSuite that verifies that the conversions are valid and that code doesn't crash. Originally the same code would crash on Spark.

Bugfix for https://issues.apache.org/jira/browse/SPARK-20687

Author: Ignacio Bermudez <ignaciobermudez@gmail.com>
Author: Ignacio Bermudez Corrales <icorrales@splunk.com>

Closes #17940 from ghoto/bug-fix/SPARK-20687.

(cherry picked from commit 06dda1d)
Signed-off-by: Sean Owen <sowen@cloudera.com>
asfgit pushed a commit that referenced this pull request May 22, 2017
…ing from Breeze sparse matrix

## What changes were proposed in this pull request?

When two Breeze SparseMatrices are operated, the result matrix may contain provisional 0 values extra in rowIndices and data arrays. This causes an incoherence with the colPtrs data, but Breeze get away with this incoherence by keeping a counter of the valid data.

In spark, when this matrices are converted to SparseMatrices, Sparks relies solely on rowIndices, data, and colPtrs, but these might be incorrect because of breeze internal hacks. Therefore, we need to slice both rowIndices and data, using their counter of active data

This method is at least called by BlockMatrix when performing distributed block operations, causing exceptions on valid operations.

See http://stackoverflow.com/questions/33528555/error-thrown-when-using-blockmatrix-add

## How was this patch tested?

Added a test to MatricesSuite that verifies that the conversions are valid and that code doesn't crash. Originally the same code would crash on Spark.

Bugfix for https://issues.apache.org/jira/browse/SPARK-20687

Author: Ignacio Bermudez <ignaciobermudez@gmail.com>
Author: Ignacio Bermudez Corrales <icorrales@splunk.com>

Closes #17940 from ghoto/bug-fix/SPARK-20687.

(cherry picked from commit 06dda1d)
Signed-off-by: Sean Owen <sowen@cloudera.com>
@srowen
Copy link
Member

srowen commented May 22, 2017

Merged to master/2.2/2.1

@asfgit asfgit closed this in 06dda1d May 22, 2017
liyichao pushed a commit to liyichao/spark that referenced this pull request May 24, 2017
…ing from Breeze sparse matrix

## What changes were proposed in this pull request?

When two Breeze SparseMatrices are operated, the result matrix may contain provisional 0 values extra in rowIndices and data arrays. This causes an incoherence with the colPtrs data, but Breeze get away with this incoherence by keeping a counter of the valid data.

In spark, when this matrices are converted to SparseMatrices, Sparks relies solely on rowIndices, data, and colPtrs, but these might be incorrect because of breeze internal hacks. Therefore, we need to slice both rowIndices and data, using their counter of active data

This method is at least called by BlockMatrix when performing distributed block operations, causing exceptions on valid operations.

See http://stackoverflow.com/questions/33528555/error-thrown-when-using-blockmatrix-add

## How was this patch tested?

Added a test to MatricesSuite that verifies that the conversions are valid and that code doesn't crash. Originally the same code would crash on Spark.

Bugfix for https://issues.apache.org/jira/browse/SPARK-20687

Author: Ignacio Bermudez <ignaciobermudez@gmail.com>
Author: Ignacio Bermudez Corrales <icorrales@splunk.com>

Closes apache#17940 from ghoto/bug-fix/SPARK-20687.
jzhuge pushed a commit to jzhuge/spark that referenced this pull request Aug 20, 2018
…ing from Breeze sparse matrix

When two Breeze SparseMatrices are operated, the result matrix may contain provisional 0 values extra in rowIndices and data arrays. This causes an incoherence with the colPtrs data, but Breeze get away with this incoherence by keeping a counter of the valid data.

In spark, when this matrices are converted to SparseMatrices, Sparks relies solely on rowIndices, data, and colPtrs, but these might be incorrect because of breeze internal hacks. Therefore, we need to slice both rowIndices and data, using their counter of active data

This method is at least called by BlockMatrix when performing distributed block operations, causing exceptions on valid operations.

See http://stackoverflow.com/questions/33528555/error-thrown-when-using-blockmatrix-add

Added a test to MatricesSuite that verifies that the conversions are valid and that code doesn't crash. Originally the same code would crash on Spark.

Bugfix for https://issues.apache.org/jira/browse/SPARK-20687

Author: Ignacio Bermudez <ignaciobermudez@gmail.com>
Author: Ignacio Bermudez Corrales <icorrales@splunk.com>

Closes apache#17940 from ghoto/bug-fix/SPARK-20687.

(cherry picked from commit 06dda1d)
Signed-off-by: Sean Owen <sowen@cloudera.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants