Files
TheRock/rocm-libraries/projects/rocsparse/clients/tools/rocsparseio-info.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

527 lines
17 KiB
C++

//
// Copyright (C) 2024-2026 Advanced Micro Devices, Inc.
//
// 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 "app.hpp"
#include "rocsparseio.h"
#include <algorithm>
#include <chrono>
#include <complex>
#include <iostream>
#include <math.h>
using rocsparseio_float_complex = std::complex<float>;
using rocsparseio_double_complex = std::complex<double>;
template <typename J, typename T>
struct transpose_pair_t
{
J index{-1};
const T* val;
struct transpose_pair_t* next{};
transpose_pair_t(J i, const T* v, struct transpose_pair_t* n = nullptr)
: index(i)
, val(v)
, next(n){};
~transpose_pair_t()
{
index = -1;
val = nullptr;
next = nullptr;
}
};
template <typename T>
double abs(T val)
{
return std::abs(val);
}
template <>
double abs(_Float16 val)
{
return std::abs((double)val);
}
template <typename I, typename J, typename T>
rocsparseio_status rocsparseio_csx_statistics(rocsparseio_direction dir,
uint64_t M,
uint64_t N,
uint64_t nnz,
const I* __restrict__ ptr_,
const J* __restrict__ ind_,
const T* __restrict__ val_,
rocsparseio_index_base base)
{
uint64_t K = M;
uint64_t len_trseq = N;
switch(base)
{
case rocsparseio_index_base_zero:
{
if(ptr_[0] != 0)
{
std::cerr << "inconsistent matrix with index base" << std::endl;
return rocsparseio_status_invalid_value;
}
break;
}
case rocsparseio_index_base_one:
{
if(ptr_[0] != 1)
{
std::cerr << "inconsistent matrix with index base" << std::endl;
return rocsparseio_status_invalid_value;
}
break;
}
}
switch(dir)
{
case rocsparseio_direction_row:
{
break;
}
case rocsparseio_direction_column:
{
K = N;
len_trseq = M;
break;
}
}
using tr_t = transpose_pair_t<J, T>;
tr_t** trseqs = new tr_t*[len_trseq];
for(uint64_t i = 0; i < len_trseq; ++i)
{
trseqs[i] = nullptr;
}
{
uint64_t k = K;
do
{
--k;
for(uint64_t l = ptr_[k] - base; l < ptr_[k + 1] - base; ++l)
{
J ind = ind_[l] - base;
if(ind < 0 || ind > len_trseq)
{
std::cerr << "inconsistent matrix with overflow of indices" << std::endl;
return rocsparseio_status_invalid_value;
}
if(trseqs[ind] == nullptr)
{
trseqs[ind] = new tr_t(k, &val_[l]);
}
else
{
auto* q = trseqs[ind];
trseqs[ind] = new tr_t(k, &val_[l], q);
}
}
} while(k > 0);
}
{
uint64_t* count = new uint64_t[K];
for(uint64_t k = 0; k < K; ++k)
{
count[k] = ptr_[k + 1] - ptr_[k];
}
std::sort(count, count + K);
std::cout << "min nnz per row: " << count[0] << std::endl;
std::cout << "max nnz per row: " << count[K - 1] << std::endl;
if(K % 2 == 0)
{
std::cout << "median nnz per row: " << count[(K - 1) / 2 - 1] << " "
<< count[(K - 1) / 2] << std::endl;
}
else
{
std::cout << "median nnz per row: " << count[(K - 1) / 2] << std::endl;
}
}
uint64_t b_min = N;
uint64_t b_max = 0;
double sym_val = static_cast<double>(0);
bool sym = true;
for(uint64_t k = 0; k < K; ++k)
{
for(uint64_t l = ptr_[k] - base; l < ptr_[k + 1] - base; ++l)
{
J ind = ind_[l] - base;
T v = val_[l];
uint64_t s = (ind > k) ? (ind - k) : (k - ind);
if(k != ind)
{
b_max = std::max(s, b_max);
b_min = std::min(s, b_min);
auto* lst = trseqs[ind];
for(; lst != nullptr; lst = lst->next)
{
if(lst->index == k)
{
const double d = abs(lst->val[0] - v);
sym_val = std::max(sym_val, d);
break;
}
}
if(lst == nullptr)
{
sym = false;
break;
}
}
}
if(sym == false)
{
break;
}
}
std::cout << "symbolic symmetry " << (sym ? "true" : "false") << std::endl;
std::cout << "numerical symmetry " << (sym_val > 0.0 ? "false" : "true") << std::endl;
std::cout << "b_min " << b_min << std::endl;
std::cout << "b_max " << b_max << std::endl;
for(uint64_t i = 0; i < len_trseq; ++i)
{
auto* p = trseqs[i];
do
{
auto* q = p;
p = p->next;
delete q;
} while(p != nullptr);
}
delete[] trseqs;
return rocsparseio_status_success;
}
template <typename I, typename J, typename T>
rocsparseio_status rocsparseio_csx_statistics(rocsparseio_direction dir,
uint64_t M,
uint64_t N,
uint64_t nnz,
const void* __restrict__ ptr_,
const void* __restrict__ ind_,
const void* __restrict__ val_,
rocsparseio_index_base base)
{
const I* __restrict__ ptr = (const I* __restrict__)ptr_;
const J* __restrict__ ind = (const J* __restrict__)ind_;
const T* __restrict__ val = (const T* __restrict__)val_;
return rocsparseio_csx_statistics(dir, M, N, nnz, ptr, ind, val, base);
}
template <typename I, typename J, typename... P>
rocsparseio_status rocsparseio_csx_statistics_val_type(rocsparseio_type val_type, P&&... params)
{
switch(val_type)
{
case rocsparseio_type_int32:
{
return rocsparseio_status_invalid_value;
}
case rocsparseio_type_int64:
{
return rocsparseio_status_invalid_value;
}
case rocsparseio_type_int8:
{
return rocsparseio_csx_statistics<I, J, int8_t>(params...);
}
case rocsparseio_type_float16:
{
return rocsparseio_csx_statistics<I, J, _Float16>(params...);
}
case rocsparseio_type_float32:
{
return rocsparseio_csx_statistics<I, J, float>(params...);
}
case rocsparseio_type_float64:
{
return rocsparseio_csx_statistics<I, J, double>(params...);
}
case rocsparseio_type_complex32:
{
return rocsparseio_csx_statistics<I, J, rocsparseio_float_complex>(params...);
}
case rocsparseio_type_complex64:
{
return rocsparseio_csx_statistics<I, J, rocsparseio_double_complex>(params...);
}
case rocsparseio_type_bfloat16:
{
return rocsparseio_status_invalid_value;
}
}
return rocsparseio_status_invalid_enum;
}
template <typename I, typename... P>
rocsparseio_status rocsparseio_csx_statistics_ind_type(rocsparseio_type ind_type,
rocsparseio_type val_type,
P&&... params)
{
switch(ind_type)
{
case rocsparseio_type_int32:
{
return rocsparseio_csx_statistics_val_type<I, int32_t>(val_type, params...);
}
case rocsparseio_type_int64:
{
return rocsparseio_csx_statistics_val_type<I, int64_t>(val_type, params...);
}
case rocsparseio_type_int8:
case rocsparseio_type_float16:
case rocsparseio_type_bfloat16:
case rocsparseio_type_float32:
case rocsparseio_type_float64:
case rocsparseio_type_complex32:
case rocsparseio_type_complex64:
{
return rocsparseio_status_invalid_value;
}
}
return rocsparseio_status_invalid_enum;
}
template <typename... P>
rocsparseio_status rocsparseio_csx_statistics_dynamic_dispatch(rocsparseio_type ptr_type,
rocsparseio_type ind_type,
rocsparseio_type val_type,
P&&... params)
{
switch(ptr_type)
{
case rocsparseio_type_int32:
{
return rocsparseio_csx_statistics_ind_type<int32_t>(ind_type, val_type, params...);
}
case rocsparseio_type_int64:
{
return rocsparseio_csx_statistics_ind_type<int64_t>(ind_type, val_type, params...);
}
case rocsparseio_type_int8:
case rocsparseio_type_float16:
case rocsparseio_type_bfloat16:
case rocsparseio_type_float32:
case rocsparseio_type_float64:
case rocsparseio_type_complex32:
case rocsparseio_type_complex64:
{
return rocsparseio_status_invalid_value;
}
}
return rocsparseio_status_invalid_enum;
}
void usage(const char* appname_)
{
fprintf(stderr, "NAME\n");
fprintf(stderr, " %s -- Get ROCSPARSEIO file information\n", appname_);
fprintf(stderr, "SYNOPSIS\n");
fprintf(stderr, " %s [OPTION]... -o <output file> \n", appname_);
fprintf(stderr, "DESCRIPTION\n");
fprintf(stderr, "\n");
fprintf(stderr, " List meta-data information.\n");
fprintf(stderr, "\n");
fprintf(stderr, "OPTIONS\n");
fprintf(stderr, " -v, --verbose\n");
fprintf(stderr, " use verbose of information.\n");
fprintf(stderr, " -h, --help\n");
fprintf(stderr, " produces this help and exit.\n");
fprintf(stderr, "\n");
fprintf(stderr, "NOTES\n");
fprintf(stderr, "\n");
}
#define ROCSPARSEIO_CHECK(stus) \
do \
{ \
rocsparseio_status check_ = (stus); \
if(check_ != rocsparseio_status_success) \
{ \
std::cerr << "invalid status: '" << check_ << "'" << std::endl; \
return stus; \
} \
} while(false)
int main(int argc, char** argv)
{
rocsparseio_cmdline_t cmd(argc, argv);
if(cmd.option("-h") || cmd.option("--help"))
{
usage(argv[0]);
return ROCSPARSEIO_STATUS_SUCCESS;
}
rocsparseio_handle handle;
rocsparseio_status status;
rocsparseio_rwmode mode = rocsparseio_rwmode_read;
status = rocsparseio_open(&handle, mode, argv[1]);
rocsparseio_string name;
rocsparseio_format format;
status = rocsparseio_read_name(handle, name);
std::cout << "name : " << name << std::endl;
status = rocsparseio_read_format(handle, &format);
switch(format)
{
case rocsparseio_format_dense_vector:
{
rocsparseio_type data_type;
uint64_t data_nmemb;
status = rocsparseiox_read_metadata_dense_vector(handle, &data_type, &data_nmemb);
ROCSPARSEIO_CHECK(status);
std::cout << "data_type : " << data_type << std::endl;
std::cout << "data_nmemb : " << data_nmemb << std::endl;
break;
}
case rocsparseio_format_dense_matrix:
{
rocsparseio_order order;
rocsparseio_type data_type;
uint64_t m, n;
status = rocsparseiox_read_metadata_dense_matrix(handle, &order, &m, &n, &data_type);
ROCSPARSEIO_CHECK(status);
std::cout << "data_type : " << data_type << std::endl;
std::cout << "order : " << order << std::endl;
std::cout << "m : " << m << std::endl;
std::cout << "n : " << n << std::endl;
break;
}
case rocsparseio_format_sparse_mcsx:
{
rocsparseio_type ptr_type, ind_type, val_type;
uint64_t m, n, nnz;
rocsparseio_direction dir;
rocsparseio_index_base base;
status = rocsparseiox_read_metadata_sparse_mcsx(
handle, &dir, &m, &n, &nnz, &ptr_type, &ind_type, &val_type, &base);
ROCSPARSEIO_CHECK(status);
std::cout << "m : " << m << std::endl;
std::cout << "n : " << n << std::endl;
std::cout << "nnz : " << nnz << std::endl;
std::cout << "ptr_type : " << ptr_type << std::endl;
std::cout << "ind_type : " << ind_type << std::endl;
std::cout << "val_type : " << val_type << std::endl;
std::cout << "base : " << base << std::endl;
uint64_t val_type_size, ind_type_size, ptr_type_size;
status = rocsparseio_type_get_size(val_type, &val_type_size);
ROCSPARSEIO_CHECK(status);
status = rocsparseio_type_get_size(ptr_type, &ptr_type_size);
ROCSPARSEIO_CHECK(status);
status = rocsparseio_type_get_size(ind_type, &ind_type_size);
ROCSPARSEIO_CHECK(status);
uint64_t s = (val_type_size + ind_type_size) * nnz + (m + 1) * ptr_type_size;
uint64_t nmb = s / (1024 * 1024);
uint64_t ngb = nmb / 1024;
nmb += nmb % 1024;
std::cout << "memory : " << ngb << " Go," << nmb << " Mb " << s % 1024 << " kb"
<< std::endl;
break;
}
case rocsparseio_format_sparse_csx:
{
rocsparseio_type ptr_type, ind_type, val_type;
uint64_t m, n, nnz;
rocsparseio_direction dir;
rocsparseio_index_base base;
status = rocsparseiox_read_metadata_sparse_csx(
handle, &dir, &m, &n, &nnz, &ptr_type, &ind_type, &val_type, &base);
ROCSPARSEIO_CHECK(status);
std::cout << "m : " << m << std::endl;
std::cout << "n : " << n << std::endl;
std::cout << "nnz : " << nnz << std::endl;
std::cout << "ptr_type : " << ptr_type << std::endl;
std::cout << "ind_type : " << ind_type << std::endl;
std::cout << "val_type : " << val_type << std::endl;
std::cout << "base : " << base << std::endl;
uint64_t val_type_size, ind_type_size, ptr_type_size;
status = rocsparseio_type_get_size(val_type, &val_type_size);
ROCSPARSEIO_CHECK(status);
status = rocsparseio_type_get_size(ptr_type, &ptr_type_size);
ROCSPARSEIO_CHECK(status);
status = rocsparseio_type_get_size(ind_type, &ind_type_size);
ROCSPARSEIO_CHECK(status);
uint64_t s = (val_type_size + ind_type_size) * nnz + (m + 1) * ptr_type_size;
uint64_t nmb = s / (1024 * 1024);
uint64_t ngb = nmb / 1024;
nmb += nmb % 1024;
std::cout << "memory : " << ngb << " Go," << nmb << " Mb " << s % 1024 << " kb"
<< std::endl;
uint64_t ptr_size = (dir == rocsparseio_direction_row) ? (m + 1) : (n + 1);
void* ptr = malloc(ptr_type_size * ptr_size);
uint64_t ind_size = nnz;
void* ind = malloc(ind_type_size * ind_size);
uint64_t val_size = nnz;
void* val = malloc(val_type_size * val_size);
status = rocsparseiox_read_sparse_csx(handle, ptr, ind, val);
status = rocsparseio_csx_statistics_dynamic_dispatch(
ptr_type, ind_type, val_type, dir, m, n, nnz, ptr, ind, val, base);
break;
}
case rocsparseio_format_sparse_gebsx:
case rocsparseio_format_sparse_coo:
case rocsparseio_format_sparse_dia:
case rocsparseio_format_sparse_ell:
case rocsparseio_format_sparse_hyb:
{
break;
}
}
status = rocsparseio_close(handle);
ROCSPARSEIO_CHECK(status);
return 0;
}