-
Notifications
You must be signed in to change notification settings - Fork 197
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
Gram matrix support for sparse input #1296
Conversation
Pull requests from external contributors require approval from a |
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.
Hi Malte, thanks for the PR! I have looked at the changes of the Gram matrices. Overall it looks nice, below you will find my comments.
I have added the "braking" label to remind us that we have code in cuML that is affected by the interface changes (even though it is the detail namespace, so technically it should not be breaking).
I will share my comments about the new norm method separately.
template <typename math_t> | ||
class DenseMatrix : public Matrix<math_t> { | ||
public: | ||
DenseMatrix(math_t* data, int rows, int cols, bool row_major = false, int ld_in = 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.
Ideally we would like to use mdspan for representing the dense matrix. Could you list the pain points that would motivate keeping a pointer based API still around?
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 thought about storing the dense data ptr as raft::device_aligned_matrix_view<math_t, std::uint32_t, layout_left_padded<math_t>>
, which would combine the the information of data/n_rows/n_cols/is_row_major/lld
.
This would require getters for all members as they need to be extracted from layout which is fine.
The reasons I did not choose to do it though are
- Python interface in cuML for what this is wrapper was originally build for starts with raw pointer(s) from (Sparse)CumlArray, which is why a simple container containing these pointers was an easy and sufficient approach. Using mdspan would add additional code here in order to construct the layouts.
- only raw data pointers need to be extracted and forwarded to third party libs (like cublas/cusparse), no element access needed that could benefit from mdspan/layout
- matrix container for sparse would still have raw data pointers and individual members for
rows/cols/nnz
which feels inconsistent
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 am fine keeping this version until the sparse wrapper PR New Sparse Matrix APIs #1279 is merged, and consolidate the interface afterwards.
- Note that we have helper functions to deal with mdspan on the Python side, see usage example here
get_dmv_float(vecs_cai, check_shape=True),
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 agree with @tfeher, rather than introducing more abstractions for this, we can unify the dense and sparse APIs using overloads of the existing abstractions (with templates if needed).
We didn’t have abstractions like the mdspan available when we were building cuml so we used pointers for everything. Now that we have the proper abstractions and infrastructure in place, we should use them.
please note that the sparse API has been merged. We should be able to add overloads for both dense and sparse without having an explicit class to unify them.
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.
@cjnolet, @tfeher , I have updated the PR to utilize both device_mdspan
and device_csr_matrix_view
as input for GramMatrixBase. I have not yet adapted the cuML branch as I would like to hear your feedback first.
I had to explicitly define combinations of inputs for the evaluate method as it is virtual and needs to be overridden by the deriving kernels. I did not find an elegant way to describe this via templates which results in some duplicated code. If you have a better suggestion on how to design this avoiding code duplication without introducing other pain I'd be happy to hear about it.
Note that lots of the code-lines is marked as deprecated
and only exist to be backwards compatible to cuML. We can remove it as soon as the cuML PR is merged as well.
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.
My apologies @tfeher and @mfoerste4, I meant to revisit this discussion myself and things have been pretty crazy the past couple of weeks. Please understand that my scrutiny over adding new types is only because
- I want to make sure that we're not exploding the number of types that a user needs work with, and
- making sure that we aren't creating new types each time we encounter a new pattern, unless said types can be at least moderately reusable across the codebase.
It sounds like the goal here is to have a trivial unified base class just so we can accept a single type and dispatch to the specific types. So far, the cython APIs in RAFT have gotten pretty tedious to code- and that's just for host/device mdspan. Adding sparse to the mid and accepting that on host and device is going to make things even more tedious. I definiely understand the reasoning here.
Currently, the SimpleMat
contains linear algebra implementations. If the goal here is just to have a unified base class that can accept read-only inputs, could we maybe just create a very simple class called something like read_only_matrix_view
which we extend for csr_read_only_matrix_view
and dense_read_only_matrix_view
?
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.
No need to apologize. As far as I am concerned we can keep the GramMatrix raft interface as is with 3 different APIs for Dense, Sparse & Mixed input. This would keep the Raft API clean and we would not need another wrapper definition - at least not in raft.
As for cuML, in addition to the read-only views we also need a data/structure-owning matrix wrapper that allows for resizing internal data structures (ResizableCsrMatrix). As this is very specific for this use-case,
I would propose to re-use the old simple unified wrapper (with resizable addon) within cuML. It has simple constructors to be created from (Sparse)CumlArray
within cython, and can be modified to internally contain/provide either mdspan
or csr_matrix_views
in order to be used when calling into raft.
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.
As for cuML, in addition to the read-only views we also need a data/structure-owning matrix wrapper that allows for resizing internal data structures (ResizableCsrMatrix). As this is very specific for this use-case,
I would propose to re-use the old simple unified wrapper (with resizable addon) within cuML.
It sounds like what you need there is indeed a structure-owning
CSR matrix. Why not use the one that's already in RAFT? That's actually not a very specific use-case at all and that structure/pattern is used heavily through the sparse APIs. Again, it looks like we're duplicating types, which means increased maintenance burden.
Eventually, all of RAFT"s sparse APIs (and cuml) will be using those sparse types but these are baby steps. The purpose of those structure-owning types is to allow you to own the underlying data arrays and initialize the sparsity (resize) once you know it.
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.
Why not use the one that's already in RAFT?
You are right, it seems that the data-owning csr_matrix would be a perfect fit once we switch to mdspan/csr_matrix_(view) representation within the unified wrapper.
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.
As far as I am concerned we can keep the GramMatrix raft interface as is with 3 different APIs for Dense, Sparse & Mixed input.
@cjnolet, are you ok with the current API of the GramMatrix? Further discussion on the cuML APIs can take place in the cuML PR.
Thanks @tfeher for reviewing. I have applied your suggestions pushed an update. |
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.
Thanks Malte for updating the PR! Here are my second batch of comments (related to csr norm).
We need to find a way not to break cuML with this PR. Can we just keep the old implementation as on overload, and remove it once the corresponding cuML PR is accepted?
I could add the old interface, but it would be a bit more intrusive as
|
…compatibility until cuml is updated
@tfeher , I added the old interface for backwards compatibility and marked it as |
@mfoerste4 just a note- I bumped this to 23.06. I'll re-review so we can get this in quickly. |
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.
Thanks for the updates, @mfoerste4. The new norm
and sparse::spmm
APIs look great. I think this is almost there.
typename NZType, | ||
typename LayoutPolicyY, | ||
typename LayoutPolicyZ> | ||
void spmm(raft::device_resources const& handle, |
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.
Tagging @divyegala for awareness thoughts since he's starting on exposing the sparse APIs w/ our new core vocabulary.
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. Thanks Malte! Before we merge this, we should probably open a blank PR in cuml that pins the RAFT fork/tag in cpp/cmake/thirdparty/get_raft.cmake
to your branch just to make sure we didn't overlook anything that might break cuml when we merge this.
Thanks @cjnolet. I have created a test PR here. |
@mfoerste4 a few recent updates to the sparse API broke your changes here. I can make these updates and push to your banch if it's easier (since I know what changed). |
@cjnolet , that would be great, thanks. I have been trying to keep it green but did not confirm after the last merge. |
/merge |
This PR adds sparse input support (CSR) for GramMatrix kernel computation. This is a requirement to enable SVM support for sparse input in [cuML issue 2197](rapidsai/cuml#2197). It also adds row norm computation for CSR which is utilized for expanded L2 norm computation within RBF kernels. Although this branch introduces a new API it is still backwards compatible with the old GramMatrix API (which is marked as deprecated). CC @cjnolet @tfeher Authors: - Malte Förster (https://github.com/mfoerste4) - Corey J. Nolet (https://github.com/cjnolet) Approvers: - Tamas Bela Feher (https://github.com/tfeher) - Corey J. Nolet (https://github.com/cjnolet) URL: rapidsai#1296
This PR adds support for sparse input to SVR and SVC. 'fit' as well as 'predict' can be called with sparse data compatible/convertible to SparseCumlArray. Support vectors in the model might also be stored as sparse data and can be retrieved as such. This PR requires rapidsai/raft#1296 to provide sparse kernel computations. Corresponding issue: #2197 Authors: - Malte Förster (https://github.com/mfoerste4) - Tamas Bela Feher (https://github.com/tfeher) Approvers: - Tamas Bela Feher (https://github.com/tfeher) - Corey J. Nolet (https://github.com/cjnolet) URL: #5273
This PR adds sparse input support (CSR) for GramMatrix kernel computation. This is a requirement to enable SVM support for sparse input in cuML issue 2197.
It also adds row norm computation for CSR which is utilized for expanded L2 norm computation within RBF kernels.
Although this branch introduces a new API it is still backwards compatible with the old GramMatrix API (which is marked as deprecated).
CC @cjnolet @tfeher