diff --git a/docs/developer/apidocs/sparse.rst b/docs/developer/apidocs/sparse.rst index 463e00a733..ed877ac567 100644 --- a/docs/developer/apidocs/sparse.rst +++ b/docs/developer/apidocs/sparse.rst @@ -6,6 +6,21 @@ crsmatrix .. doxygenclass:: KokkosSparse::CrsMatrix :members: +ccsmatrix +--------- +.. doxygenclass:: KokkosSparse::CcsMatrix + :members: + +crs2ccs +------- +.. doxygenfunction:: KokkosSparse::crs2ccs(OrdinalType nrows, OrdinalType ncols, SizeType nnz, ValViewType vals, RowMapViewType row_map, ColIdViewType col_ids) +.. doxygenfunction:: KokkosSparse::crs2ccs(KokkosSparse::CrsMatrix &crsMatrix) + +ccs2crs +------- +.. doxygenfunction:: KokkosSparse::ccs2crs(OrdinalType nrows, OrdinalType ncols, SizeType nnz, ValViewType vals, ColMapViewType col_map, RowIdViewType row_ids) +.. doxygenfunction:: KokkosSparse::ccs2crs(KokkosSparse::CcsMatrix &ccsMatrix) + spmv ---- diff --git a/sparse/impl/KokkosSparse_spgemm_imp_outer.hpp b/sparse/impl/KokkosSparse_spgemm_imp_outer.hpp index c6a24e2163..8a390cc9a4 100644 --- a/sparse/impl/KokkosSparse_spgemm_imp_outer.hpp +++ b/sparse/impl/KokkosSparse_spgemm_imp_outer.hpp @@ -570,7 +570,7 @@ void KokkosSPGEMM( diff --git a/sparse/impl/KokkosSparse_spmv_spec.hpp b/sparse/impl/KokkosSparse_spmv_spec.hpp index cc29d72b77..fda6839c8f 100644 --- a/sparse/impl/KokkosSparse_spmv_spec.hpp +++ b/sparse/impl/KokkosSparse_spmv_spec.hpp @@ -176,7 +176,7 @@ struct SPMV { /// /// The first 5 template parameters are the template parameters of the /// input 1-D View of coefficients 'alpha'. The next 5 template -/// parameters are the same as those of KokkosSparse::CrsMatrix. In +/// parameters are the same as those of KokkosSparse::CrsMatrix. In /// particular: /// /// AT: type of each entry of the sparse matrix diff --git a/sparse/impl/KokkosSparse_spmv_struct_spec.hpp b/sparse/impl/KokkosSparse_spmv_struct_spec.hpp index ad175c2dfa..28892ef8b7 100644 --- a/sparse/impl/KokkosSparse_spmv_struct_spec.hpp +++ b/sparse/impl/KokkosSparse_spmv_struct_spec.hpp @@ -176,7 +176,7 @@ struct SPMV_STRUCT { /// /// The first 5 template parameters are the template parameters of the /// input 1-D View of coefficients 'alpha'. The next 5 template -/// parameters are the same as those of KokkosSparse::CrsMatrix. In +/// parameters are the same as those of KokkosSparse::CrsMatrix. In /// particular: /// /// AT: type of each entry of the sparse matrix diff --git a/sparse/src/KokkosSparse_CcsMatrix.hpp b/sparse/src/KokkosSparse_CcsMatrix.hpp new file mode 100644 index 0000000000..c2ae9c806e --- /dev/null +++ b/sparse/src/KokkosSparse_CcsMatrix.hpp @@ -0,0 +1,293 @@ +/* +//@HEADER +// ************************************************************************ +// +// Kokkos v. 3.0 +// Copyright (2020) National Technology & Engineering +// Solutions of Sandia, LLC (NTESS). +// +// Under the terms of Contract DE-NA0003525 with NTESS, +// the U.S. Government retains certain rights in this software. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact Siva Rajamanickam (srajama@sandia.gov) +// +// ************************************************************************ +//@HEADER +*/ + +/// \file KokkosSparse_CcsMatrix.hpp +/// \brief Local sparse matrix interface +/// +/// This file provides KokkosSparse::CcsMatrix. This implements a +/// local (no MPI) sparse matrix stored in compressed column sparse +/// ("Ccs") format. + +#ifndef KOKKOS_SPARSE_CCSMATRIX_HPP_ +#define KOKKOS_SPARSE_CCSMATRIX_HPP_ + +#include "Kokkos_Core.hpp" +#include +#include +#include +#include "KokkosSparse_findRelOffset.hpp" +#include "KokkosKernels_default_types.hpp" +#include "KokkosKernels_Macros.hpp" + +namespace Kokkos { +/// \class StaticCcsGraph +/// \brief Compressed column storage array copied from Kokkos::StaticCrsGraph. +/// +/// \tparam DataType The type of stored entries. If a StaticCcsGraph is +/// used as the graph of a sparse matrix, then this is usually an +/// integer type, the type of the column indices in the sparse +/// matrix. +/// +/// \tparam Arg1Type The second template parameter, corresponding +/// either to the Device type (if there are no more template +/// parameters) or to the Layout type (if there is at least one more +/// template parameter). +/// +/// \tparam Arg2Type The third template parameter, which if provided +/// corresponds to the Device type. +/// +/// \tparam Arg3Type The third template parameter, which if provided +/// corresponds to the MemoryTraits. +/// +/// \tparam SizeType The type of col offsets. Usually the default +/// parameter suffices. However, setting a nondefault value is +/// necessary in some cases, for example, if you want to have a +/// sparse matrices with dimensions (and therefore column indices) +/// that fit in \c int, but want to store more than INT_MAX +/// entries in the sparse matrix. +/// +/// A col has a range of entries: +///
    +///
  • col_map[i0] <= entry < col_map[i0+1]
  • +///
  • 0 <= i1 < col_map[i0+1] - col_map[i0]
  • +///
  • entries( entry , i2 , i3 , ... );
  • +///
  • entries( col_map[i0] + i1 , i2 , i3 , ... );
  • +///
+template ::size_type> +class StaticCcsGraph { + private: + using traits = ViewTraits; + + public: + using data_type = DataType; + using array_layout = typename traits::array_layout; + using execution_space = typename traits::execution_space; + using device_type = typename traits::device_type; + using memory_traits = typename traits::memory_traits; + using size_type = SizeType; + + using col_map_type = + View; + using entries_type = + View; + using row_block_type = + View; + + entries_type entries; + col_map_type col_map; + + //! Construct an empty view. + KOKKOS_INLINE_FUNCTION + StaticCcsGraph() : entries(), col_map() {} + + //! Copy constructor (shallow copy). + KOKKOS_INLINE_FUNCTION + StaticCcsGraph(const StaticCcsGraph& rhs) + : entries(rhs.entries), col_map(rhs.col_map) {} + + template + KOKKOS_INLINE_FUNCTION StaticCcsGraph(const EntriesType& entries_, + const ColMapType& col_map_) + : entries(entries_), col_map(col_map_) {} + + /** \brief Return number of columns in the graph + */ + KOKKOS_INLINE_FUNCTION + size_type numCols() const { + return (col_map.extent(0) != 0) + ? col_map.extent(0) - static_cast(1) + : static_cast(0); + } +}; +} // namespace Kokkos + +namespace KokkosSparse { +/// \class CcsMatrix +/// \brief Compressed sparse column implementation of a sparse matrix. +/// \tparam ScalarType The type of entries in the sparse matrix. +/// \tparam OrdinalType The type of column indices in the sparse matrix. +/// \tparam Device The Kokkos Device type. +/// \tparam MemoryTraits Traits describing how Kokkos manages and +/// accesses data. The default parameter suffices for most users. +/// +/// "Ccs" stands for "compressed column sparse." +template ::size_type> +class CcsMatrix { + static_assert( + std::is_signed::value, + "CcsMatrix requires that OrdinalType is a signed integer type."); + + public: + //! Type of the matrix's execution space. + typedef typename Device::execution_space execution_space; + //! Type of the matrix's memory space. + typedef typename Device::memory_space memory_space; + //! Canonical device type + typedef Kokkos::Device device_type; + typedef MemoryTraits memory_traits; + + /// \brief Type of each entry of the "column map." + /// + /// The "column map" corresponds to the \c ptr array of column offsets in + /// compressed sparse column (CCS) storage. + typedef SizeType size_type; + //! Type of each value in the matrix. + typedef ScalarType value_type; + //! Type of each (column) index in the matrix. + typedef OrdinalType ordinal_type; + //! Type of the graph structure of the sparse matrix - consistent with Kokkos. + typedef Kokkos::StaticCcsGraph + staticccsgraph_type; + //! Type of the "column map" (which contains the offset for each column's + //! data). + typedef typename staticccsgraph_type::col_map_type col_map_type; + typedef Kokkos::View + values_type; + //! Type of column indices in the sparse matrix. + typedef typename staticccsgraph_type::entries_type index_type; + + /// \name Storage of the actual sparsity structure and values. + /// + /// CcsMatrix uses the compressed sparse column (CCS) storage format to + /// store the sparse matrix. + //@{ + //! The graph (sparsity structure) of the sparse matrix. + staticccsgraph_type graph; + //! The 1-D array of values of the sparse matrix. + values_type values; + //@} + + private: + /// \brief The number of rows in the CCS matrix + ordinal_type numRows_; + + public: + /// \brief Default constructor; constructs an empty sparse matrix. + KOKKOS_INLINE_FUNCTION + CcsMatrix() : numRows_(0) {} + + // clang-format off + /// \brief Constructor that accepts a column map, row indices, and + /// values. + /// + /// The matrix will store and use the column map, indices, and values + /// directly (by view, not by deep copy). + /// + /// \param label [in] The sparse matrix's label. + /// \param nrows [in] The number of rows. + /// \param ncols [in] The number of columns. + /// \param annz [in] The number of entries. + /// \param vals [in] The entries. + /// \param colmap [in] The column map (containing the offsets to the data in + /// each column). + /// \param rows [in] The row indices. + // clang-format on + CcsMatrix(const std::string& /* label */, const OrdinalType nrows, + const OrdinalType ncols, const size_type annz, + const values_type& vals, const col_map_type& colmap, + const index_type& rows) + : graph(rows, colmap), values(vals), numRows_(nrows) { + const ordinal_type actualNumRows = + (colmap.extent(0) != 0) + ? static_cast(colmap.extent(0) - + static_cast(1)) + : static_cast(0); + if (ncols != actualNumRows) { + std::ostringstream os; + os << "Input argument ncols = " << ncols + << " != the actual number of " + "rows " + << actualNumRows << " according to the 'rows' input argument."; + throw std::invalid_argument(os.str()); + } + if (annz != nnz()) { + std::ostringstream os; + os << "Input argument annz = " << annz << " != this->nnz () = " << nnz() + << "."; + throw std::invalid_argument(os.str()); + } + } + + //! The number of rows in the sparse matrix. + KOKKOS_INLINE_FUNCTION ordinal_type numCols() const { + return graph.numCols(); + } + + //! The number of columns in the sparse matrix. + KOKKOS_INLINE_FUNCTION ordinal_type numRows() const { return numRows_; } + + //! The number of "point" (non-block) rows in the matrix. Since Ccs is not + //! blocked, this is just the number of regular rows. + KOKKOS_INLINE_FUNCTION ordinal_type numPointRows() const { return numRows(); } + + //! The number of "point" (non-block) columns in the matrix. Since Ccs is not + //! blocked, this is just the number of regular columns. + KOKKOS_INLINE_FUNCTION ordinal_type numPointCols() const { return numCols(); } + + //! The number of stored entries in the sparse matrix. + KOKKOS_INLINE_FUNCTION size_type nnz() const { + return graph.entries.extent(0); + } +}; + +/// \class is_ccs_matrix +/// \brief is_ccs_matrix::value is true if T is a CcsMatrix<...>, false +/// otherwise +template +struct is_ccs_matrix : public std::false_type {}; +template +struct is_ccs_matrix> : public std::true_type {}; +template +struct is_ccs_matrix> : public std::true_type {}; + +} // namespace KokkosSparse +#endif diff --git a/sparse/src/KokkosSparse_CrsMatrix.hpp b/sparse/src/KokkosSparse_CrsMatrix.hpp index c39ce348e4..dda08faba9 100644 --- a/sparse/src/KokkosSparse_CrsMatrix.hpp +++ b/sparse/src/KokkosSparse_CrsMatrix.hpp @@ -42,7 +42,7 @@ //@HEADER */ -/// \file Kokkos_Sparse_CrsMatrix.hpp +/// \file KokkosSparse_CrsMatrix.hpp /// \brief Local sparse matrix interface /// /// This file provides KokkosSparse::CrsMatrix. This implements a diff --git a/sparse/src/KokkosSparse_Utils.hpp b/sparse/src/KokkosSparse_Utils.hpp index e8f7fca72d..2616d8fbb7 100644 --- a/sparse/src/KokkosSparse_Utils.hpp +++ b/sparse/src/KokkosSparse_Utils.hpp @@ -434,7 +434,7 @@ void transpose_matrix( TransposeFunctor_t tm(num_rows, num_cols, xadj, adj, vals, t_xadj, t_adj, t_vals, tmp_row_view, true, team_size); - Kokkos::parallel_for("KokkosKernels::Impl::transpose_matrix::S0", + Kokkos::parallel_for("KokkosSparse::Impl::transpose_matrix::S0", count_tp_t((num_rows + team_size - 1) / team_size, team_size, thread_size), tm); @@ -446,7 +446,7 @@ void transpose_matrix( Kokkos::deep_copy(tmp_row_view, t_xadj); Kokkos::parallel_for( - "KokkosKernels::Impl::transpose_matrix::S1", + "KokkosSparse::Impl::transpose_matrix::S1", fill_tp_t((num_rows + team_size - 1) / team_size, team_size, thread_size), tm); diff --git a/sparse/src/KokkosSparse_ccs2crs.hpp b/sparse/src/KokkosSparse_ccs2crs.hpp new file mode 100644 index 0000000000..ae42592b1e --- /dev/null +++ b/sparse/src/KokkosSparse_ccs2crs.hpp @@ -0,0 +1,160 @@ +/* +//@HEADER +// ************************************************************************ +// +// Kokkos v. 3.0 +// Copyright (2020) National Technology & Engineering +// Solutions of Sandia, LLC (NTESS). +// +// Under the terms of Contract DE-NA0003525 with NTESS, +// the U.S. Government retains certain rights in this software. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact Siva Rajamanickam (srajama@sandia.gov) +// +// ************************************************************************ +//@HEADER +*/ + +#include "KokkosKernels_Utils.hpp" +#include "KokkosSparse_CcsMatrix.hpp" +#include "KokkosSparse_CrsMatrix.hpp" + +#ifndef _KOKKOSSPARSE_CCS2CRS_HPP +#define _KOKKOSSPARSE_CCS2CRS_HPP +namespace KokkosSparse { +namespace Impl { +template +class Ccs2Crs { + private: + using CrsST = typename ValViewType::value_type; + using CrsOT = OrdinalType; + using CrsET = typename ValViewType::execution_space; + using CrsMT = void; + using CrsSzT = SizeType; + using CrsType = CrsMatrix; + using CrsValsViewType = typename CrsType::values_type; + using CrsRowMapViewType = typename CrsType::row_map_type::non_const_type; + using CrsColIdViewType = typename CrsType::index_type; + + OrdinalType __nrows; + OrdinalType __ncols; + SizeType __nnz; + ValViewType __vals; + ColMapViewType __col_map; + RowIdViewType __row_ids; + + RowIdViewType __crs_row_cnt; + + CrsValsViewType __crs_vals; + CrsRowMapViewType __crs_row_map; + CrsColIdViewType __crs_col_ids; + + public: + Ccs2Crs(OrdinalType nrows, OrdinalType ncols, SizeType nnz, ValViewType vals, + ColMapViewType col_map, RowIdViewType row_ids) + : __nrows(nrows), + __ncols(ncols), + __nnz(nnz), + __vals(vals), + __col_map(col_map), + __row_ids(row_ids) { + __crs_vals = CrsValsViewType( + Kokkos::view_alloc(Kokkos::WithoutInitializing, "__crs_vals"), nnz); + __crs_row_map = + CrsRowMapViewType(Kokkos::view_alloc("__crs_row_map"), nrows + 1); + __crs_col_ids = CrsColIdViewType( + Kokkos::view_alloc(Kokkos::WithoutInitializing, "__crs_col_ids"), nnz); + + KokkosSparse::Impl::transpose_matrix< + ColMapViewType, RowIdViewType, ValViewType, CrsRowMapViewType, + CrsColIdViewType, CrsValsViewType, CrsRowMapViewType, CrsET>( + __ncols, __nrows, __col_map, __row_ids, __vals, __crs_row_map, + __crs_col_ids, __crs_vals); + } + + CrsType get_crsMat() { + return CrsType("ccs2crs", __nrows, __ncols, __nnz, __crs_vals, + __crs_row_map, __crs_col_ids); + } +}; +} // namespace Impl +// clang-format off +/// +/// \brief Blocking function that converts a ccs matrix to a CrsMatrix. +/// Ccs values are copied from column-contiguous layout into row-contiguous layout. +/// \tparam OrdinalType The view value type associated with the RowIdViewType +/// \tparam SizeType The type of nnz +/// \tparam ValViewType The values view type +/// \tparam ColMapViewType The column map view type +/// \tparam RowIdViewType The row ids view type +/// \param nrows The number of rows in the ccs matrix +/// \param ncols The number of columns in the ccs matrix +/// \param nnz The number of non-zeros in the ccs matrix +/// \param vals The values view of the ccs matrix +/// \param col_map The column map view of the ccs matrix +/// \param row_ids The row ids view of the ccs matrix +/// \return A KokkosSparse::CrsMatrix. +/// +/// \note In KokkosKernels sparse code, adj stands for adjacency list +/// and here we're passing in a ccs matrix with xadj=col_map and adj=row_ids. +// clang-format on +template +auto ccs2crs(OrdinalType nrows, OrdinalType ncols, SizeType nnz, + ValViewType vals, ColMapViewType col_map, RowIdViewType row_ids) { + using Ccs2crsType = Impl::Ccs2Crs; + Ccs2crsType ccs2Crs(nrows, ncols, nnz, vals, col_map, row_ids); + return ccs2Crs.get_crsMat(); +} + +/// +/// @brief Blocking function that converts a crs matrix to a CcsMatrix. +/// Ccs values are copied from column-contiguous layout into row-contiguous +/// layout. +/// +/// \tparam ScalarType The ccsMatrix::scalar_type +/// \tparam OrdinalType The ccsMatrix::ordinal_type +/// \tparam Device The ccsMatrix::device_type +/// \tparam MemoryTraits The ccsMatrix::memory_traits +/// \tparam SizeType The ccsMatrix::size_type +/// \param ccsMatrix The KokkosSparse::CcsMatrix. +/// \return A KokkosSparse::CrsMatrix. +template +auto ccs2crs(KokkosSparse::CcsMatrix &ccsMatrix) { + return ccs2crs(ccsMatrix.numRows(), ccsMatrix.numCols(), ccsMatrix.nnz(), + ccsMatrix.values, ccsMatrix.graph.col_map, + ccsMatrix.graph.entries); +} +} // namespace KokkosSparse +#endif // _KOKKOSSPARSE_CCS2CRS_HPP diff --git a/sparse/src/KokkosSparse_crs2ccs.hpp b/sparse/src/KokkosSparse_crs2ccs.hpp new file mode 100644 index 0000000000..3fd165ae47 --- /dev/null +++ b/sparse/src/KokkosSparse_crs2ccs.hpp @@ -0,0 +1,159 @@ +/* +//@HEADER +// ************************************************************************ +// +// Kokkos v. 3.0 +// Copyright (2020) National Technology & Engineering +// Solutions of Sandia, LLC (NTESS). +// +// Under the terms of Contract DE-NA0003525 with NTESS, +// the U.S. Government retains certain rights in this software. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact Siva Rajamanickam (srajama@sandia.gov) +// +// ************************************************************************ +//@HEADER +*/ + +#include "KokkosKernels_Utils.hpp" +#include "KokkosSparse_CcsMatrix.hpp" +#include "KokkosSparse_CrsMatrix.hpp" + +#ifndef _KOKKOSSPARSE_CRS2CCS_HPP +#define _KOKKOSSPARSE_CRS2CCS_HPP +namespace KokkosSparse { +namespace Impl { +template +class Crs2Ccs { + private: + using CcsST = typename ValViewType::value_type; + using CcsOT = OrdinalType; + using CcsET = typename ValViewType::execution_space; + using CcsMT = void; + using CcsSzT = SizeType; + using CcsType = CcsMatrix; + using CcsValsViewType = typename CcsType::values_type; + using CcsColMapViewType = typename CcsType::col_map_type::non_const_type; + using CcsRowIdViewType = typename CcsType::index_type; + + OrdinalType __nrows; + OrdinalType __ncols; + SizeType __nnz; + ValViewType __vals; + RowMapViewType __row_map; + ColIdViewType __col_ids; + + CcsValsViewType __ccs_vals; + CcsColMapViewType __ccs_col_map; + CcsRowIdViewType __ccs_row_ids; + + public: + Crs2Ccs(OrdinalType nrows, OrdinalType ncols, SizeType nnz, ValViewType vals, + RowMapViewType row_map, ColIdViewType col_ids) + : __nrows(nrows), + __ncols(ncols), + __nnz(nnz), + __vals(vals), + __row_map(row_map), + __col_ids(col_ids) { + __ccs_vals = CcsValsViewType( + Kokkos::view_alloc(Kokkos::WithoutInitializing, "__ccs_vals"), nnz); + __ccs_col_map = + CcsColMapViewType(Kokkos::view_alloc("__ccs_col_map"), ncols + 1); + __ccs_row_ids = CcsRowIdViewType( + Kokkos::view_alloc(Kokkos::WithoutInitializing, "__ccs_row_ids"), nnz); + + KokkosSparse::Impl::transpose_matrix< + RowMapViewType, ColIdViewType, ValViewType, CcsColMapViewType, + CcsRowIdViewType, CcsValsViewType, CcsColMapViewType, CcsET>( + __nrows, __ncols, __row_map, __col_ids, __vals, __ccs_col_map, + __ccs_row_ids, __ccs_vals); + } + + CcsType get_ccsMat() { + return CcsType("crs2ccs", __nrows, __ncols, __nnz, __ccs_vals, + __ccs_col_map, __ccs_row_ids); + } +}; +} // namespace Impl +// clang-format off +/// +/// \brief Blocking function that converts a CrsMatrix to a CcsMatrix. +/// Crs values are copied from row-contiguous layout into column-contiguous layout. +/// \tparam OrdinalType The view value type associated with the RowIdViewType +/// \tparam SizeType The type of nnz +/// \tparam ValViewType The values view type +/// \tparam RowMapViewType The column map view type +/// \tparam ColIdViewType The row ids view type +/// \param nrows The number of rows in the crs matrix +/// \param ncols The number of columns in the crs matrix +/// \param nnz The number of non-zeros in the crs matrix +/// \param vals The values view of the crs matrix +/// \param row_map The row map view of the crs matrix +/// \param col_ids The col ids view of the crs matrix +/// \return A KokkosSparse::CcsMatrix. +/// +/// \note In KokkosKernels sparse code, adj stands for adjacency list +/// and here we're passing in a crs matrix with xadj=row_map and adj=col_ids. +// clang-format on +template +auto crs2ccs(OrdinalType nrows, OrdinalType ncols, SizeType nnz, + ValViewType vals, RowMapViewType row_map, ColIdViewType col_ids) { + using Crs2ccsType = Impl::Crs2Ccs; + Crs2ccsType crs2Ccs(nrows, ncols, nnz, vals, row_map, col_ids); + return crs2Ccs.get_ccsMat(); +} + +/// +/// @brief Blocking function that converts a crs matrix to a CcsMatrix. +/// Crs values are copied from row-contiguous layout into column-contiguous +/// layout. +/// +/// \tparam ScalarType The crsMatrix::scalar_type +/// \tparam OrdinalType The crsMatrix::ordinal_type +/// \tparam Device The crsMatrix::device_type +/// \tparam MemoryTraits The crsMatrix::memory_traits +/// \tparam SizeType The crsMatrix::size_type +/// \param crsMatrix The KokkosSparse::CrsMatrix. +/// \return A KokkosSparse::CcsMatrix. +template +auto crs2ccs(KokkosSparse::CrsMatrix &crsMatrix) { + return crs2ccs(crsMatrix.numRows(), crsMatrix.numCols(), crsMatrix.nnz(), + crsMatrix.values, crsMatrix.graph.row_map, + crsMatrix.graph.entries); +} +} // namespace KokkosSparse + +#endif // _KOKKOSSPARSE_CRS2CCS_HPP \ No newline at end of file diff --git a/sparse/src/KokkosSparse_csc2csr.hpp b/sparse/src/KokkosSparse_csc2csr.hpp deleted file mode 100644 index 32f0c2b745..0000000000 --- a/sparse/src/KokkosSparse_csc2csr.hpp +++ /dev/null @@ -1,250 +0,0 @@ -/* -//@HEADER -// ************************************************************************ -// -// Kokkos v. 3.0 -// Copyright (2020) National Technology & Engineering -// Solutions of Sandia, LLC (NTESS). -// -// Under the terms of Contract DE-NA0003525 with NTESS, -// the U.S. Government retains certain rights in this software. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// 3. Neither the name of the Corporation nor the names of the -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY -// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Questions? Contact Siva Rajamanickam (srajama@sandia.gov) -// -// ************************************************************************ -//@HEADER -*/ - -#include "KokkosKernels_Utils.hpp" -#include - -#ifndef _KOKKOSSPARSE_CSC2CSR_HPP -#define _KOKKOSSPARSE_CSC2CSR_HPP -namespace KokkosSparse { -namespace Impl { -template -class Csc2Csr { - private: - using CrsST = typename ValViewType::value_type; - using CrsOT = OrdinalType; - using CrsET = typename ValViewType::execution_space; - using CrsMT = void; - using CrsSzT = SizeType; - using CrsType = CrsMatrix; - using CrsValsViewType = typename CrsType::values_type; - using CrsRowMapViewType = typename CrsType::row_map_type::non_const_type; - using CrsColIdViewType = typename CrsType::index_type; - - OrdinalType __nrows; - OrdinalType __ncols; - SizeType __nnz; - ValViewType __vals; - RowIdViewType __row_ids; - ColMapViewType __col_map; - - RowIdViewType __crs_row_cnt; - - CrsValsViewType __crs_vals; - CrsRowMapViewType __crs_row_map; - CrsRowMapViewType __crs_row_map_scratch; - CrsColIdViewType __crs_col_ids; - - public: - struct AlgoTags { - struct s1RowCnt {}; - struct s2RowMap {}; - struct s3Copy {}; - }; - - using s1RowCntTag = typename AlgoTags::s1RowCnt; - using s3CopyTag = typename AlgoTags::s3Copy; - - private: - using TeamPolicyType = Kokkos::TeamPolicy; - - int __suggested_team_size, __suggested_vec_size, __league_size; - - template - void __run(FunctorType &functor) { - // s1RowCntTag - { - Kokkos::parallel_for("Csc2Csr", - Kokkos::RangePolicy(0, __nnz), - functor); - CrsET().fence(); - } - // s2RowMapTag - { - namespace KE = Kokkos::Experimental; - CrsET crsET; - // Use exclusive scan so we can allocate the row map uninitialized and - // avoid accessing device views on the host. - KE::exclusive_scan(crsET, KE::cbegin(__crs_row_cnt), - KE::cend(__crs_row_cnt), KE::begin(__crs_row_map), 0); - CrsET().fence(); - Kokkos::deep_copy(__crs_row_map_scratch, __crs_row_map); - CrsET().fence(); - } - // s3CopyTag - { - TeamPolicyType teamPolicy(__ncols, __suggested_team_size, - __suggested_vec_size); - Kokkos::parallel_for("Csc2Csr", teamPolicy, functor); - CrsET().fence(); - } - // TODO: s3CopySortCompressTag - } - - public: - template - class __Functor { - private: - OrdinalType __nrows; - OrdinalType __ncols; - SizeType __nnz; - ValViewType __vals; - CrsValsViewType __crs_vals; - RowIdViewType __row_ids; - CrsRowMapViewType __crs_row_map; - CrsRowMapViewType __crs_row_map_scratch; - ColMapViewType __col_map; - CrsColIdViewType __crs_col_ids; - RowIdViewType __crs_row_cnt; - - public: - __Functor(OrdinalType nrows, OrdinalType ncols, SizeType nnz, - ValViewType vals, CrsValsViewType crs_vals, RowIdViewType row_ids, - CrsRowMapViewType crs_row_map, - CrsRowMapViewType crs_row_map_scratch, ColMapViewType col_map, - CrsColIdViewType crs_col_ids, RowIdViewType crs_row_cnt) - : __nrows(nrows), - __ncols(ncols), - __nnz(nnz), - __vals(vals), - __crs_vals(crs_vals), - __row_ids(row_ids), - __crs_row_map(crs_row_map), - __crs_row_map_scratch(crs_row_map_scratch), - __col_map(col_map), - __crs_col_ids(crs_col_ids), - __crs_row_cnt(crs_row_cnt){}; - - KOKKOS_INLINE_FUNCTION - void operator()(const s3CopyTag &, const MemberType &member) const { - auto j = member.league_rank(); - auto col_start = __col_map(j); - auto col_len = __col_map(j + 1) - col_start; - - Kokkos::parallel_for( - Kokkos::TeamVectorRange(member, 0, col_len), [&](const int &k) { - auto idx = col_start + k; - auto i = __row_ids(idx); - auto crs_idx = - Kokkos::atomic_fetch_inc(&__crs_row_map_scratch.data()[i]); - __crs_col_ids(crs_idx) = j; - __crs_vals(crs_idx) = __vals(idx); - }); - } - - KOKKOS_INLINE_FUNCTION - void operator()(const s1RowCntTag &, const int &thread_id) const { - Kokkos::atomic_inc(&__crs_row_cnt.data()[__row_ids(thread_id)]); - } - }; - - Csc2Csr(OrdinalType nrows, OrdinalType ncols, SizeType nnz, ValViewType vals, - RowIdViewType row_ids, ColMapViewType col_map, int league_size = 2) - : __nrows(nrows), - __ncols(ncols), - __nnz(nnz), - __vals(vals), - __row_ids(row_ids), - __col_map(col_map), - __league_size(league_size) { - __crs_vals = CrsValsViewType( - Kokkos::view_alloc(Kokkos::WithoutInitializing, "__crs_vals"), nnz); - __crs_row_map = CrsRowMapViewType( - Kokkos::view_alloc(Kokkos::WithoutInitializing, "__crs_row_map"), - nrows + 1); - __crs_row_map_scratch = - CrsRowMapViewType(Kokkos::view_alloc(Kokkos::WithoutInitializing, - "__crs_row_map_scratch"), - nrows + 1); - __crs_col_ids = CrsColIdViewType( - Kokkos::view_alloc(Kokkos::WithoutInitializing, "__crs_col_ids"), nnz); - - __crs_row_cnt = RowIdViewType("__crs_row_cnt", __nrows + 1); - - __Functor functor( - __nrows, __ncols, __nnz, __vals, __crs_vals, __row_ids, __crs_row_map, - __crs_row_map_scratch, __col_map, __crs_col_ids, __crs_row_cnt); - - KokkosKernels::Impl::get_suggested_vector_size( - __suggested_vec_size, __nrows, __nnz); - __suggested_team_size = - KokkosKernels::Impl::get_suggested_team_size( - functor, __suggested_vec_size); - - __run(functor); - } - - CrsType get_csrMat() { - return CrsType("csc2csr", __nrows, __ncols, __nnz, __crs_vals, - __crs_row_map, __crs_col_ids); - } -}; -} // namespace Impl -/// -/// \brief Converts a csc matrix to a CrsMatrix. -/// \tparam OrdinalType The view value type associated with the RowIdViewType -/// \tparam SizeType The type of nnz -/// \tparam ValViewType The values view type -/// \tparam RowIdViewType The row ids view type -/// \tparam ColMapViewType The column map view type -/// \param nrows The number of rows in the csc matrix -/// \param ncols The number of columns in the csc matrix -/// \param nnz The number of non-zeros in the csc matrix -/// \param vals The values view of the csc matrix -/// \param row_ids The row ids view of the csc matrix -/// \param col_map The column map view of the csc matrix -/// \return A KokkosSparse::CrsMatrix. -template -auto csc2csr(OrdinalType nrows, OrdinalType ncols, SizeType nnz, - ValViewType vals, RowIdViewType row_ids, ColMapViewType col_map, - int league_size) { - using Csc2csrType = Impl::Csc2Csr; - Csc2csrType csc2Csr(nrows, ncols, nnz, vals, row_ids, col_map, league_size); - return csc2Csr.get_csrMat(); -} -} // namespace KokkosSparse -#endif // _KOKKOSSPARSE_CSC2CSR_HPP diff --git a/sparse/unit_test/Test_Sparse.hpp b/sparse/unit_test/Test_Sparse.hpp index cde0ede5e3..a9562dff39 100644 --- a/sparse/unit_test/Test_Sparse.hpp +++ b/sparse/unit_test/Test_Sparse.hpp @@ -22,8 +22,9 @@ #include "Test_Sparse_trsv.hpp" #include "Test_Sparse_par_ilut.hpp" #include "Test_Sparse_Transpose.hpp" -#include "Test_Sparse_TestUtils_RandCscMat.hpp" -#include "Test_Sparse_csc2csr.hpp" +#include "Test_Sparse_TestUtils_RandCsMat.hpp" +#include "Test_Sparse_ccs2crs.hpp" +#include "Test_Sparse_crs2ccs.hpp" // TPL specific tests, these require // particular pairs of backend and TPL diff --git a/sparse/unit_test/Test_Sparse_TestUtils_RandCscMat.hpp b/sparse/unit_test/Test_Sparse_TestUtils_RandCsMat.hpp similarity index 62% rename from sparse/unit_test/Test_Sparse_TestUtils_RandCscMat.hpp rename to sparse/unit_test/Test_Sparse_TestUtils_RandCsMat.hpp index fc33f9f08b..07fe611cba 100644 --- a/sparse/unit_test/Test_Sparse_TestUtils_RandCscMat.hpp +++ b/sparse/unit_test/Test_Sparse_TestUtils_RandCsMat.hpp @@ -46,19 +46,25 @@ namespace Test { template -void doCscMat(size_t m, size_t n, ScalarType min_val, ScalarType max_val) { +void doCsMat(size_t m, size_t n, ScalarType min_val, ScalarType max_val) { auto expected_min = ScalarType(1.0); int64_t expected_nnz = 0; - RandCscMat cm(m, n, min_val, max_val); + RandCsMatrix cm(m, n, min_val, max_val); for (int64_t i = 0; i < cm.get_nnz(); ++i) ASSERT_GE(cm(i), expected_min) << cm.info; - for (int64_t j = 0; j < cm.get_n(); ++j) { - for (int64_t i = 0; i < cm.get_col_len(j); ++i) - ASSERT_FLOAT_EQ(cm(cm.get_col_start(j) + i), cm(expected_nnz + i)) - << cm.info; - expected_nnz += cm.get_col_len(j); + auto map_d = cm.get_map(); + auto map = Kokkos::create_mirror_view(map_d); + Kokkos::deep_copy(map, map_d); + + for (int64_t j = 0; j < cm.get_dim1(); ++j) { + int64_t row_len = j < static_cast(m) ? (map(j + 1) - map(j)) : 0; + for (int64_t i = 0; i < row_len; ++i) { + int64_t row_start = j < static_cast(m) ? map(j) : 0; + ASSERT_FLOAT_EQ(cm(row_start + i), cm(expected_nnz + i)) << cm.info; + } + expected_nnz += row_len; } ASSERT_EQ(cm.get_nnz(), expected_nnz) << cm.info; @@ -66,40 +72,40 @@ void doCscMat(size_t m, size_t n, ScalarType min_val, ScalarType max_val) { auto vals = cm.get_vals(); ASSERT_EQ(vals.extent(0), cm.get_nnz() + 1) << cm.info; - auto row_ids = cm.get_row_ids(); - ASSERT_EQ(row_ids.extent(0), cm.get_n() * cm.get_m() + 1) << cm.info; + auto row_ids = cm.get_ids(); + ASSERT_EQ(row_ids.extent(0), cm.get_dim1() * cm.get_dim2() + 1) << cm.info; - auto col_map = cm.get_col_map(); - ASSERT_EQ(col_map.extent(0), cm.get_n() + 1); + auto col_map = cm.get_map(); + ASSERT_EQ(col_map.extent(0), cm.get_dim1() + 1); } template -void doAllCscMat(size_t m, size_t n) { +void doAllCsMat(size_t m, size_t n) { int min = 1, max = 10; - // Verify that CscMax is constructed properly. - doCscMat(m, n, min, max); - doCscMat(m, n, min, max); + // Verify that CsMax is constructed properly. + doCsMat(m, n, min, max); + doCsMat(m, n, min, max); - doCscMat(m, n, min, max); - doCscMat(m, n, min, max); + doCsMat(m, n, min, max); + doCsMat(m, n, min, max); - // Verify that CscMax can be instantiated with complex types. - RandCscMat, Kokkos::LayoutLeft, ExeSpaceType> cmcf( + // Verify that CsMat can be instantiated with complex types. + RandCsMatrix, Kokkos::LayoutLeft, ExeSpaceType> cmcf( m, n, min, max); - RandCscMat, Kokkos::LayoutRight, ExeSpaceType> cmcd( + RandCsMatrix, Kokkos::LayoutRight, ExeSpaceType> cmcd( m, n, min, max); } -// Test randomly generated csc matrices -TEST_F(TestCategory, sparse_randcscmat) { +// Test randomly generated Cs matrices +TEST_F(TestCategory, sparse_randcsmat) { // Square cases - for (int dim = 1; dim < 1024; dim *= 4) doAllCscMat(dim, dim); + for (int dim = 1; dim < 1024; dim *= 4) doAllCsMat(dim, dim); // Non-square cases for (int dim = 1; dim < 1024; dim *= 4) { - doAllCscMat(dim * 3, dim); - doAllCscMat(dim, dim * 3); + doAllCsMat(dim * 3, dim); + doAllCsMat(dim, dim * 3); } } } // namespace Test \ No newline at end of file diff --git a/sparse/unit_test/Test_Sparse_block_gauss_seidel.hpp b/sparse/unit_test/Test_Sparse_block_gauss_seidel.hpp index c250af361f..38c806ddf9 100644 --- a/sparse/unit_test/Test_Sparse_block_gauss_seidel.hpp +++ b/sparse/unit_test/Test_Sparse_block_gauss_seidel.hpp @@ -177,7 +177,6 @@ void test_block_gauss_seidel_rank1(lno_t numRows, size_type nnz, using crsMat_t = typename KokkosSparse::CrsMatrix; using MatrixConverter = KokkosSparse::Impl::MatrixConverter; - typedef typename device::execution_space exec_space; typedef typename crsMat_t::StaticCrsGraphType graph_t; typedef typename crsMat_t::values_type::non_const_type scalar_view_t; diff --git a/sparse/unit_test/Test_Sparse_ccs2crs.hpp b/sparse/unit_test/Test_Sparse_ccs2crs.hpp new file mode 100644 index 0000000000..6d9b45eb99 --- /dev/null +++ b/sparse/unit_test/Test_Sparse_ccs2crs.hpp @@ -0,0 +1,195 @@ +/* +//@HEADER +// ************************************************************************ +// +// Kokkos v. 3.0 +// Copyright (2020) National Technology & Engineering +// Solutions of Sandia, LLC (NTESS). +// +// Under the terms of Contract DE-NA0003525 with NTESS, +// the U.S. Government retains certain rights in this software. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact Siva Rajamanickam (srajama@sandia.gov) +// +// ************************************************************************ +//@HEADER +*/ + +#include "KokkosSparse_ccs2crs.hpp" +#include "KokkosSparse_crs2ccs.hpp" +#include "KokkosKernels_TestUtils.hpp" + +namespace Test { +template +void check_crs_matrix(CrsType crsMat, CcsType ccsMat) { + auto ccs_row_ids_d = ccsMat.get_ids(); + auto ccs_col_map_d = ccsMat.get_map(); + auto ccs_vals_d = ccsMat.get_vals(); + + using ViewTypeRowIds = decltype(ccs_row_ids_d); + using ViewTypeColMap = decltype(ccs_col_map_d); + using ViewTypeVals = decltype(ccs_vals_d); + + // Copy to host + typename ViewTypeRowIds::HostMirror ccs_row_ids = + Kokkos::create_mirror_view(ccs_row_ids_d); + Kokkos::deep_copy(ccs_row_ids, ccs_row_ids_d); + typename ViewTypeColMap::HostMirror ccs_col_map = + Kokkos::create_mirror_view(ccs_col_map_d); + Kokkos::deep_copy(ccs_col_map, ccs_col_map_d); + typename ViewTypeVals::HostMirror ccs_vals = + Kokkos::create_mirror_view(ccs_vals_d); + Kokkos::deep_copy(ccs_vals, ccs_vals_d); + + auto crs_col_ids_d = crsMat.graph.entries; + auto crs_row_map_d = crsMat.graph.row_map; + auto crs_vals_d = crsMat.values; + + using ViewTypeCrsColIds = decltype(crs_col_ids_d); + using ViewTypeCrsRowMap = decltype(crs_row_map_d); + using ViewTypeCrsVals = decltype(crs_vals_d); + + // Copy to host + typename ViewTypeCrsColIds::HostMirror crs_col_ids = + Kokkos::create_mirror_view(crs_col_ids_d); + Kokkos::deep_copy(crs_col_ids, crs_col_ids_d); + typename ViewTypeCrsRowMap::HostMirror crs_row_map = + Kokkos::create_mirror_view(crs_row_map_d); + Kokkos::deep_copy(crs_row_map, crs_row_map_d); + typename ViewTypeCrsVals::HostMirror crs_vals = + Kokkos::create_mirror_view(crs_vals_d); + Kokkos::deep_copy(crs_vals, crs_vals_d); + + Kokkos::fence(); + + for (int j = 0; j < ccsMat.get_dim1(); ++j) { + auto col_start = ccs_col_map(j); + auto col_len = ccs_col_map(j + 1) - col_start; + + for (int k = 0; k < col_len; ++k) { + auto i = col_start + k; + + auto row_start = crs_row_map(ccs_row_ids(i)); + auto row_len = crs_row_map(ccs_row_ids(i) + 1) - row_start; + auto row_end = row_start + row_len; + + if (row_len == 0) continue; + + // Linear search for corresponding element in crs matrix + int l = row_start; + while (l < row_end && crs_col_ids(l) != j) { + ++l; + } + + if (l == row_end) + FAIL() << "crs element at (i: " << ccs_row_ids(i) << ", j: " << j + << ") not found!" << std::endl; + + ASSERT_EQ(ccs_vals(i), crs_vals(l)) + << "(i: " << ccs_row_ids(i) << ", j: " << j << ")" << std::endl; + } + } +} +template +void doCcs2Crs(size_t m, size_t n, ScalarType min_val, ScalarType max_val, + bool fully_sparse = false) { + RandCsMatrix ccsMat( + n, m, min_val, max_val, fully_sparse); + + auto crsMat = KokkosSparse::ccs2crs(ccsMat.get_dim2(), ccsMat.get_dim1(), + ccsMat.get_nnz(), ccsMat.get_vals(), + ccsMat.get_map(), ccsMat.get_ids()); + + check_crs_matrix(crsMat, ccsMat); +} + +template +void doAllScalarsCcs2Crs(size_t m, size_t n, int min, int max) { + doCcs2Crs(m, n, min, max); + doCcs2Crs(m, n, min, max); + doCcs2Crs, LayoutType, ExeSpaceType>(m, n, min, max); + doCcs2Crs, LayoutType, ExeSpaceType>(m, n, min, max); +} + +template +void doAllLayoutsCcs2Crs(size_t m, size_t n, int min, int max) { + doAllScalarsCcs2Crs(m, n, min, max); + doAllScalarsCcs2Crs(m, n, min, max); +} + +template +void doAllCcs2crs(size_t m, size_t n) { + int min = 1, max = 10; + doAllLayoutsCcs2Crs(m, n, min, max); +} + +TEST_F(TestCategory, sparse_ccs2crs) { + uint64_t ticks = + std::chrono::high_resolution_clock::now().time_since_epoch().count() % + UINT32_MAX; + std::srand(ticks); + + // Empty cases + doCcs2Crs(1, 0, 1, 10); + doCcs2Crs(0, 1, 1, 10); + + doCcs2Crs(1, 0, 1, 10); + doCcs2Crs(0, 1, 1, 10); + + doCcs2Crs(0, 0, 1, 10); + doCcs2Crs(0, 0, 1, 10); + + // Square cases + for (size_t i = 4; i < 1024; i *= 4) { + size_t dim = (std::rand() % 511) + 1; + doAllCcs2crs(dim, dim); + } + + // Non-square cases + for (size_t i = 1; i < 1024; i *= 4) { + size_t m = (std::rand() % 511) + 1; + size_t n = (std::rand() % 511) + 1; + while (n == m) n = (std::rand() % 511) + 1; + doAllCcs2crs(m, n); + } + + // Fully sparse cases + doCcs2Crs(5, 5, 1, 10, true); + doCcs2Crs(50, 10, 10, 100, true); + + // Test the convenience wrapper that accepts a ccs matrix + RandCsMatrix csMat(2, 2, 10, 10, + false); + auto ccsMatrix = crs2ccs(csMat.get_dim1(), csMat.get_dim2(), csMat.get_nnz(), + csMat.get_vals(), csMat.get_map(), csMat.get_ids()); + auto crsMatrix = ccs2crs(ccsMatrix); + check_crs_matrix(crsMatrix, csMat); +} +} // namespace Test \ No newline at end of file diff --git a/sparse/unit_test/Test_Sparse_crs2ccs.hpp b/sparse/unit_test/Test_Sparse_crs2ccs.hpp new file mode 100644 index 0000000000..b915573c81 --- /dev/null +++ b/sparse/unit_test/Test_Sparse_crs2ccs.hpp @@ -0,0 +1,194 @@ +/* +//@HEADER +// ************************************************************************ +// +// Kokkos v. 3.0 +// Copyright (2020) National Technology & Engineering +// Solutions of Sandia, LLC (NTESS). +// +// Under the terms of Contract DE-NA0003525 with NTESS, +// the U.S. Government retains certain rights in this software. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact Siva Rajamanickam (srajama@sandia.gov) +// +// ************************************************************************ +//@HEADER +*/ + +#include "KokkosSparse_crs2ccs.hpp" +#include "KokkosSparse_ccs2crs.hpp" +#include "KokkosKernels_TestUtils.hpp" + +namespace Test { +template +void check_ccs_matrix(CcsType ccsMat, CrsType crsMat) { + auto crs_col_ids_d = crsMat.get_ids(); + auto crs_row_map_d = crsMat.get_map(); + auto crs_vals_d = crsMat.get_vals(); + + using ViewTypeRowIds = decltype(crs_col_ids_d); + using ViewTypeColMap = decltype(crs_row_map_d); + using ViewTypeVals = decltype(crs_vals_d); + + // Copy to host + typename ViewTypeRowIds::HostMirror crs_col_ids = + Kokkos::create_mirror_view(crs_col_ids_d); + Kokkos::deep_copy(crs_col_ids, crs_col_ids_d); + typename ViewTypeColMap::HostMirror crs_row_map = + Kokkos::create_mirror_view(crs_row_map_d); + Kokkos::deep_copy(crs_row_map, crs_row_map_d); + typename ViewTypeVals::HostMirror crs_vals = + Kokkos::create_mirror_view(crs_vals_d); + Kokkos::deep_copy(crs_vals, crs_vals_d); + + auto ccs_row_ids_d = ccsMat.graph.entries; + auto ccs_col_map_d = ccsMat.graph.col_map; + auto ccs_vals_d = ccsMat.values; + + using ViewTypeCrsColIds = decltype(ccs_row_ids_d); + using ViewTypeCrsRowMap = decltype(ccs_col_map_d); + using ViewTypeCrsVals = decltype(ccs_vals_d); + + // Copy to host + typename ViewTypeCrsColIds::HostMirror ccs_row_ids = + Kokkos::create_mirror_view(ccs_row_ids_d); + Kokkos::deep_copy(ccs_row_ids, ccs_row_ids_d); + typename ViewTypeCrsRowMap::HostMirror ccs_col_map = + Kokkos::create_mirror_view(ccs_col_map_d); + Kokkos::deep_copy(ccs_col_map, ccs_col_map_d); + typename ViewTypeCrsVals::HostMirror ccs_vals = + Kokkos::create_mirror_view(ccs_vals_d); + Kokkos::deep_copy(ccs_vals, ccs_vals_d); + + for (int j = 0; j < crsMat.get_dim2(); ++j) { + auto col_start = ccs_col_map(j); + auto col_len = ccs_col_map(j + 1) - col_start; + + for (int k = 0; k < col_len; ++k) { + auto i = col_start + k; + + auto row_start = crs_row_map(ccs_row_ids(i)); + auto row_len = crs_row_map(ccs_row_ids(i) + 1) - row_start; + auto row_end = row_start + row_len; + + if (row_len == 0) continue; + + // Linear search for corresponding element in crs matrix + int l = row_start; + while (l < row_end && crs_col_ids(l) != j) { + ++l; + } + + if (l == row_end) + FAIL() << "ccs element at (i: " << ccs_row_ids(i) << ", j: " << j + << ") not found!" << std::endl; + + ASSERT_EQ(ccs_vals(i), crs_vals(l)) + << "(i: " << ccs_row_ids(i) << ", j: " << j << ")" << std::endl; + } + } +} + +template +void doCrs2Ccs(size_t m, size_t n, ScalarType min_val, ScalarType max_val, + bool fully_sparse = false) { + RandCsMatrix crsMat( + m, n, min_val, max_val, fully_sparse); + + auto ccsMat = KokkosSparse::crs2ccs(crsMat.get_dim1(), crsMat.get_dim2(), + crsMat.get_nnz(), crsMat.get_vals(), + crsMat.get_map(), crsMat.get_ids()); + + check_ccs_matrix(ccsMat, crsMat); +} + +template +void doAllScalarsCrs2Ccs(size_t m, size_t n, int min, int max) { + doCrs2Ccs(m, n, min, max); + doCrs2Ccs(m, n, min, max); + doCrs2Ccs, LayoutType, ExeSpaceType>(m, n, min, max); + doCrs2Ccs, LayoutType, ExeSpaceType>(m, n, min, max); +} + +template +void doAllLayoutsCrs2Ccs(size_t m, size_t n, int min, int max) { + doAllScalarsCrs2Ccs(m, n, min, max); + doAllScalarsCrs2Ccs(m, n, min, max); +} + +template +void doAllCrs2Ccs(size_t m, size_t n) { + int min = 1, max = 10; + doAllLayoutsCrs2Ccs(m, n, min, max); +} + +TEST_F(TestCategory, sparse_crs2ccs) { + uint64_t ticks = + std::chrono::high_resolution_clock::now().time_since_epoch().count() % + UINT32_MAX; + std::srand(ticks); + + // Empty cases + doCrs2Ccs(1, 0, 1, 10); + doCrs2Ccs(0, 1, 1, 10); + + doCrs2Ccs(1, 0, 1, 10); + doCrs2Ccs(0, 1, 1, 10); + + doCrs2Ccs(0, 0, 1, 10); + doCrs2Ccs(0, 0, 1, 10); + + // Square cases + for (size_t i = 4; i < 1024; i *= 4) { + size_t dim = (std::rand() % 511) + 1; + doAllCrs2Ccs(dim, dim); + } + + // Non-square cases + for (size_t i = 1; i < 1024; i *= 4) { + size_t m = (std::rand() % 511) + 1; + size_t n = (std::rand() % 511) + 1; + while (n == m) n = (std::rand() % 511) + 1; + doAllCrs2Ccs(m, n); + } + + // Fully sparse cases + doCrs2Ccs(5, 5, 1, 10, true); + doCrs2Ccs(50, 10, 10, 100, true); + + // Test the convenience wrapper that accepts a crs matrix + RandCsMatrix csMat(2, 2, 10, 10, + false); + auto crsMatrix = ccs2crs(csMat.get_dim2(), csMat.get_dim1(), csMat.get_nnz(), + csMat.get_vals(), csMat.get_map(), csMat.get_ids()); + auto ccsMatrix = crs2ccs(crsMatrix); + check_ccs_matrix(ccsMatrix, csMat); +} +} // namespace Test \ No newline at end of file diff --git a/sparse/unit_test/Test_Sparse_csc2csr.hpp b/sparse/unit_test/Test_Sparse_csc2csr.hpp index e7d2ad868e..fc8e3186f7 100644 --- a/sparse/unit_test/Test_Sparse_csc2csr.hpp +++ b/sparse/unit_test/Test_Sparse_csc2csr.hpp @@ -49,16 +49,15 @@ namespace Test { template void doCsc2Csr(size_t m, size_t n, ScalarType min_val, ScalarType max_val, bool fully_sparse = false) { - RandCscMat cscMat( - m, n, min_val, max_val, fully_sparse); - constexpr int league_size = 32; + RandCsMatrix cscMat( + n, m, min_val, max_val, fully_sparse); - auto csrMat = KokkosSparse::csc2csr( - cscMat.get_m(), cscMat.get_n(), cscMat.get_nnz(), cscMat.get_vals(), - cscMat.get_row_ids(), cscMat.get_col_map(), league_size); + auto csrMat = KokkosSparse::csc2csr(cscMat.get_dim2(), cscMat.get_dim1(), + cscMat.get_nnz(), cscMat.get_vals(), + cscMat.get_map(), cscMat.get_ids()); - auto csc_row_ids_d = cscMat.get_row_ids(); - auto csc_col_map_d = cscMat.get_col_map(); + auto csc_row_ids_d = cscMat.get_ids(); + auto csc_col_map_d = cscMat.get_map(); auto csc_vals_d = cscMat.get_vals(); using ViewTypeRowIds = decltype(csc_row_ids_d); @@ -97,7 +96,7 @@ void doCsc2Csr(size_t m, size_t n, ScalarType min_val, ScalarType max_val, Kokkos::fence(); - for (int j = 0; j < cscMat.get_n(); ++j) { + for (int j = 0; j < cscMat.get_dim1(); ++j) { auto col_start = csc_col_map(j); auto col_len = csc_col_map(j + 1) - col_start; @@ -147,17 +146,36 @@ void doAllCsc2csr(size_t m, size_t n) { } TEST_F(TestCategory, sparse_csc2csr) { + uint64_t ticks = + std::chrono::high_resolution_clock::now().time_since_epoch().count() % + UINT32_MAX; + std::srand(ticks); + + // Empty cases + doCsc2Csr(1, 0, 1, 10); + doCsc2Csr(0, 1, 1, 10); + + doCsc2Csr(1, 0, 1, 10); + doCsc2Csr(0, 1, 1, 10); + + doCsc2Csr(0, 0, 1, 10); + doCsc2Csr(0, 0, 1, 10); + // Square cases - for (size_t dim = 4; dim < 1024; dim *= 4) + for (size_t i = 4; i < 1024; i *= 4) { + size_t dim = (std::rand() % 511) + 1; doAllCsc2csr(dim, dim); + } // Non-square cases - for (size_t dim = 1; dim < 1024; dim *= 4) { - doAllCsc2csr(dim * 3, dim); - doAllCsc2csr(dim, dim * 3); + for (size_t i = 1; i < 1024; i *= 4) { + size_t m = (std::rand() % 511) + 1; + size_t n = (std::rand() % 511) + 1; + while (n == m) n = (std::rand() % 511) + 1; + doAllCsc2csr(m, n); } - // Fully sparse + // Fully sparse cases doCsc2Csr(5, 5, 1, 10, true); doCsc2Csr(50, 10, 10, 100, true); } diff --git a/test_common/KokkosKernels_MatrixConverter.cpp b/test_common/KokkosKernels_MatrixConverter.cpp index a56c8788aa..1b9c05e457 100644 --- a/test_common/KokkosKernels_MatrixConverter.cpp +++ b/test_common/KokkosKernels_MatrixConverter.cpp @@ -251,7 +251,7 @@ int main(int argc, char *argv[]) { cols_view_t new_entries("new_rowmap", a_crsmat.nnz()); values_view_t new_values("new_rowmap", a_crsmat.nnz()); - KokkosKernels::Impl::transpose_matrix< + KokkosSparse::Impl::transpose_matrix< c_row_map_view_t, c_cols_view_t, c_values_view_t, row_map_view_t, cols_view_t, values_view_t, row_map_view_t, MyExecSpace>( a_crsmat.numRows(), a_crsmat.numCols(), a_crsmat.graph.row_map, diff --git a/test_common/KokkosKernels_TestUtils.hpp b/test_common/KokkosKernels_TestUtils.hpp index d534695afd..350e3a21bf 100644 --- a/test_common/KokkosKernels_TestUtils.hpp +++ b/test_common/KokkosKernels_TestUtils.hpp @@ -548,42 +548,47 @@ int string_compare_no_case(const char* str1, const char* str2) { return strcmp(str1_s.c_str(), str2_s.c_str()); } -/// /brief Csc matrix class for testing purposes. +/// /brief Cs (Compressed Sparse) matrix class for testing purposes. +/// This class is for testing purposes only and will generate a random +/// Crs / Ccs matrix when instantiated. The class is intentionally written +/// without the use of "row" and "column" member names. +/// dim1 refers to either rows for Crs matrix or columns for a Ccs matrix. +/// dim2 refers to either columns for a Crs matrix or rows for a Ccs matrix. /// \tparam ScalarType /// \tparam LayoutType /// \tparam ExeSpaceType template -class RandCscMat { +class RandCsMatrix { private: - using ValViewTypeD = Kokkos::View; - using RowIdViewTypeD = Kokkos::View; - using ColMapViewTypeD = Kokkos::View; - int64_t __nrows; - int64_t __ncols; + using ValViewTypeD = Kokkos::View; + using IdViewTypeD = Kokkos::View; + using MapViewTypeD = Kokkos::View; + int64_t __dim2; + int64_t __dim1; int64_t __nnz = 0; - ColMapViewTypeD __col_map_d; - RowIdViewTypeD __row_ids_d; + MapViewTypeD __map_d; + IdViewTypeD __ids_d; ValViewTypeD __vals_d; - using ColMapViewTypeH = typename ColMapViewTypeD::HostMirror; - using RowIdViewTypeH = typename RowIdViewTypeD::HostMirror; - using ValViewTypeH = typename ValViewTypeD::HostMirror; - ColMapViewTypeH __col_map; - RowIdViewTypeH __row_ids; + using MapViewTypeH = typename MapViewTypeD::HostMirror; + using IdViewTypeH = typename IdViewTypeD::HostMirror; + using ValViewTypeH = typename ValViewTypeD::HostMirror; + MapViewTypeH __map; + IdViewTypeH __ids; ValViewTypeH __vals; bool __fully_sparse; - /// Generates a random column map where: - /// 1. __col_map(i) is in [__row_ids.data(), &row_ids.data()[nnz - 1] - /// 2. __col_map(i) > col_map(i - 1) for i > 1 - /// 3. __col_map(i) == col_map(j) iff __col_map(i) == col_map(j) == nullptr - /// 4. __col_map(i) - col_map(i - 1) is in [0, m] - void __populate_random_csc_mat(uint64_t ticks) { + /// Generates a random map where (using Ccs terminology): + /// 1. __map(i) is in [__ids.data(), &row_ids.data()[nnz - 1] + /// 2. __map(i) > col_map(i - 1) for i > 1 + /// 3. __map(i) == col_map(j) iff __map(i) == col_map(j) == nullptr + /// 4. __map(i) - col_map(i - 1) is in [0, m] + void __populate_random_cs_mat(uint64_t ticks) { std::srand(ticks); - for (int64_t col_idx = 0; col_idx < __ncols; col_idx++) { - int64_t r = std::rand() % (__nrows + 1); - if (r == 0 || __fully_sparse) { // 100% sparse column - __col_map(col_idx) = __nnz; - } else { // sparse column with r elements + for (int64_t col_idx = 0; col_idx < __dim1; col_idx++) { + int64_t r = std::rand() % (__dim2 + 1); + if (r == 0 || __fully_sparse) { // 100% sparse vector + __map(col_idx) = __nnz; + } else { // sparse vector with r elements // Populate r row ids std::vector v(r); @@ -591,26 +596,26 @@ class RandCscMat { std::shuffle(v.begin(), v.end(), std::mt19937(std::random_device()())); - for (int64_t i = 0; i < r; i++) __row_ids(i + __nnz) = v.at(i); + for (int64_t i = 0; i < r; i++) __ids(i + __nnz) = v.at(i); // Point to new column and accumulate number of non zeros - __col_map(col_idx) = __nnz; + __map(col_idx) = __nnz; __nnz += r; } } - // last entry in map points to end of row id list - __col_map(__ncols) = __nnz; + // last entry in map points to end of id list + __map(__dim1) = __nnz; // Copy to device - Kokkos::deep_copy(__col_map_d, __col_map); - Kokkos::deep_copy(__row_ids_d, __row_ids); + Kokkos::deep_copy(__map_d, __map); + Kokkos::deep_copy(__ids_d, __ids); ExeSpaceType().fence(); } template T __getter_copy_helper(T src) { - T dst(std::string("RandCscMat.") + typeid(T).name() + " copy", + T dst(std::string("RandCsMatrix.") + typeid(T).name() + " copy", src.extent(0)); Kokkos::deep_copy(dst, src); ExeSpaceType().fence(); @@ -619,36 +624,36 @@ class RandCscMat { public: std::string info; - /// Constructs a random csc matrix. - /// \param m The number of rows. - /// \param n The number of columns. + /// Constructs a random cs matrix. + /// \param dim1 The first dimension: rows for Crs or columns for Ccs + /// \param dim2 The second dimension: columns for Crs or rows for Ccs /// \param min_val The minimum scalar value in the matrix. /// \param max_val The maximum scalar value in the matrix. - RandCscMat(int64_t m, int64_t n, ScalarType min_val, ScalarType max_val, - bool fully_sparse = false) { - __ncols = n; - __nrows = m; + RandCsMatrix(int64_t dim1, int64_t dim2, ScalarType min_val, + ScalarType max_val, bool fully_sparse = false) { + __dim1 = dim1; + __dim2 = dim2; __fully_sparse = fully_sparse; - __col_map_d = ColMapViewTypeD("RandCscMat.ColMapViewType", __ncols + 1); - __col_map = Kokkos::create_mirror_view(__col_map_d); - __row_ids_d = RowIdViewTypeD("RandCscMat.RowIdViewType", - m * n + 1); // over-allocated - __row_ids = Kokkos::create_mirror_view(__row_ids_d); + __map_d = MapViewTypeD("RandCsMatrix.ColMapViewType", __dim1 + 1); + __map = Kokkos::create_mirror_view(__map_d); + __ids_d = IdViewTypeD("RandCsMatrix.RowIdViewType", + dim2 * dim1 + 1); // over-allocated + __ids = Kokkos::create_mirror_view(__ids_d); uint64_t ticks = std::chrono::high_resolution_clock::now().time_since_epoch().count() % UINT32_MAX; info = std::string( - std::string("RandCscMat<") + typeid(ScalarType).name() + ", " + + std::string("RandCsMatrix<") + typeid(ScalarType).name() + ", " + typeid(LayoutType).name() + ", " + typeid(ExeSpaceType).name() + ">(" + - std::to_string(m) + ", " + std::to_string(n) + + std::to_string(dim2) + ", " + std::to_string(dim1) + "...): rand seed: " + std::to_string(ticks) + ", fully sparse: " + (__fully_sparse ? "true" : "false") + "\n"); Kokkos::Random_XorShift64_Pool random(ticks); - __populate_random_csc_mat(ticks); + __populate_random_cs_mat(ticks); - __vals_d = ValViewTypeD("RandCscMat.ValViewType", __nnz + 1); + __vals_d = ValViewTypeD("RandCsMatrix.ValViewType", __nnz + 1); __vals = Kokkos::create_mirror_view(__vals_d); Kokkos::fill_random(__vals, random, min_val, max_val); // random scalars Kokkos::fence(); @@ -661,17 +666,15 @@ class RandCscMat { // O(c), where c is a constant. ScalarType operator()(int64_t idx) { return __vals(idx); } - int64_t get_nnz() { return __nnz; } - int64_t get_m() { return __nrows; } - int64_t get_n() { return __ncols; } - int64_t get_col_len(int64_t j) { - return j < __ncols ? (__col_map(j + 1) - __col_map(j)) : 0; - } - int64_t get_col_start(int64_t j) { return j < __ncols ? __col_map(j) : 0; } + // dimension2: This is either columns for a Crs matrix or rows for a Ccs + // matrix. + int64_t get_dim2() { return __dim2; } + // dimension1: This is either rows for Crs matrix or columns for a Ccs matrix. + int64_t get_dim1() { return __dim1; } ValViewTypeD get_vals() { return __getter_copy_helper(__vals_d); } - RowIdViewTypeD get_row_ids() { return __getter_copy_helper(__row_ids_d); } - ColMapViewTypeD get_col_map() { return __getter_copy_helper(__col_map_d); } + IdViewTypeD get_ids() { return __getter_copy_helper(__ids_d); } + MapViewTypeD get_map() { return __getter_copy_helper(__map_d); } }; /// \brief Randomly shuffle the entries in each row (col) of a Crs (Ccs) matrix.