Files
TheRock/rocm-libraries/projects/rocsparse/clients/common/rocsparse_clients_spmat_descr.cpp
T
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

470 lines
20 KiB
C++

/* ************************************************************************
* Copyright (C) 2026 Advanced Micro Devices, Inc. All rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* ************************************************************************ */
#include "rocsparse_clients_spmat_descr.hpp"
template <class... Ts>
struct select_lambdas : Ts...
{
using Ts::operator()...;
};
template <class... Ts>
select_lambdas(Ts...) -> select_lambdas<Ts...>;
template <typename T, typename I, typename J>
const device_dense_vector<T>& rocsparse_clients::spmat_descr<T, I, J>::get_device_values() const
{
return std::visit(
[](const auto& d) -> const auto& { return d.device().val; }, this->m_data);
}
template <typename T, typename I, typename J>
const host_vector<T>& rocsparse_clients::spmat_descr<T, I, J>::get_host_values() const
{
return std::visit(
[](const auto& d) -> const auto& { return d.host().val; }, this->m_data);
}
template <typename T, typename I, typename J>
device_dense_vector<T>& rocsparse_clients::spmat_descr<T, I, J>::get_device_values()
{
return std::visit(
[](auto& d) -> auto& { return d.device().val; }, this->m_data);
}
template <typename T, typename I, typename J>
host_vector<T>& rocsparse_clients::spmat_descr<T, I, J>::get_host_values()
{
return std::visit(
[](auto& d) -> auto& { return d.host().val; }, this->m_data);
}
template <typename T, typename I, typename J>
int64_t rocsparse_clients::spmat_descr<T, I, J>::get_batch_count() const
{
return this->m_batch_count;
}
template <typename T, typename I, typename J>
rocsparse_format rocsparse_clients::spmat_descr<T, I, J>::get_format() const
{
return this->m_format;
}
template <typename T, typename I, typename J>
int64_t rocsparse_clients::spmat_descr<T, I, J>::get_stride() const
{
return this->m_batch_val_stride;
}
template <typename T, typename I, typename J>
rocsparse_clients::spmat_descr<T, I, J>::~spmat_descr()
{
if(this->m_local_descr != nullptr)
{
delete this->m_local_descr;
this->m_local_descr = nullptr;
}
}
template <typename T>
void batch_count_near_check(int64_t batch_count,
int64_t data_size,
host_dense_vector<T>& host_data,
int64_t host_data_stride,
device_dense_vector<T>& device_data,
int64_t device_data_stride,
const int64_t* __restrict__ symbolic,
const int64_t* __restrict__ numeric)
{
for(int64_t i = 0; i < batch_count; ++i)
{
if((symbolic[i] != -1) || (numeric[i] != -1))
{
CHECK_HIP_ERROR(
hipMemset(&device_data[device_data_stride * i], 0, sizeof(T) * data_size));
std::ignore = memset(&host_data[host_data_stride * i], 0, sizeof(T) * data_size);
}
}
host_data.near_check(device_data);
}
template <typename T>
void batch_count_near_check(int64_t batch_count,
int64_t data_size,
host_vector<T>& host_data,
int64_t host_data_stride,
device_dense_vector<T>& device_data,
int64_t device_data_stride,
const int64_t* __restrict__ symbolic,
const int64_t* __restrict__ numeric)
{
for(int64_t i = 0; i < batch_count; ++i)
{
if((symbolic[i] != -1) || (numeric[i] != -1))
{
CHECK_HIP_ERROR(
hipMemset(&device_data[device_data_stride * i], 0, sizeof(T) * data_size));
std::ignore = memset(&host_data[host_data_stride * i], 0, sizeof(T) * data_size);
}
}
host_data.near_check(device_data);
}
template <typename T, typename I, typename J>
void rocsparse_clients::spmat_descr<T, I, J>::near_check_values(
const host_dense_vector<int64_t>& symbolic, const host_dense_vector<int64_t>& numeric)
{
ROCSPARSE_CLIENTS_ROUTINE_TRACE;
auto& host_values = this->get_host_values();
auto& device_values = this->get_device_values();
if(this->m_batch_count == 1)
{
if((symbolic[0] == -1) && (numeric[0] == -1))
{
host_values.near_check(device_values);
}
}
else
{
batch_count_near_check(this->m_batch_count,
this->get_size_values(),
host_values,
this->m_batch_val_stride,
device_values,
this->m_batch_val_stride,
symbolic,
numeric);
}
}
template <typename T, typename I, typename J>
bool rocsparse_clients::spmat_descr<T, I, J>::is_square() const
{
ROCSPARSE_CLIENTS_ROUTINE_TRACE;
return std::visit(
select_lambdas{
[](const coo_t& that) -> bool { return (that.host().m == that.host().n); },
[](const coo_aos_t& that) -> bool { return (that.host().m == that.host().n); },
[](const csr_t& that) -> bool { return (that.host().m == that.host().n); },
[](const csc_t& that) -> bool { return (that.host().m == that.host().n); },
[](const ell_t& that) -> bool { return (that.host().m == that.host().n); },
[](const bell_t& that) -> bool { return (that.host().m == that.host().n); },
[](const bsr_t& that) -> bool { return (that.host().mb == that.host().nb); },
[](const sell_t& that) -> bool { return (that.host().m == that.host().n); }},
this->m_data);
return true;
}
template <typename T, typename I, typename J>
void rocsparse_clients::spmat_descr<T, I, J>::reinit_values()
{
this->get_device_values().transfer_from(this->get_host_values());
}
template <typename T, typename I, typename J>
int64_t rocsparse_clients::spmat_descr<T, I, J>::get_nrows() const
{
ROCSPARSE_CLIENTS_ROUTINE_TRACE;
return std::visit(
select_lambdas{
[](const coo_t& that) -> int64_t { return that.host().m; },
[](const coo_aos_t& that) -> int64_t { return that.host().m; },
[](const csr_t& that) -> int64_t { return that.host().m; },
[](const csc_t& that) -> int64_t { return that.host().m; },
[](const ell_t& that) -> int64_t { return that.host().m; },
[](const bell_t& that) -> int64_t { return that.host().m; },
[](const bsr_t& that) -> int64_t { return that.host().mb * that.host().row_block_dim; },
[](const sell_t& that) -> int64_t { return that.host().m; },
},
this->m_data);
}
template <typename T, typename I, typename J>
int64_t rocsparse_clients::spmat_descr<T, I, J>::get_size_values() const
{
ROCSPARSE_CLIENTS_ROUTINE_TRACE;
return std::visit(
select_lambdas{
[](const coo_t& that) -> int64_t { return that.host().nnz; },
[](const coo_aos_t& that) -> int64_t { return that.host().nnz; },
[](const csr_t& that) -> int64_t { return that.host().nnz; },
[](const csc_t& that) -> int64_t { return that.host().nnz; },
[](const ell_t& that) -> int64_t { return that.host().m * that.host().width; },
[](const bell_t& that) -> int64_t {
return that.host().width * that.host().m * that.host().bdim * that.host().bdim;
},
[](const bsr_t& that) -> int64_t {
return that.host().nnzb * that.host().row_block_dim * that.host().col_block_dim;
},
[](const sell_t& that) -> int64_t { return that.host().sell_colval_size; },
},
this->m_data);
}
template <typename T, typename I, typename J>
int64_t rocsparse_clients::spmat_descr<T, I, J>::get_size_cols() const
{
ROCSPARSE_CLIENTS_ROUTINE_TRACE;
return std::visit(
select_lambdas{
[](const coo_t& that) -> int64_t { return that.host().nnz; },
[](const coo_aos_t& that) -> int64_t { return that.host().nnz; },
[](const csr_t& that) -> int64_t { return that.host().nnz; },
[](const csc_t& that) -> int64_t { return that.host().n + 1; },
[](const ell_t& that) -> int64_t { return that.host().m * that.host().width; },
[](const bell_t& that) -> int64_t { return that.host().width * that.host().m; },
[](const bsr_t& that) -> int64_t { return that.host().nnzb; },
[](const sell_t& that) -> int64_t { return that.host().sell_colval_size; },
},
this->m_data);
}
template <typename T, typename I, typename J>
int64_t rocsparse_clients::spmat_descr<T, I, J>::get_size_rows() const
{
ROCSPARSE_CLIENTS_ROUTINE_TRACE;
return std::visit(select_lambdas{
[](const coo_t& that) -> int64_t { return that.host().nnz; },
[](const coo_aos_t& that) -> int64_t { return that.host().nnz; },
[](const csr_t& that) -> int64_t { return that.host().m + 1; },
[](const csc_t& that) -> int64_t { return that.host().nnz; },
[](const ell_t& that) -> int64_t { return 0; },
[](const bell_t& that) -> int64_t { return 0; },
[](const bsr_t& that) -> int64_t { return that.host().mb + 1; },
[](const sell_t& that) -> int64_t {
return (that.host().m - 1) / that.host().sell_slice_size + 1;
},
},
this->m_data);
}
template <typename T, typename I, typename J>
rocsparse_clients::spmat_descr<T, I, J>::spmat_descr(const Arguments& arg,
int64_t batch_count,
bool full_rank)
: m_data(make_variant(arg.formatA))
{
ROCSPARSE_CLIENTS_ROUTINE_TRACE;
const rocsparse_format format = arg.formatA;
this->m_format = format;
this->init(arg, batch_count, full_rank);
}
template <typename T, typename I, typename J>
void rocsparse_clients::spmat_descr<T, I, J>::init(const Arguments& arg,
int64_t batch_count,
bool full_rank)
{
ROCSPARSE_CLIENTS_ROUTINE_TRACE;
//
// Build host matrix.
//
std::visit(
select_lambdas{[&](coo_t& that) {
const bool to_int = arg.timing ? false : true;
rocsparse_matrix_factory<T, I, I> matrix_factory(arg, to_int, full_rank);
matrix_factory.init_coo(that.host());
},
[&](csr_t& that) {
const bool to_int = arg.timing ? false : true;
rocsparse_matrix_factory<T, I, J> matrix_factory(arg, to_int, full_rank);
matrix_factory.init_csr(that.host());
},
[&](bsr_t& that) {
static constexpr bool toint = false;
rocsparse_matrix_factory<T, I, J> matrix_factory(arg, toint, false);
{
J M = arg.M;
J N = arg.N;
J block_dim = arg.block_dim;
rocsparse_direction direction = arg.direction;
J Mb = (M + block_dim - 1) / block_dim;
J Nb = (N + block_dim - 1) / block_dim;
auto& host = that.host();
I nnzb = arg.nnz;
matrix_factory.init_bsr(host.ptr,
host.ind,
host.val,
direction,
Mb,
Nb,
nnzb,
block_dim,
arg.baseA);
host.mb = Mb;
host.nb = Nb;
host.nnzb = nnzb;
host.row_block_dim = block_dim;
host.col_block_dim = block_dim;
host.block_direction = arg.direction;
host.base = arg.baseA;
}
},
[&](coo_aos_t& that) {
std::cerr << "handling coo_aos not yet implemented" << std::endl;
throw(rocsparse_status_not_implemented);
},
[&](csc_t& that) {
const bool to_int = arg.timing ? false : true;
rocsparse_matrix_factory<T, I, J> matrix_factory(arg, to_int, full_rank);
J m = arg.M;
J n = arg.N;
matrix_factory.init_csc(that.host(), m, n, arg.baseA);
},
[&](ell_t& that) {
std::cerr << "handling ell not yet implemented" << std::endl;
throw(rocsparse_status_not_implemented);
},
[&](bell_t& that) {
std::cerr << "handling bell not yet implemented" << std::endl;
throw(rocsparse_status_not_implemented);
},
[&](sell_t& that) {
std::cerr << "handling sell not yet implemented" << std::endl;
throw(rocsparse_status_not_implemented);
}},
this->m_data);
//
// Build device matrix.
//
std::visit(
[&](auto& that) {
auto& device = that.device();
device(that.host());
},
this->m_data);
const int64_t stride_shift = 0;
const double random_multiplier = 1.0e-6;
int64_t stride = 0;
this->m_batch_count = batch_count;
if(batch_count > 1)
{
auto& host_values = this->get_host_values();
const size_t host_values_size = host_values.size();
const size_t host_values_size_in_bytes = sizeof(T) * host_values_size;
stride = host_values_size + stride_shift;
this->m_batch_val_stride = stride;
host_dense_vector<char> buffer(host_values_size_in_bytes);
CHECK_HIP_ERROR(
hipMemcpy(buffer, host_values, host_values_size_in_bytes, hipMemcpyDefault));
const int64_t size = batch_count * stride;
host_values.resize(size);
memset(host_values, 255 - 1, sizeof(T) * size);
CHECK_HIP_ERROR(
hipMemcpy(host_values, buffer, host_values_size_in_bytes, hipMemcpyDefault));
for(int64_t i = 1; i < batch_count; ++i)
{
CHECK_HIP_ERROR(hipMemcpy(
&host_values[i * stride], buffer, host_values_size_in_bytes, hipMemcpyDefault));
T* p = &host_values[i * stride];
for(int64_t j = 0; j < host_values_size; ++j)
{
p[j] = p[j] * (1.0 + random_cached_generator<float>(1.0, 2.0) * random_multiplier);
}
}
auto& device_values = this->get_device_values();
device_values.resize(size);
device_values.transfer_from(host_values);
}
//
// Create local spmat.
//
std::visit([&](auto& that) { this->m_local_descr = new rocsparse_local_spmat(that.device()); },
this->m_data);
if(batch_count > 1)
{
//
// To fix, exposed C-API is inconsistent.
//
switch(this->get_format())
{
case rocsparse_format_coo:
case rocsparse_format_bell:
case rocsparse_format_coo_aos:
case rocsparse_format_ell:
{
CHECK_ROCSPARSE_ERROR(
rocsparse_coo_set_strided_batch(this->m_local_descr[0], batch_count, stride));
break;
}
case rocsparse_format_csr:
case rocsparse_format_sell:
case rocsparse_format_bsr:
{
CHECK_ROCSPARSE_ERROR(
rocsparse_csr_set_strided_batch(this->m_local_descr[0], batch_count, 0, stride));
break;
}
case rocsparse_format_csc:
{
CHECK_ROCSPARSE_ERROR(
rocsparse_csc_set_strided_batch(this->m_local_descr[0], batch_count, 0, stride));
break;
}
}
}
}
template <typename T, typename I, typename J>
rocsparse_clients::spmat_descr<T, I, J>::operator rocsparse_spmat_descr&()
{
return this->m_local_descr[0];
}
template <typename T, typename I, typename J>
rocsparse_clients::spmat_descr<T, I, J>::operator const rocsparse_spmat_descr&() const
{
return this->m_local_descr[0];
}
template struct rocsparse_clients::spmat_descr<float, int32_t, int32_t>;
template struct rocsparse_clients::spmat_descr<double, int32_t, int32_t>;
template struct rocsparse_clients::spmat_descr<rocsparse_float_complex, int32_t, int32_t>;
template struct rocsparse_clients::spmat_descr<rocsparse_double_complex, int32_t, int32_t>;
template struct rocsparse_clients::spmat_descr<float, int64_t, int32_t>;
template struct rocsparse_clients::spmat_descr<double, int64_t, int32_t>;
template struct rocsparse_clients::spmat_descr<rocsparse_float_complex, int64_t, int32_t>;
template struct rocsparse_clients::spmat_descr<rocsparse_double_complex, int64_t, int32_t>;
template struct rocsparse_clients::spmat_descr<float, int64_t, int64_t>;
template struct rocsparse_clients::spmat_descr<double, int64_t, int64_t>;
template struct rocsparse_clients::spmat_descr<rocsparse_float_complex, int64_t, int64_t>;
template struct rocsparse_clients::spmat_descr<rocsparse_double_complex, int64_t, int64_t>;