-
Notifications
You must be signed in to change notification settings - Fork 8
Implement csc_view, implement transposed.
#30
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
Changes from 7 commits
de12da2
ae5af30
6632825
3750a1e
e1f2cd2
3fde64c
1f2be4a
dd7bfb4
907539b
273ae73
cf16b4c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| #include <iostream> | ||
| #include <spblas/spblas.hpp> | ||
|
|
||
| #include <fmt/core.h> | ||
| #include <fmt/ranges.h> | ||
|
|
||
| int main(int argc, char** argv) { | ||
| using namespace spblas; | ||
| namespace md = spblas::__mdspan; | ||
|
|
||
| using T = float; | ||
|
|
||
| spblas::index_t m = 100; | ||
| spblas::index_t n = 10; | ||
| spblas::index_t k = 100; | ||
| spblas::index_t nnz_in = 10; | ||
|
|
||
| fmt::print("\n\t###########################################################" | ||
| "######################"); | ||
| fmt::print("\n\t### Running SpMM Example:"); | ||
| fmt::print("\n\t###"); | ||
| fmt::print("\n\t### Y = alpha * A * X"); | ||
| fmt::print("\n\t###"); | ||
| fmt::print("\n\t### with "); | ||
| fmt::print("\n\t### A, in CSR format, of size ({}, {}) with nnz = {}", m, k, | ||
| nnz_in); | ||
| fmt::print("\n\t### x, a dense matrix, of size ({}, {})", k, n); | ||
| fmt::print("\n\t### y, a dense vector, of size ({}, {})", m, n); | ||
| fmt::print("\n\t### using float and spblas::index_t (size = {} bytes)", | ||
| sizeof(spblas::index_t)); | ||
| fmt::print("\n\t###########################################################" | ||
| "######################"); | ||
| fmt::print("\n"); | ||
|
|
||
| auto&& [values, colptr, rowind, shape, nnz] = generate_csc<T>(m, k, nnz_in); | ||
|
|
||
| csc_view<T> a(values, colptr, rowind, shape, nnz); | ||
|
|
||
| std::vector<T> x_values(k * n, 1); | ||
| std::vector<T> y_values(m * n, 0); | ||
|
|
||
| md::mdspan x(x_values.data(), k, n); | ||
| md::mdspan y(y_values.data(), m, n); | ||
|
|
||
| // y = A * (alpha * x) | ||
| multiply(a, scaled(2.f, x), y); | ||
|
|
||
| fmt::print("{}\n", spblas::__backend::values(y)); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. are you sure we want to print out the 100x10 = 1000 values of y ? maybe we want to have a "print dense matrix" routine that prints the first 4 rows (first 4 columns, ... , last 4 columns) and then ... then last 4 rows (first 4 columns, ... , last 4 columns) in a nicely printed and tab aligned to commas view ?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we could do similar thing with dense vector, only printing out first 4 elements, then last 4 elements. And also a similar thing for sparse matrix with printing first 4 rows and last 4 rows ... maybe it could take in a parameter that represents block_size (default = 4) to be printed ?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I think writing a pretty printer and then using that in the examples would be nice. (We can implement a |
||
|
|
||
| fmt::print("\tExample is completed!\n"); | ||
|
|
||
| return 0; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| #pragma once | ||
|
|
||
| #include <spblas/concepts.hpp> | ||
|
|
||
| namespace spblas { | ||
|
|
||
| template <matrix M> | ||
| auto transposed(M&& m); | ||
|
|
||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| #pragma once | ||
|
|
||
| #include <spblas/detail/view_inspectors.hpp> | ||
|
|
||
| namespace spblas { | ||
|
|
||
| template <matrix M> | ||
| requires(__detail::is_csr_view_v<M>) | ||
| auto transposed(M&& m) { | ||
| return csc_view<tensor_scalar_t<M>, tensor_index_t<M>, tensor_offset_t<M>>( | ||
| m.values(), m.rowptr(), m.colind(), {m.shape()[1], m.shape()[0]}, | ||
| m.size()); | ||
| } | ||
|
|
||
| template <matrix M> | ||
| requires(__detail::is_csc_view_v<M>) | ||
| auto transposed(M&& m) { | ||
| return csr_view<tensor_scalar_t<M>, tensor_index_t<M>, tensor_offset_t<M>>( | ||
| m.values(), m.colptr(), m.rowind(), {m.shape()[1], m.shape()[0]}, | ||
| m.size()); | ||
| } | ||
|
Comment on lines
+7
to
+21
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. here is where the relationship between CSR and CSC through transpose (not conjugate transpose though) comes into play with the switching of
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you had csr_view<float> a(/* ... */);
// Explicit transpose class
transposed_view<csr_view<float>> a_t = transposed(a);
// Versus csc_view
csc_view<float> a_csc_t = transposed(a);If |
||
|
|
||
| } // namespace spblas | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,26 +5,44 @@ | |
|
|
||
| namespace spblas { | ||
|
|
||
| // Customization point implementations for csr_view. | ||
| // Customization point implementations for csr_view and csc_view. | ||
|
|
||
| template <typename M> | ||
| requires(__detail::is_csr_view_v<M>) | ||
| auto tag_invoke(__backend::size_fn_, M&& m) { | ||
| return m.size(); | ||
| } | ||
|
|
||
| template <typename M> | ||
| requires(__detail::is_csc_view_v<M>) | ||
| auto tag_invoke(__backend::size_fn_, M&& m) { | ||
| return m.size(); | ||
| } | ||
|
|
||
| template <typename M> | ||
| requires(__detail::is_csr_view_v<M>) | ||
| auto tag_invoke(__backend::shape_fn_, M&& m) { | ||
| return m.shape(); | ||
| } | ||
|
|
||
| template <typename M> | ||
| requires(__detail::is_csc_view_v<M>) | ||
| auto tag_invoke(__backend::shape_fn_, M&& m) { | ||
| return m.shape(); | ||
| } | ||
|
|
||
| template <typename M> | ||
| requires(__detail::is_csr_view_v<M>) | ||
| auto tag_invoke(__backend::values_fn_, M&& m) { | ||
| return m.values(); | ||
| } | ||
|
|
||
| template <typename M> | ||
| requires(__detail::is_csc_view_v<M>) | ||
| auto tag_invoke(__backend::values_fn_, M&& m) { | ||
| return m.values(); | ||
| } | ||
|
|
||
| namespace { | ||
|
|
||
| template <typename M> | ||
|
|
@@ -47,6 +65,26 @@ auto row(M&& m, typename std::remove_cvref_t<M>::index_type row_index) { | |
| return __ranges::views::zip(column_indices, row_values); | ||
| } | ||
|
|
||
| template <typename M> | ||
| requires(__detail::is_csc_view_v<M>) | ||
| auto column(M&& m, typename std::remove_cvref_t<M>::index_type column_index) { | ||
| using O = typename std::remove_cvref_t<M>::offset_type; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we probably need to go through and update all the usages everywhere to include a
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually |
||
| O first = m.colptr()[column_index]; | ||
| O last = m.colptr()[column_index + 1]; | ||
|
|
||
| using row_iter_t = decltype(m.rowind().data()); | ||
| using value_iter_t = decltype(m.values().data()); | ||
|
|
||
| __ranges::subrange<row_iter_t> column_indices( | ||
| __ranges::next(m.rowind().data(), first), | ||
| __ranges::next(m.rowind().data(), last)); | ||
| __ranges::subrange<value_iter_t> column_values( | ||
| __ranges::next(m.values().data(), first), | ||
| __ranges::next(m.values().data(), last)); | ||
|
|
||
| return __ranges::views::zip(column_indices, column_values); | ||
| } | ||
|
|
||
| } // namespace | ||
|
|
||
| template <typename M> | ||
|
|
@@ -62,6 +100,20 @@ auto tag_invoke(__backend::rows_fn_, M&& m) { | |
| return __ranges::views::zip(row_indices, row_values); | ||
| } | ||
|
|
||
| template <typename M> | ||
| requires(__detail::is_csc_view_v<M>) | ||
| auto tag_invoke(__backend::columns_fn_, M&& m) { | ||
| using I = typename std::remove_cvref_t<M>::index_type; | ||
| auto column_indices = __ranges::views::iota(I(0), I(m.shape()[1])); | ||
|
|
||
| auto column_values = | ||
| column_indices | __ranges::views::transform([=](auto column_index) { | ||
| return column(m, column_index); | ||
| }); | ||
|
|
||
| return __ranges::views::zip(column_indices, column_values); | ||
| } | ||
|
|
||
| template <typename M> | ||
| requires(__detail::is_csr_view_v<M>) | ||
| auto tag_invoke(__backend::lookup_row_fn_, M&& m, | ||
|
|
@@ -70,6 +122,14 @@ auto tag_invoke(__backend::lookup_row_fn_, M&& m, | |
| return row(m, row_index); | ||
| } | ||
|
|
||
| template <typename M> | ||
| requires(__detail::is_csc_view_v<M>) | ||
| auto tag_invoke(__backend::lookup_column_fn_, M&& m, | ||
| typename std::remove_cvref_t<M>::index_type column_index) { | ||
| using I = typename std::remove_cvref_t<M>::index_type; | ||
| return column(m, column_index); | ||
| } | ||
|
|
||
| // Customization point implementations for vectors | ||
|
|
||
| template <__ranges::random_access_range V> | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -26,6 +26,21 @@ template <> | |
| inline constexpr auto create_spmat_csr<std::complex<double>> = | ||
| &armpl_spmat_create_csr_z; | ||
|
|
||
| template <typename T> | ||
| armpl_status_t (*create_spmat_csc)(armpl_spmat_t*, armpl_int_t, armpl_int_t, | ||
| const armpl_int_t*, const armpl_int_t*, | ||
| const T*, armpl_int_t); | ||
| template <> | ||
| inline constexpr auto create_spmat_csc<float> = &armpl_spmat_create_csc_s; | ||
| template <> | ||
| inline constexpr auto create_spmat_csc<double> = &armpl_spmat_create_csc_d; | ||
| template <> | ||
| inline constexpr auto create_spmat_csc<std::complex<float>> = | ||
| &armpl_spmat_create_csc_c; | ||
| template <> | ||
| inline constexpr auto create_spmat_csc<std::complex<double>> = | ||
| &armpl_spmat_create_csc_z; | ||
|
|
||
|
Comment on lines
+29
to
+43
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do you prefer this kind of template specialization over the kind I have in https://github.com/SparseBLAS/spblas-reference/pull/23/files#diff-6ac61c9e281330753acb230d10581803329208dd22ef5d9fdb5492b845c8acf1R19-R42 for instance ?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, I actually prefer what you're doing there with IESparseBLAS. I think Chris originally wrote this code, but the two styles are pretty much equivalent. |
||
| template <typename T> | ||
| armpl_status_t (*create_spmat_dense)(armpl_spmat_t*, enum armpl_dense_layout, | ||
| armpl_int_t, armpl_int_t, armpl_int_t, | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.