-
-
Notifications
You must be signed in to change notification settings - Fork 26.6k
ENH add sparse_matmul_to_dense #31952
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
Conversation
A little benchmarkSummary: Roughly up to a factor of 2 as compared to sparse-sparse A @ B, never worse. I guess that the csc @ csc case could be improved by constructing Detailsfrom time import time
import numpy as np
import scipy.sparse as sp
from sklearn.utils.sparsefuncs import sparse_matmul_to_dense
def bench(n1=100, n2=100, n3=100, sparseness=0.5, rng=123):
rng = np.random.default_rng(rng)
a_dense = rng.standard_normal((n1, n2))
b_dense = rng.standard_normal((n2, n3))
p = [1 - sparseness, sparseness]
a_dense.flat[rng.choice([False, True], size=n1 * n2, p=p)] = 0
b_dense.flat[rng.choice([False, True], size=n2 * n3, p=p)] = 0
t0 = time()
a_dense @ b_dense
t = time() - t0
print(f"dense @ dense = {t}s")
for af in ("csr", "csc"):
a = sp.csr_array(a_dense) if af == "csr" else sp.csc_array(a_dense)
for bf in ("csr", "csc"):
b = sp.csr_array(b_dense) if bf == "csr" else sp.csc_array(b_dense)
t0 = time()
a @ b
t = time() - t0
print(f"{af} @ {bf} time = {t}s")
t0 = time()
sparse_matmul_to_dense(a, b)
t = time() - t0
print(f"sparse_matmul_to_dense time = {t}s\n") |
* csr_matmul_csc_to_dense does not improve performance vs. converting to csr
78d79e6 to
7bc3bd1
Compare
OmarManzoor
left a comment
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.
Thank you for the PR @lorentzenchr. I left a few comments
doc/whats_new/upcoming_changes/sklearn.utils/31952.efficiency.rst
Outdated
Show resolved
Hide resolved
OmarManzoor
left a comment
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.
A few more
OmarManzoor
left a comment
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.
LGTM. Thank you @lorentzenchr
| ) | ||
|
|
||
|
|
||
| def sparse_matmul_to_dense(A, B, out=None): |
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.
Do you see using out somewhere out side of testing code?
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.
So far, the only call in non-tests is via safe_sparse_dot - on purpose. safe_sparse_dot does not have an out parameter. But there are a few places where it could be used, e.g. in sandwich_dot inside linear_models._linear_loss.py.
| n1, n3 = n3, n1 | ||
| else: | ||
| # It seems best to just convert to csr. | ||
| A = A.tocsr() |
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.
Doe this use more memory than the implementation on main?
(Same question for the B conversion below: B = B.tocsr())
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.
Scipy (at least for CSR and CSC) converts the "other" matrix/array to the same format, here https://github.com/scipy/scipy/blob/f762ab3dddf1541da7475580f16d5a4b8da31fea/scipy/sparse/_compressed.py#L432C32-L432C37
Therefore the code of this PR uses the same amount of memory as pure scipy A @ B, only difference is the returned dense array.
Reference Issues/PRs
Fixes #516.
What does this implement/fix? Explain your changes.
This adds a dedicated Cython routine to compute
dense_C = sparse_A @ sparse_B.Any other comments?