Provided by: librsb-dev_1.3.0.2+dfsg-6.1build1_amd64
NAME
librsb - rsb-examples - Example programs and code
DESCRIPTION
- Examples of usage of librsb in C (<rsb.h> and <blas_sparse.h>), C++ (optional <rsb.hpp>), Fortran (<rsb.F90> and <rsb_blas_sparse.F90>).
SYNOPSIS
Files file assemble.cpp C++ example based on <rsb.hpp> assembling RsbMatrix by pieces. file autotune.cpp C++ example based on <rsb.hpp> for performance-benchmarking a matrix from file using RsbMatrix.tune_spmm(), for various right-hand side counts. file bench.cpp C++ example based on <rsb.hpp> for performance-benchmarking a matrix from file using RsbMatrix.spmm(), for various right-hand side counts. file build.cpp C++ example based on <rsb.hpp> using timings for common matrix operations on RsbMatrix: RsbMatrix.get_coo(), rsb_coo_sort(), rsb_time(). file example.cpp C++ example based on <rsb.hpp> using RsbMatrix.spmm(). file misc.cpp C++ example based on <rsb.hpp> showing various RsbMatrix operations. file mtx2bin.cpp C++ example based on <rsb.hpp> converting a Matrix Market file into a custom format using RsbMatrix.get_coo(). file render.cpp C++ example based on <rsb.hpp> of invoking the autotuner on an RsbMatrix matrix with RsbMatrix.tune_spmm() and rendering it with RsbMatrix.rndr(). file span.cpp C++ example based on <rsb.hpp> illustrating use of RsbMatrix.file_save(), and std::span-based versions of RsbMatrix.tune_spmm(), RsbMatrix.spmv(). file twonnz.cpp C++ example based on <rsb.hpp> measuring RsbMatrix.spmm() performance of a matrix with only two elements; this is is effectively measuring performance of result vector scaling. file autotune.c C 'RSB autotune' example program based on <rsb.h>. uses rsb_file_mtx_load(), rsb_spmm(), rsb_tune_spmm(). file backsolve.c C triangular solve example program. Uses rsb_spsv(),rsb_tune_spsm(). Based on <rsb.h>. file cplusplus.cpp C++ program using the C <rsb.h> interface. Uses rsb_tune_spmm(), rsb_spmv(). file hello-spblas.c A first C 'hello RSB' example program using a Sparse BLAS interface and <rsb.h>. Uses BLAS_duscr_begin(), BLAS_ussp(), BLAS_usgp(), BLAS_duscr_insert_entries(), BLAS_duscr_end(), BLAS_dusget_element(),BLAS_dusmv(),BLAS_usds(). file hello.c A first 'hello RSB' example C program based on <rsb.h>. Uses rsb_lib_set_opt(), rsb_mtx_get_info_str(). file io-spblas.c Example C program using the Sparse BLAS interface and reading from file using rsb_blas_file_mtx_load(), BLAS_usgp(), BLAS_dusmv(), BLAS_usds(). file power.c A toy <rsb.h>-based C program implementing the power method for computing matrix eigenvalues. Uses rsb_spmv(). file snippets.c Collection of C snippets of other examples. Used piecewise the documentation. Not intended to be read as example. file transpose.c A toy <rsb.h>-based C program showing instantiation, transposition and other operations on a single matrix. Uses rsb_mtx_clone(), rsb_file_mtx_save(), rsb_file_mtx_get_dims(), rsb_file_mtx_load().
Detailed Description
Examples of usage of librsb in C (<rsb.h> and <blas_sparse.h>), C++ (optional <rsb.hpp>), Fortran (<rsb.F90> and <rsb_blas_sparse.F90>). The following fully working example programs illustrate correct ways of using the library. • First example in C, using <rsb.h>: examples_hello_c. • First example in C, using <blas_sparse.h>: examples_hello_spblas_c. • Autotuning example in C, using <rsb.h>: examples_autotune_c. • I/O example in C, using <blas_sparse.h>: examples_io_spblas_c. • Example transposing a matrix in C, using <rsb.h> in C: examples_transpose_c. • Example showing the power method in C, using <rsb.h> in C: examples_power_c. • Example in Fortran, using <rsb_blas_sparse.F90>: examples_fortran_F90. • Example in Fortran, using <rsb.F90>: examples_fortran_rsb_fi_F90. • Example in C, using <rsb.h>: examples_backsolve_c. • Misc example snippets in C, using <rsb.h>: examples_snippets_c. • Benchmark invocation from shell script: examples_bench_sh. Once installed librsb, the script displayed here (examples/make.sh) should be sufficient to build these examples: #!/bin/bash # Example script to build the librsb example programs. # Uses librsb-config in the $PATH for build flags. # Environment-provided $LIBRSB_CONFIG override that. set -e set -x srcdir=${srcdir:-`pwd`} builddir=${builddir:-`pwd`} prefix="/usr" exec_prefix="${prefix}" bindir="${exec_prefix}/bin" if test -z "${LIBRSB_CONFIG}"; then export PATH="${bindir}:$PATH" fi LIBRSB_CONFIG=${LIBRSB_CONFIG:-librsb-config} PKG_CONFIG=pkg-config WANT_PKGCONFIG="yes" WANT_CLEANUP=${WANT_CLEANUP:-false} if test x"yes" == x"yes" ; then CXX="`${LIBRSB_CONFIG} --cxx`" if test x"rsblib" != x"" -a x"${CXX}" != x"" ; then for s in ${srcdir}/*.cpp do p=${builddir}/`basename ${s/.cpp/}` rm -f $p CXXFLAGS=`${LIBRSB_CONFIG} --cxxflags --I_opts` LDFLAGS=`${LIBRSB_CONFIG} --ldflags --extra_libs` LINK=`${LIBRSB_CONFIG} --link` o="${p}.o" ccmd="$CXX $CXXFLAGS -c $s -o $o" lcmd="$LINK $o $LDFLAGS -o $p" echo "$ccmd && $lcmd" ( $ccmd && $lcmd ) ${WANT_CLEANUP} && rm -f "$p" # one may use a single command, but that's error-prone (may miss libraries): #cmd="$CXX $CXXFLAGS $s $LDFLAGS -o $p" #echo $cmd #$cmd done fi fi if test x"yes" == x"yes" ; then for s in ${srcdir}/*.c do p=`basename ${s/.c/}` if test $p == hello-spblas -a x"yes" != x"yes" ; then continue; fi if test $p == io-spblas -a x"yes" != x"yes" ; then continue; fi rm -f $p CFLAGS=`${LIBRSB_CONFIG} --I_opts --cppflags` LDFLAGS=`${LIBRSB_CONFIG} --ldflags --extra_libs` CC=`${LIBRSB_CONFIG} --cc` LINK=`${LIBRSB_CONFIG} --link` o="${p}.o" ccmd="$CC $CFLAGS -c $s -o $o" lcmd="$LINK $o $LDFLAGS -o $p" echo "$ccmd && $lcmd" ( $ccmd && $lcmd ) ${WANT_CLEANUP} && rm -f "$p" # one may use a single command, but that's error-prone (may miss libraries): #cmd="$CC $CFLAGS $s $LDFLAGS -o $p" #echo $cmd #$cmd if test x"${WANT_PKGCONFIG}" != x"no" ; then CFLAGS=`${PKG_CONFIG} --cflags librsb` LIBS=`${PKG_CONFIG} --libs --static librsb` ccmd="$CC $CFLAGS -c $s -o $o" lcmd="$LINK $o $LIBS -o $p" ${WANT_CLEANUP} && rm -f "$p" echo "$ccmd && $lcmd" ( $ccmd && $lcmd ) fi done fi if test x"yes" == x"yes" ; then if test x"yes" = x"yes" ; then FP=${srcdir}/fortran_rsb_fi.F90 if test x"yes" = x"yes" ; then FP+=\ ${srcdir}/fortran.F90 fi # activated if you have built the Fortran modules and installed them in the right path. for s in $FP do p=`basename ${s/.F90/}` rm -f $p FCFLAGS=`${LIBRSB_CONFIG} --I_opts --fcflags` LDFLAGS=`${LIBRSB_CONFIG} --ldflags --extra_libs` FC=`${LIBRSB_CONFIG} --fc` LINK=`${LIBRSB_CONFIG} --link` o="${p}.o" FCLIBS=`${LIBRSB_CONFIG} --fclibs` ccmd="$FC $FCFLAGS -c $s -o $o" lcmd="$LINK $o $LDFLAGS $FCLIBS -o $p" echo "$ccmd && $lcmd" ( $ccmd && $lcmd ) ${WANT_CLEANUP} && rm -f "$p" done fi fi echo " [*] done building examples!" examples/hello.c: /* Copyright (C) 2008-2021 Michele Martone This file is part of librsb. librsb is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. librsb is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with librsb; see the file COPYING. If not, see <http://www.gnu.org/licenses/>. */ /*! \ingroup rsb-examples @file @author Michele Martone @brief A first "hello RSB" example C program based on <rsb.h>. Uses #rsb_lib_set_opt(), #rsb_mtx_get_info_str(). \include hello.c */ #include <rsb.h> /* librsb header to include */ #include <stdio.h> /* printf() */ int main(const int argc, char * const argv[]) { /*! A Hello-RSB program. This program shows how to use the rsb.h interface correctly to: - initialize the library using #rsb_lib_init() - set library options using #rsb_lib_set_opt() - revert such changes - allocate (build) a single sparse matrix in the RSB format using #rsb_mtx_alloc_from_coo_const() - prints information obtained via #rsb_mtx_get_info_str() - multiply the matrix times a vector using #rsb_spmv() - deallocate the matrix using #rsb_mtx_free() - finalize the library using #rsb_lib_exit() In this example, we use #RSB_DEFAULT_TYPE as matrix type. This type depends on what was configured at library build time. * */ const rsb_blk_idx_t bs = RSB_DEFAULT_BLOCKING; const rsb_blk_idx_t brA = bs, bcA = bs; const RSB_DEFAULT_TYPE one = 1; const rsb_type_t typecode = RSB_NUMERICAL_TYPE_DEFAULT; const rsb_nnz_idx_t nnzA = 4; /* matrix nonzeroes count */ const rsb_coo_idx_t nrA = 3; /* matrix rows count */ const rsb_coo_idx_t ncA = 3; /* matrix columns count */ /* nonzero row indices coordinates: */ const rsb_coo_idx_t IA[] = {0,1,2,2}; /* nonzero column indices coordinates: */ const rsb_coo_idx_t JA[] = {0,1,2,2}; const RSB_DEFAULT_TYPE VA[] = {11,22,32,1};/* values of nonzeroes */ RSB_DEFAULT_TYPE X[] = { 0, 0, 0 }; /* X vector's array */ const RSB_DEFAULT_TYPE B[] = { -1, -2, -5 }; /* B vector's array */ char ib[200]; struct rsb_mtx_t *mtxAp = NULL; /* matrix structure pointer */ rsb_err_t errval = RSB_ERR_NO_ERROR; printf("Hello, RSB!\n"); printf("Initializing the library...\n"); if((errval = rsb_lib_init(RSB_NULL_INIT_OPTIONS)) != RSB_ERR_NO_ERROR) { printf("Error initializing the library!\n"); goto err; } printf("Correctly initialized the library.\n"); printf("Attempting to set the" " RSB_IO_WANT_EXTRA_VERBOSE_INTERFACE library option.\n"); { rsb_int_t evi=1; /* Setting a single optional library parameter. */ errval = rsb_lib_set_opt( RSB_IO_WANT_EXTRA_VERBOSE_INTERFACE, &evi); if(errval != RSB_ERR_NO_ERROR) { char errbuf[256]; rsb_strerror_r(errval,&errbuf[0],sizeof(errbuf)); printf("Failed setting the" " RSB_IO_WANT_EXTRA_VERBOSE_INTERFACE" " library option (reason string:\n%s).\n",errbuf); if(errval&RSB_ERRS_UNSUPPORTED_FEATURES) { printf("This error may be safely ignored.\n"); } else { printf("Some unexpected error occurred!\n"); goto err; } } else { printf("Setting back the " "RSB_IO_WANT_EXTRA_VERBOSE_INTERFACE" " library option.\n"); evi = 0; errval = rsb_lib_set_opt(RSB_IO_WANT_EXTRA_VERBOSE_INTERFACE, &evi); errval = RSB_ERR_NO_ERROR; } } mtxAp = rsb_mtx_alloc_from_coo_const( VA,IA,JA,nnzA,typecode,nrA,ncA,brA,bcA, RSB_FLAG_NOFLAGS /* default format will be chosen */ |RSB_FLAG_DUPLICATES_SUM/* duplicates will be summed */ ,&errval); if((!mtxAp) || (errval != RSB_ERR_NO_ERROR)) { printf("Error while allocating the matrix!\n"); goto err; } printf("Correctly allocated a matrix.\n"); printf("Summary information of the matrix:\n"); /* print out the matrix summary information */ rsb_mtx_get_info_str(mtxAp,"RSB_MIF_MATRIX_INFO__TO__CHAR_P", ib,sizeof(ib)); printf("%s",ib); printf("\n"); if((errval = rsb_spmv(RSB_TRANSPOSITION_N,&one,mtxAp,B,1,&one,X,1)) != RSB_ERR_NO_ERROR ) { printf("Error performing a multiplication!\n"); goto err; } printf("Correctly performed a SPMV.\n"); rsb_mtx_free(mtxAp); printf("Correctly freed the matrix.\n"); if((errval = rsb_lib_exit(RSB_NULL_EXIT_OPTIONS)) != RSB_ERR_NO_ERROR) { printf("Error finalizing the library!\n"); goto err; } printf("Correctly finalized the library.\n"); printf("Program terminating with no error.\n"); return EXIT_SUCCESS; err: rsb_perror(NULL,errval); printf("Program terminating with error.\n"); return EXIT_FAILURE; } examples/hello-spblas.c: /* Copyright (C) 2008-2021 Michele Martone This file is part of librsb. librsb is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. librsb is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with librsb; see the file COPYING. If not, see <http://www.gnu.org/licenses/>. */ /*! \ingroup rsb-examples @file @author Michele Martone @brief A first C "hello RSB" example program using a Sparse BLAS interface and <rsb.h>. Uses #BLAS_duscr_begin(), #BLAS_ussp(), #BLAS_usgp(), #BLAS_duscr_insert_entries(), #BLAS_duscr_end(), #BLAS_dusget_element(),#BLAS_dusmv(),#BLAS_usds(). \include hello-spblas.c */ #include <rsb.h> /* for rsb_lib_init */ #include <blas_sparse.h> /* Sparse BLAS on the top of librsb */ #include <stdio.h> /* printf */ int main(const int argc, char * const argv[]) { /*! * A Hello/Sparse BLAS program. * * This program shows how to use the blas_sparse.h * interface correctly to: * * - initialize the library using #rsb_lib_init() * - allocate (build) a single sparse matrix in the RSB * format using #BLAS_duscr_begin()/#BLAS_duscr_insert_entries() * /#BLAS_duscr_end() * - extract one matrix element with #BLAS_dusget_element() * - multiply the matrix times a vector using #BLAS_dusmv() * - deallocate the matrix using #BLAS_usds() * - finalize the library using * #rsb_lib_exit(#RSB_NULL_EXIT_OPTIONS) */ #ifndef RSB_NUMERICAL_TYPE_DOUBLE printf("'double' type configured out." " Please reconfigure the library with it and recompile.\n"); return EXIT_SUCCESS; #else /* RSB_NUMERICAL_TYPE_DOUBLE */ blas_sparse_matrix A = blas_invalid_handle; /* handle for A */ const int nnz = 4; /* number of nonzeroes of matrix A */ const int nr = 3; /* number of A's rows */ const int nc = 3; /* number of A's columns */ /* A's nonzero elements row indices (coordinates): */ #ifdef RSB_WANT_LONG_IDX_TYPE const int64_t IA[] = { 0, 1, 2, 2 }; #else /* RSB_WANT_LONG_IDX_TYPE */ const int IA[] = { 0, 1, 2, 2 }; #endif /* RSB_WANT_LONG_IDX_TYPE */ /* A's nonzero elements column indices (coordinates): */ #ifdef RSB_WANT_LONG_IDX_TYPE const int64_t JA[] = { 0, 1, 0, 2 }; #else /* RSB_WANT_LONG_IDX_TYPE */ const int JA[] = { 0, 1, 0, 2 }; #endif /* RSB_WANT_LONG_IDX_TYPE */ /* A's nonzero values (matrix coefficients): */ double VA[] = { 11.0, 22.0, 13.0, 33.0 }; /* the X vector's array: */ double X[] = { 0.0, 0.0, 0.0 }; /* the B vector's array: */ const double B[] = { -1.0, -2.0, -2.0 }; /* the (known) result array: */ const double AB[] = { 11.0+26.0, 44.0, 66.0+13.0 }; /* rsb error variable: */ rsb_err_t errval = RSB_ERR_NO_ERROR; int i; printf("Hello, RSB!\n"); /* initialize the library */ if((errval = rsb_lib_init(RSB_NULL_INIT_OPTIONS)) != RSB_ERR_NO_ERROR) { goto err; } printf("Correctly initialized the library.\n"); /* initialize a matrix descriptor */ A = BLAS_duscr_begin(nr,nc); if( A == blas_invalid_handle ) { goto err; } /* specify properties (e.g.: symmetry)*/ if( BLAS_ussp(A,blas_lower_symmetric) != 0 ) { goto err; } /* get properties (e.g.: symmetry) */ if( BLAS_usgp(A,blas_lower_symmetric) != 1 ) { printf("Symmetry property non set ?!\n"); goto err; } /* insert the nonzeroes (here, all at once) */ if( BLAS_duscr_insert_entries(A, nnz, VA, IA, JA) == blas_invalid_handle) { goto err; } /* finalize (allocate) the matrix build */ if( BLAS_duscr_end(A) == blas_invalid_handle ) { goto err; } printf("Correctly allocated a matrix.\n"); VA[0] = 0.0; if( BLAS_dusget_element(A, IA[0], JA[0], &VA[0]) ) { goto err; } /* a check */ if( VA[0] != 11.0 ) { goto err; } /* compute X = X + (-1) * A * B */ if(BLAS_dusmv(blas_no_trans,-1,A,B,1,X,1)) { goto err; } for( i = 0 ; i < nc; ++i ) if( X[i] != AB[i] ) { printf("Computed SPMV result seems wrong. Terminating.\n"); goto err; } printf("Correctly performed a SPMV.\n"); /* deallocate matrix A */ if( BLAS_usds(A) ) { goto err; } printf("Correctly freed the matrix.\n"); /* finalize the library */ if((errval = rsb_lib_exit(RSB_NULL_EXIT_OPTIONS)) != RSB_ERR_NO_ERROR) { goto err; } printf("Correctly finalized the library.\n"); printf("Program terminating with no error.\n"); return EXIT_SUCCESS; err: rsb_perror(NULL,errval); printf("Program terminating with error.\n"); return EXIT_FAILURE; #endif /* RSB_NUMERICAL_TYPE_DOUBLE */ } examples/autotune.c: /* Copyright (C) 2008-2021 Michele Martone This file is part of librsb. librsb is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. librsb is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with librsb; see the file COPYING. If not, see <http://www.gnu.org/licenses/>. */ /*! \ingroup rsb-examples @file @author Michele Martone @brief C "RSB autotune" example program based on <rsb.h>. uses #rsb_file_mtx_load(), rsb_spmm(), rsb_tune_spmm(). \include autotune.c */ #include <rsb.h> /* librsb header to include */ #include <stdio.h> /* printf() */ #include <ctype.h> /* isdigit() */ #include <stdlib.h> /* atoi() */ /* #include "rsb_internals.h" */ static int tune_from_file(char * const filename, rsb_int_t wvat) { struct rsb_mtx_t *mtxMp = NULL; /* spmv specific variables */ const void * alphap = NULL; // equivalent to 1 const void * betap = NULL; // equivalent to 1 rsb_flags_t order = RSB_FLAG_WANT_COLUMN_MAJOR_ORDER; const rsb_coo_idx_t nrhs = 2; /* number of right hand sides */ rsb_trans_t transA = RSB_TRANSPOSITION_N; /* transposition */ rsb_nnz_idx_t ldB = 0; rsb_nnz_idx_t ldC = 0; /* misc variables */ rsb_err_t errval = RSB_ERR_NO_ERROR; rsb_time_t dt; char ib[200]; const char*is = "RSB_MIF_MATRIX_INFO__TO__CHAR_P"; /* misc variables */ /* input autotuning variables */ rsb_int_t oitmax = 1 /*15*/; /* auto-tune iterations */ rsb_time_t tmax = 0.1; /* time per autotune operation */ /* output autotuning variables */ rsb_flags_t flagsA = RSB_FLAG_NOFLAGS; /* int ione = 1; */ rsb_type_t typecodea [] = RSB_MATRIX_TYPE_CODES_ARRAY; int typecodei; errval = rsb_lib_init(RSB_NULL_INIT_OPTIONS); if( (errval) != RSB_ERR_NO_ERROR ) goto err; errval = rsb_lib_set_opt(RSB_IO_WANT_VERBOSE_TUNING, &wvat ); /* errval = rsb_lib_set_opt(RSB_IO_WANT_EXTRA_VERBOSE_INTERFACE, &ione); */ if( (errval) != RSB_ERR_NO_ERROR ) goto err; printf("Loading matrix from file \"%s\".\n",filename); mtxMp = rsb_file_mtx_load(filename, flagsA, typecodea[0], &errval); if( (errval) != RSB_ERR_NO_ERROR ) goto err; for( typecodei = 0 ; typecodei < RSB_IMPLEMENTED_TYPES; ++typecodei ) { rsb_type_t typecode = typecodea[typecodei]; struct rsb_mtx_t *mtxAp = NULL; struct rsb_mtx_t *mtxOp = NULL; rsb_real_t sf = 0.0; rsb_int_t tn = 0; sf = 0.0; tn = 0; printf("Considering %c clone.\n",typecode); errval = rsb_mtx_clone(&mtxAp, typecode, transA, NULL, mtxMp, flagsA); if( (errval) != RSB_ERR_NO_ERROR ) goto err; printf("Base matrix:\n"); rsb_mtx_get_info_str(mtxAp,is,ib,sizeof(ib)); printf("%s\n\n",ib); dt = -rsb_time(); errval = rsb_tune_spmm(NULL, &sf, &tn, oitmax, tmax, transA, alphap, mtxAp, nrhs, order, NULL, ldB, betap, NULL, ldC); dt += rsb_time(); if(tn == 0) printf("After %lfs, autotuning routine did not find a better" " threads count configuration.\n",dt); else printf("After %lfs, thread autotuning declared speedup of %lg x," " when using threads count of %d.\n",dt,sf,tn); printf("\n"); dt = -rsb_time(); mtxOp = mtxAp; errval = rsb_tune_spmm(&mtxAp, &sf, &tn, oitmax, tmax, transA, alphap, NULL, nrhs, order, NULL, ldB, betap, NULL, ldC); if( (errval) != RSB_ERR_NO_ERROR ) goto err; dt += rsb_time(); if( mtxOp == mtxAp ) { printf("After %lfs, global autotuning found old matrix optimal," " with declared speedup %lg x when using %d threads\n",dt,sf,tn); } else { printf("After %lfs, global autotuning declared speedup of %lg x," " when using threads count of %d and a new matrix:\n",dt,sf,tn); rsb_mtx_get_info_str(mtxAp,is,ib,sizeof(ib)); printf("%s\n",ib); } printf("\n"); /* user is expected to: errval = rsb_lib_set_opt(RSB_IO_WANT_EXECUTING_THREADS,&tn); and use mtxAp in SpMV. */ rsb_mtx_free(mtxAp); mtxAp = NULL; } rsb_mtx_free(mtxMp); mtxMp = NULL; err: rsb_perror(NULL,errval); if ( errval != RSB_ERR_NO_ERROR ) printf("Program terminating with error.\n"); return errval; } int main(const int argc, char * const argv[]) { /*! Autotuning example. */ /* matrix variables */ struct rsb_mtx_t *mtxAp = NULL; /* matrix structure pointer */ const int bs = RSB_DEFAULT_BLOCKING; rsb_coo_idx_t nrA = 500; /* number of rows */ rsb_coo_idx_t ncA = 500; /* number of cols */ const rsb_type_t typecode = RSB_NUMERICAL_TYPE_DEFAULT; const rsb_coo_idx_t rd = 1;/* every rd rows one is non empty */ const rsb_coo_idx_t cd = 4;/* every cd cols one is non empty */ rsb_nnz_idx_t nnzA = (nrA/rd)*(ncA/cd); /* nonzeroes */ rsb_coo_idx_t*IA = NULL; rsb_coo_idx_t*JA = NULL; RSB_DEFAULT_TYPE*VA = NULL; /* spmv specific variables */ const RSB_DEFAULT_TYPE alpha = 1; const RSB_DEFAULT_TYPE beta = 1; RSB_DEFAULT_TYPE*Cp = NULL; RSB_DEFAULT_TYPE*Bp = NULL; rsb_flags_t order = RSB_FLAG_WANT_COLUMN_MAJOR_ORDER; const rsb_coo_idx_t nrhs = 2; /* number of right hand sides */ const rsb_trans_t transA = RSB_TRANSPOSITION_N; rsb_nnz_idx_t ldB = nrA; rsb_nnz_idx_t ldC = ncA; /* misc variables */ rsb_err_t errval = RSB_ERR_NO_ERROR; const size_t so = sizeof(RSB_DEFAULT_TYPE); const size_t si = sizeof(rsb_coo_idx_t); rsb_time_t dt,odt; rsb_int_t t; const rsb_int_t tt = 100; /* will repeat spmv tt times */ char ib[200]; const char*is = "RSB_MIF_MATRIX_INFO__TO__CHAR_P"; /* misc counters */ rsb_coo_idx_t ci; rsb_coo_idx_t ri; rsb_coo_idx_t ni; rsb_int_t nrhsi; /* misc variables */ rsb_time_t etime = 0.0; /* input autotuning variables */ const rsb_int_t oitmax = 15; /* auto-tune iterations */ const rsb_time_t tmax = 0.1; /* time per autotune operation */ /* input/output autotuning variables */ rsb_int_t tn = 0; /* threads number */ /* output autotuning variables */ rsb_real_t sf = 0.0; /* speedup factor obtained from auto tuning */ const rsb_int_t wvat = 1; /* want verbose autotuning; see documentation of RSB_IO_WANT_VERBOSE_TUNING */ if(argc > 1 && !isdigit(argv[1][0]) ) { errval = tune_from_file(argv[1],wvat); goto ret; } if(argc > 1) { nrA = ncA = atoi(argv[1]); if ( nrA < RSB_MIN_MATRIX_DIM || (nrA > (RSB_MAX_MATRIX_DIM) )) goto err; nnzA = (nrA/rd)*(ncA/cd); ldB = nrA; ldC = ncA; } printf("Creating %d x %d matrix with %d nonzeroes.\n",(int)nrA, (int)ncA, (int)nnzA); IA = calloc(nnzA, si); JA = calloc(nnzA, si); VA = calloc(nnzA, so); Bp = calloc(nrhs*ncA ,so); Cp = calloc(nrhs*nrA ,so); if( ! ( VA && IA && JA && Bp && Cp ) ) goto err; for(nrhsi=0;nrhsi<nrhs;++nrhsi) for(ci=0;ci<ncA/cd;++ci) Bp[nrhsi*ldC+ci] = 1.0; for(nrhsi=0;nrhsi<nrhs;++nrhsi) for(ri=0;ri<nrA/rd;++ri) Cp[nrhsi*ldC+ri] = 1.0; ni = 0; for(ci=0;ci<ncA/cd;++ci) for(ri=0;ri<nrA/rd;++ri) { VA[ni] = nrA * ri + ci, IA[ni] = ri; JA[ni] = ci; ni++; } if((errval = rsb_lib_init(RSB_NULL_INIT_OPTIONS)) != RSB_ERR_NO_ERROR) goto err; errval = rsb_lib_set_opt(RSB_IO_WANT_VERBOSE_TUNING, &wvat ); if( (errval) != RSB_ERR_NO_ERROR ) { printf("Error setting option!\n"); goto err; } mtxAp = rsb_mtx_alloc_from_coo_const( VA,IA,JA,nnzA,typecode,nrA,ncA,bs,bs, RSB_FLAG_NOFLAGS,&errval); /* VA, IA, JA are not necessary anymore */ free(VA); free(IA); free(JA); VA = NULL; IA = NULL; JA = NULL; if((!mtxAp) || (errval != RSB_ERR_NO_ERROR)) goto err; printf("Allocated matrix of %zd nonzeroes:\n",(size_t)nnzA); rsb_mtx_get_info_str(mtxAp,is,ib,sizeof(ib)); printf("%s\n\n",ib); dt = - rsb_time(); for(t=0;t<tt;++t) /* If nrhs == 1, the following is equivalent to rsb_spmv(transA,alphap,mtxAp,Bp,1,betap,Cp,1); */ rsb_spmm(transA,&alpha,mtxAp,nrhs,order,Bp,ldB,&beta,Cp,ldC); dt += rsb_time(); odt = dt; printf("Before auto-tuning, %d multiplications took %lfs.\n",tt,dt); printf("Threads autotuning (may take more than %lfs)...\n", oitmax*tmax); dt = -rsb_time(); errval = rsb_tune_spmm(NULL, &sf, &tn, oitmax, tmax, transA, &alpha, mtxAp, nrhs, order, Bp, ldB, &beta, Cp, ldC); dt += rsb_time(); if(errval != RSB_ERR_NO_ERROR) goto err; if(tn == 0) printf("After %lfs, autotuning routine did not find a better" " threads count configuration.\n",dt); else printf("After %lfs, autotuning routine declared speedup of %lg x," " when using threads count of %d.\n",dt,sf,tn); errval = rsb_lib_set_opt(RSB_IO_WANT_EXECUTING_THREADS,&tn); if(errval != RSB_ERR_NO_ERROR) goto err; rsb_mtx_get_info_str(mtxAp,is,ib,sizeof(ib)); printf("%s\n",ib); dt = -rsb_time(); for(t=0;t<tt;++t) /*rsb_spmv(transA,&alpha,mtxAp,Bp,1,&beta,Cp,1);*/ rsb_spmm(transA,&alpha,mtxAp,nrhs,order,Bp,ldB,&beta,Cp,ldC); dt += rsb_time(); printf("After threads auto-tuning, %d multiplications took %lfs" " -- effective speedup of %lg x\n",tt,dt,odt/dt); odt = dt; tn = 0; /* this will restore default threads count */ errval = rsb_lib_set_opt(RSB_IO_WANT_EXECUTING_THREADS,&tn); if(errval != RSB_ERR_NO_ERROR) goto err; errval = rsb_lib_get_opt(RSB_IO_WANT_EXECUTING_THREADS,&tn); if(errval != RSB_ERR_NO_ERROR) goto err; printf("Matrix autotuning (may take more than %lfs; using %d" " threads )...\n", oitmax*tmax, tn); /* A negative tn will request also threads autotuning: */ /* tn = -tn; */ dt = -rsb_time(); errval = rsb_tune_spmm(&mtxAp, &sf, &tn, oitmax, tmax, transA, &alpha, NULL, nrhs, order, Bp, ldB, &beta, Cp, ldC); dt += rsb_time(); if(errval != RSB_ERR_NO_ERROR) goto err; if(tn == 0) printf("After %lfs, autotuning routine did not find a better" " threads count configuration.\n",dt); else printf("After %lfs, autotuning routine declared speedup of %lg x," " when using threads count of %d.\n",dt,sf,tn); rsb_mtx_get_info_str(mtxAp,is,ib,sizeof(ib)); printf("%s\n",ib); dt = -rsb_time(); for(t=0;t<tt;++t) /*rsb_spmv(transA,&alpha,mtxAp,Bp,1,&beta,Cp,1);*/ rsb_spmm(transA,&alpha,mtxAp,nrhs,order,Bp,ldB,&beta,Cp,ldC); dt += rsb_time(); printf("After threads auto-tuning, %d multiplications took %lfs" " -- further speedup of %lg x\n",tt,dt,odt/dt); rsb_mtx_free(mtxAp); free(Cp); free(Bp); errval = rsb_lib_get_opt(RSB_IO_WANT_LIBRSB_ETIME,&etime); if(errval == RSB_ERR_UNSUPPORTED_FEATURE) { printf("librsb timer-based profiling is not supported in " "this build. If you wish to have it, re-configure librsb " "with its support. So you can safely ignore the error you" " might just have seen printed out on screen.\n"); errval = RSB_ERR_NO_ERROR; } else if(etime) /* This will only work if enabled at configure time. */ printf("Elapsed program time is %5.2lfs\n",etime); ret: if((errval = rsb_lib_exit(RSB_NULL_EXIT_OPTIONS)) !=RSB_ERR_NO_ERROR) goto err; return EXIT_SUCCESS; err: rsb_perror(NULL,errval); printf("Program terminating with error.\n"); return EXIT_FAILURE; } examples/io-spblas.c: /* Copyright (C) 2008-2021 Michele Martone This file is part of librsb. librsb is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. librsb is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with librsb; see the file COPYING. If not, see <http://www.gnu.org/licenses/>. */ /*! \ingroup rsb-examples @file @author Michele Martone @brief Example C program using the Sparse BLAS interface and reading from file using \ref rsb_blas_file_mtx_load(), \ref BLAS_usgp(), \ref BLAS_dusmv(), \ref BLAS_usds(). \include io-spblas.c */ #include <rsb.h> /* for rsb_lib_init */ #include <blas_sparse.h> #include <stdio.h> int main(const int argc, char * const argv[]) { #ifndef RSB_NUMERICAL_TYPE_DOUBLE printf("Skipping a test because of 'double' type opted out.\n"); return EXIT_SUCCESS; #else /* RSB_NUMERICAL_TYPE_DOUBLE */ blas_sparse_matrix A = blas_invalid_handle; const rsb_type_t typecode = RSB_NUMERICAL_TYPE_DOUBLE; const rsb_char_t * filename = argc > 1 ? argv[1] : "pd.mtx"; printf("Hello, RSB!\n"); if((rsb_perror(NULL, rsb_lib_init(RSB_NULL_INIT_OPTIONS)))!=RSB_ERR_NO_ERROR) { printf("Error while initializing the library.\n"); goto err; } printf("Correctly initialized the library.\n"); A = rsb_blas_file_mtx_load(filename, typecode ); if( A == blas_invalid_handle ) { printf("Error while loading matrix %s from file.\n", filename); goto err; } printf("Correctly loaded and allocated a matrix" " from file %s.\n",filename); if( BLAS_usgp(A,blas_symmetric) == 1 ) printf("Matrix is symmetric\n"); if( BLAS_usgp(A,blas_hermitian) == 1 ) printf("Matrix is hermitian\n"); printf("Now SPMV with NULL vectors will be attempted," " resulting in an error (so don't worry).\n"); if(BLAS_dusmv(blas_no_trans,-1,A,NULL,1,NULL,1)) { printf("Correctly detected an error condition.\n"); goto okerr; } printf("No error detected ?\nIf you see this line printed out," " please report as a bug, because the above NULL pointers" " should have been detected\n"); return EXIT_FAILURE; okerr: printf("Program correctly recovered from intentional" " error condition.\n"); if(BLAS_usds(A)) { printf("Error while freeing the matrix!\n"); goto err; } printf("Correctly freed the matrix.\n"); err: if(rsb_perror(NULL, rsb_lib_exit(RSB_NULL_EXIT_OPTIONS))!=RSB_ERR_NO_ERROR) { printf("Failed finalizing the library.\n"); goto ferr; } printf("Correctly finalized the library.\n"); return EXIT_SUCCESS; ferr: return EXIT_FAILURE; #endif /* RSB_NUMERICAL_TYPE_DOUBLE */ } examples/transpose.c: /* Copyright (C) 2008-2021 Michele Martone This file is part of librsb. librsb is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. librsb is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with librsb; see the file COPYING. If not, see <http://www.gnu.org/licenses/>. */ /*! @file @author Michele Martone @brief A toy <rsb.h>-based C program showing instantiation, transposition and other operations on a single matrix. Uses \ref rsb_mtx_clone(), \ref rsb_file_mtx_save(), \ref rsb_file_mtx_get_dims(), \ref rsb_file_mtx_load(). \ingroup rsb-examples \include transpose.c */ #include <rsb.h> #include <stdio.h> /* printf */ int main(const int argc, char * const argv[]) { struct rsb_mtx_t *mtxAp = NULL; const rsb_blk_idx_t brA = RSB_DEFAULT_BLOCKING, bcA = RSB_DEFAULT_BLOCKING; rsb_nnz_idx_t nnzA = 4; rsb_coo_idx_t nrA = 3; rsb_coo_idx_t ncA = 3; const rsb_coo_idx_t IA[] = { 0, 1, 2, 0 }; const rsb_coo_idx_t JA[] = { 0, 1, 2, 2 }; const RSB_DEFAULT_TYPE VA[] = { 11, 22, 33, 13 }; RSB_DEFAULT_TYPE XV[] = { 0,0,0,0,0,0 }; rsb_coo_idx_t vl = 0; const rsb_type_t typecode = RSB_NUMERICAL_TYPE_DEFAULT; rsb_err_t errval = RSB_ERR_NO_ERROR; /* library initialization */ if(rsb_lib_init(RSB_NULL_INIT_OPTIONS)!=RSB_ERR_NO_ERROR) { return EXIT_FAILURE; } /* allocation */ mtxAp = rsb_mtx_alloc_from_coo_const( VA,IA,JA,nnzA,typecode,nrA,ncA, brA,bcA,RSB_FLAG_NOFLAGS,NULL); if(!mtxAp) { return EXIT_FAILURE; } /* printout */ if(RSB_ERR_NO_ERROR!=(errval = rsb_file_mtx_save(mtxAp,NULL))) { if(errval != RSB_ERR_UNSUPPORTED_FEATURE) goto err; } /* matrix transposition */ if( RSB_ERR_NO_ERROR != (errval = rsb_mtx_clone(&mtxAp,RSB_NUMERICAL_TYPE_SAME_TYPE, RSB_TRANSPOSITION_T,NULL,mtxAp,RSB_FLAG_IDENTICAL_FLAGS))) { goto err; } /* printout */ if(RSB_ERR_NO_ERROR!=(errval = rsb_file_mtx_save(mtxAp,NULL))) { if(errval != RSB_ERR_UNSUPPORTED_FEATURE) goto err; } rsb_mtx_free(mtxAp); /* doing the same after load from file */ mtxAp = rsb_file_mtx_load("pd.mtx", RSB_FLAG_NOFLAGS,typecode,NULL); if(!mtxAp) { return EXIT_FAILURE; } /* printout */ if(RSB_ERR_NO_ERROR!=(errval = rsb_file_mtx_save(mtxAp,NULL))) { if(errval != RSB_ERR_UNSUPPORTED_FEATURE) goto err; } /* one can see dimensions in advance, also */ if(RSB_ERR_NO_ERROR!=(errval = rsb_file_mtx_get_dims("pd.mtx",&nrA,&ncA,&nnzA,NULL))) { if(errval != RSB_ERR_UNSUPPORTED_FEATURE) goto err; } /* A matrix can be rendered to Postscript. */ { if(RSB_ERR_NO_ERROR!=(errval = rsb_mtx_rndr("pd.eps",mtxAp,512,512,RSB_MARF_EPS_B))) goto err; } rsb_mtx_free(mtxAp); /* also vectors can be loaded */ if(RSB_ERR_NO_ERROR!=(errval = rsb_file_vec_load("vf.mtx",typecode,NULL,&vl ))) goto err; /* we expect vf.mtx to be 6 rows long */ if( vl != 6 ) { goto err; } if(RSB_ERR_NO_ERROR!=(errval = rsb_file_vec_load("vf.mtx",typecode,XV, NULL ))) goto err; /* matrices can be rendered from file to a pixelmap as well */ { unsigned char pixmap[3*2*2]; if(RSB_ERR_NO_ERROR!=(errval = rsb_file_mtx_rndr(pixmap,"pd.mtx",2,2,2,RSB_MARF_RGB))) goto err; } if(RSB_ERR_NO_ERROR != rsb_lib_exit(RSB_NULL_EXIT_OPTIONS)) { goto err; } return EXIT_SUCCESS; err: rsb_perror(NULL,errval); return EXIT_FAILURE; } examples/power.c: /* Copyright (C) 2008-2021 Michele Martone This file is part of librsb. librsb is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. librsb is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with librsb; see the file COPYING. If not, see <http://www.gnu.org/licenses/>. */ /*! @file @author Michele Martone @brief A toy <rsb.h>-based C program implementing the power method for computing matrix eigenvalues. Uses #rsb_spmv(). \ingroup rsb-examples \include power.c */ #include <stdio.h> // printf #include <math.h> // sqrt #include <stdlib.h> // calloc #include <rsb.h> int main(const int argc, char * const argv[]) { const int WANT_VERBOSE = 0; struct rsb_mtx_t *mtxAp = NULL; const int bs = RSB_DEFAULT_BLOCKING; const int br = bs, bc = bs; /* bs x bs blocked */ const rsb_nnz_idx_t nnzA = 4; const rsb_coo_idx_t nrA = 3; const rsb_coo_idx_t ncA = 3; rsb_int_t it = 0; const rsb_int_t maxit = 100; const rsb_coo_idx_t IA[] = { 0, 1, 2, 0 }; const rsb_coo_idx_t JA[] = { 0, 1, 2, 2 }; const RSB_DEFAULT_POSSIBLY_FIRST_BLAS_TYPE VA[] = { 11, 22, 33, 13 }; const RSB_DEFAULT_POSSIBLY_FIRST_BLAS_TYPE ZERO = 0; int i; rsb_err_t errval = 0; RSB_DEFAULT_POSSIBLY_FIRST_BLAS_TYPE norm = 0.0, /* nu */ oldnorm = 1.0, /* oldnorm */ *b1 = NULL, *b2 = NULL, *bnow = NULL, *bnext = NULL;/* b1 and b2 aliases */ rsb_type_t typecode = RSB_NUMERICAL_TYPE_FIRST_BLAS; size_t ds = 0; /* tolerance */ const RSB_DEFAULT_POSSIBLY_FIRST_BLAS_TYPE tol = 1e-14; /* library initialization */ if(rsb_lib_init(RSB_NULL_INIT_OPTIONS)!=RSB_ERR_NO_ERROR) return EXIT_FAILURE; /* allocation */ mtxAp = rsb_mtx_alloc_from_coo_const(VA,IA,JA,nnzA, typecode,nrA,ncA,br,bc,RSB_FLAG_NOFLAGS,NULL); if(!mtxAp) return EXIT_FAILURE; ds = (nrA)*sizeof(RSB_DEFAULT_POSSIBLY_FIRST_BLAS_TYPE); b1 = calloc(1,ds); b2 = calloc(1,ds); if(! (b1 && b2)) { errval = RSB_ERR_ENOMEM; goto err; } for( i = 0; i < nrA; ++i ) b1[i] = 1; bnow = b1, bnext = b2;/* b,b' */ while( fabs(norm-oldnorm) > tol && it<maxit ) { ++ it; oldnorm = norm; /* b'<-Ab */ if(( rsb_spmv(RSB_TRANSPOSITION_N,NULL,mtxAp,bnow, 1,&ZERO,bnext,1)) != RSB_ERR_NO_ERROR ) goto err; /* nu<-||Ab||^2 */ norm = 0; for(i=0;i<nrA;++i) norm += bnext[i]*bnext[i]; /* nu<-||Ab|| */ norm = sqrt(norm); norm = 1.0/norm; /* b'<- Ab / ||Ab|| */ for(i=0;i<nrA;++i) bnext[i] *= norm; norm = 1.0/norm; printf("it:%d norm:%lg norm diff:%lg\n",it,norm,norm-oldnorm); {void *tmp=bnow;bnow=bnext;bnext=tmp;/* pointers swap */} if(WANT_VERBOSE) { printf("norm:%lg\n",norm); if(isinf(norm)) /* isinf is a C99 feature (need correct * compilation flags) */ goto err; for(i=0;i<2;++i) printf("x[%d]=%lg\n",i,((double*)bnext)[i]); } } /* the biggest eigenvalue should be in bnow */ rsb_mtx_free(mtxAp); free(b1); free(b2); if(rsb_lib_exit(RSB_NULL_EXIT_OPTIONS)!=RSB_ERR_NO_ERROR) goto err; if( it == maxit ) { printf("ERROR: hit iterations limit without convergence!"); errval=RSB_ERR_GENERIC_ERROR; } return EXIT_SUCCESS; err: rsb_perror(NULL,errval); return EXIT_FAILURE; } examples/fortran.F90: ! ! Copyright (C) 2008-2022 Michele Martone ! ! This file is part of librsb. ! ! librsb is free software; you can redistribute it and/or modify it ! under the terms of the GNU Lesser General Public License as published ! by the Free Software Foundation; either version 3 of the License, or ! (at your option) any later version. ! ! librsb is distributed in the hope that it will be useful, but WITHOUT ! ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ! FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public ! License for more details. ! ! You should have received a copy of the GNU Lesser General Public ! License along with librsb; see the file COPYING. ! If not, see <http://www.gnu.org/licenses/>. ! !> @file !! @brief Sparse BLAS-based usage: !! uscr_begin(), usgp(), ussp(), usmv(), ... !! \include fortran.F90 SUBROUTINE blas_sparse_mod_example(res) USE blas_sparse USE rsb ! For the second part of the example and RSB_IDX_KIND USE iso_c_binding IMPLICIT NONE INTEGER :: i, j INTEGER(KIND=RSB_BLAS_IDX_KIND) :: istat = 0, res TYPE(C_PTR),TARGET :: mtxAp = c_null_ptr ! matrix pointer INTEGER(C_INT) :: A INTEGER,PARAMETER :: transn = blas_no_trans INTEGER(KIND=RSB_IDX_KIND),PARAMETER :: incx = 1 INTEGER(KIND=RSB_IDX_KIND),PARAMETER :: incy = 1 REAL(KIND=8),parameter :: alpha = 3 ! Symmetric (declared via lower triangle) matrix based example, e.g.: ! 1 0 ! 1 1 ! declaration of VA,IA,JA !INTEGER,PARAMETER :: nr = 100 INTEGER(KIND=RSB_IDX_KIND),PARAMETER :: nr = 20 INTEGER(KIND=RSB_IDX_KIND),PARAMETER :: nc = nr INTEGER(KIND=RSB_IDX_KIND),PARAMETER :: nnz = (nr*(nr+1))/2 ! half the square INTEGER(KIND=RSB_IDX_KIND),PARAMETER :: nrhs = 1 INTEGER(KIND=RSB_IDX_KIND) :: nt = 0 INTEGER :: ic, ir ! For compatibility with (or compassion for) flang-13, we turn these three lines off: ! REAL(KIND=8),PARAMETER :: VA(nnz) = (/ ((1, ic=1,ir), ir=1,nr ) /) ! (/1, 1, 1/) ! INTEGER(KIND=RSB_IDX_KIND),PARAMETER :: IA(nnz) = (/ (((ir), ic=1,ir), ir=1,nr ) /) ! (/1, 2, 2/) ! INTEGER(KIND=RSB_IDX_KIND),PARAMETER :: JA(nnz) = (/ (((ic), ic=1,ir), ir=1,nr ) /) ! (/1, 1, 2/) ! and use these other ones instead, initializing VA,IA,JA later: REAL(KIND=8) :: va(nnz) INTEGER(KIND=RSB_IDX_KIND) :: IA(nnz) INTEGER(KIND=RSB_IDX_KIND) :: JA(nnz) REAL(KIND=8) :: x(nc,nrhs) = reshape((/((1), ic=1,nc*nrhs)/),[nc,nrhs]) ! reference x ! (/1, 1/) REAL(KIND=8),parameter :: cy(nr,nrhs) = reshape((/((alpha+alpha*nr), ir=1,nr*nrhs)/),[nr,nrhs]) ! reference cy after ! (/9, 9/) REAL(KIND=8) :: y(nr,nrhs) = reshape((/((alpha), ir=1,nr*nrhs)/),[nr,nrhs]) ! y will be overwritten ! (/3, 3/) va(:) = (/ ((1, ic=1,ir), ir=1,nr ) /) ! (/1, 1, 1/) ia(:) = (/ (((ir), ic=1,ir), ir=1,nr ) /) ! (/1, 2, 2/) ja(:) = (/ (((ic), ic=1,ir), ir=1,nr ) /) ! (/1, 1, 2/) ! First example part: pure blas_sparse code. res = 0 CALL duscr_begin(nr,nc,a,res) IF (res.NE.0) GOTO 9999 CALL ussp(a,blas_lower_symmetric,istat) IF (istat.NE.0) GOTO 9997 CALL ussp(a,blas_rsb_spmv_autotuning_on,istat) ! (experimental) turns auto-tuning + thread setting on IF (istat.NE.0) print *,"autotuning returned nonzero:", istat & &," ...did you enable autotuning ?" ! ! First style example CALL uscr_insert_entries(a,nnz,va,ia,ja,istat) IF (istat.NE.0) GOTO 9997 CALL uscr_end(a,istat) IF (istat.NE.0) GOTO 9997 ! CALL ussp(A,blas_rsb_duplicates_sum,istat) ! CALL uscr_insert_entries(A,nnz,VA,IA,JA,istat) ! uncomment this to activate add of coefficients to pattern CALL usgp(a,blas_rsb_spmv_autotuning_on,nt) ! (experimental) IF (nt.NE.0) print*,"autotuner chose ",nt," threads" CALL ussp(a,blas_rsb_spmv_autotuning_off,istat) ! (experimental) turns auto-tuning + thread setting off IF (istat.NE.0) GOTO 9997 DO j = 1, nrhs CALL usmv(transn,alpha,a,x(:,j),incx,y(:,j),incy,istat) END DO IF (istat.NE.0) GOTO 9997 ! DO j = 1, nrhs DO i = 1, nr IF (y(i,j).NE.cy(i,j)) print *, "first check results are not ok" IF (y(i,j).NE.cy(i,j)) GOTO 9997 END DO END DO ! y(:,:) = alpha ! reset ! ! Second style example CALL ussp(a,blas_rsb_autotune_next_operation,istat) ! (experimental) turns auto-tuning + thread setting on IF (istat.NE.0) GOTO 9997 DO j = 1, nrhs CALL usmv(transn,alpha,a,x(:,j),incx,y(:,j),incy,istat) END DO CALL usmm(blas_colmajor,transn,nrhs, alpha,a,x,nr,y,nc,istat) ! Equivalent to the above (as long as incx=incy=1). CALL usmm(blas_colmajor,transn,nrhs,-alpha,a,x,nr,y,nc,istat) ! Subtract the last usmm call contribution. IF (istat.NE.0) GOTO 9997 ! DO j = 1, nrhs DO i = 1, nr IF (y(i,j).NE.cy(i,j)) print *,"second check results are not ok" IF (y(i,j).NE.cy(i,j)) GOTO 9997 END DO END DO ! print *, "check results are ok" ! Second part of the example: access to the rsb.h interface via ! the ISO C Binding interface. mtxap = rsb_blas_get_mtx(a) ! get pointer to rsb structure (as in the rsb.h API) IF(nr.LT.5) istat = rsb_file_mtx_save(mtxap,c_null_char) ! write to stdout (only if matrix small enough) GOTO 9998 9997 res = -1 9998 CONTINUE CALL usds(a,istat) IF (istat.NE.0) res = -1 9999 CONTINUE end SUBROUTINE blas_sparse_mod_example ! Example loading a matrix from file and measuring SPMM. SUBROUTINE blas_sparse_io_example(res) USE blas_sparse USE rsb ! For rsb_blas_file_mtx_load USE iso_c_binding IMPLICIT NONE INTEGER(KIND=RSB_IDX_KIND) :: res ! note: same as RSB_BLAS_IDX_KIND INTEGER :: j INTEGER(KIND=RSB_BLAS_IDX_KIND) :: istat = 0 INTEGER :: A INTEGER,PARAMETER :: transn = blas_no_trans INTEGER(KIND=RSB_IDX_KIND),PARAMETER :: incx = 1 INTEGER(KIND=RSB_IDX_KIND),PARAMETER :: incy = 1 COMPLEX(KIND=8),PARAMETER :: alpha = 3 INTEGER(KIND=RSB_IDX_KIND) :: nr INTEGER(KIND=RSB_IDX_KIND) :: nc INTEGER(KIND=RSB_IDX_KIND) :: nz INTEGER(KIND=RSB_IDX_KIND) :: st INTEGER(KIND=RSB_IDX_KIND),PARAMETER :: nrhs = 4 COMPLEX(KIND=8), ALLOCATABLE, TARGET, DIMENSION(:,:) :: x COMPLEX(KIND=8), ALLOCATABLE, TARGET, DIMENSION(:,:) :: y CHARACTER(KIND=C_CHAR,LEN=7),TARGET :: filename = 'pd.mtx'//c_null_char INTEGER(C_SIGNED_CHAR) :: typecode = rsb_numerical_type_double_complex REAL(KIND=c_double) :: mvt,mmt,omt INTEGER(KIND=C_INT),TARGET::IZERO=0 res = 0 a = rsb_blas_file_mtx_load(filename, typecode); IF (a.EQ.blas_invalid_handle) GOTO 9997 CALL usgp(a,blas_num_rows,nr) CALL usgp(a,blas_num_cols,nc) CALL usgp(a,blas_num_nonzeros,nz) print*,"Read matrix ",filename(1:6)," ",nr,"x",nc,":",nz CALL usgp(a,blas_general,st) IF (st .EQ. 1) print*,"Matrix has no symmetry" CALL usgp(a,blas_upper_symmetric,st) IF (st .EQ. 1) print*,"Matrix is upper symmetric" CALL usgp(a,blas_upper_hermitian,st) IF (st .EQ. 1) print*,"Matrix is upper hermitian" ! ... IF (istat.NE.0) GOTO 9997 WRITE(*,'(a,i0)') "Using NRHS=",nrhs ALLOCATE( x(nc,nrhs)) ALLOCATE( y(nr,nrhs)) x = 1.0 y = 0.0 mvt = -rsb_time() DO j = 1, nrhs CALL usmv(transn,alpha,a,x(:,j),incx,y(:,j),incy,istat) END DO IF (istat.NE.0) GOTO 9997 mvt = mvt + rsb_time() WRITE(*,'(a,e12.4,a)') "Repeated USMV took ",mvt," s" y = 0.0 mmt = -rsb_time() CALL usmm(blas_colmajor,transn,nrhs, alpha,a,x,nr,y,nc,istat) IF (istat.NE.0) GOTO 9997 mmt = mmt + rsb_time() WRITE(*,'(a,e12.4,a)') "A single USMM took ",mmt," s" WRITE(*,'(a,g11.4,a)')"USMM-to-USMV speed ratio is is ", mvt/mmt, "x" print*,"Call auto-tuning routine.." ! Change IZERO value to 1 to get verbose tuning again. res = rsb_lib_set_opt(rsb_io_want_verbose_tuning,c_loc(izero)) IF (res.NE.0) GOTO 9997 CALL ussp(a,blas_rsb_autotune_next_operation,istat) ! (experimental) turns auto-tuning + thread setting on IF (istat.NE.0) GOTO 9997 CALL usmm(blas_colmajor,transn,nrhs, alpha,a,x,nr,y,nc,istat) IF (istat.NE.0) GOTO 9997 print*,"Repeat measurement." y = 0.0 omt = -rsb_time() CALL usmm(blas_colmajor,transn,nrhs, alpha,a,x,nr,y,nc,istat) IF (istat.NE.0) GOTO 9997 omt = omt + rsb_time() WRITE(*,'(a,e12.4,a)') "Tuned USMM took ",omt," s" WRITE(*,'(a,g11.4,a)')"Tuned-to-untuned speed ratio is is ",mmt/omt,"x" GOTO 9998 9997 res = -1 9998 CONTINUE CALL usds(a,istat) IF (istat.NE.0) res = -1 end SUBROUTINE blas_sparse_io_example PROGRAM main USE rsb, ONLY: rsb_lib_init, rsb_lib_exit, c_ptr, c_null_ptr,& & rsb_io_want_extra_verbose_interface,rsb_io_want_verbose_tuning,& & rsb_lib_set_opt,rsb_idx_kind ! USE blas_sparse, only: RSB_BLAS_IDX_KIND ! only if using long indices USE iso_c_binding IMPLICIT NONE INTEGER :: passed = 0, failed = 0 INTEGER(KIND=RSB_IDX_KIND) :: res ! note: same as RSB_BLAS_IDX_KIND !TYPE(C_PTR),PARAMETER :: EO = RSB_NULL_EXIT_OPTIONS !TYPE(C_PTR),PARAMETER :: IO = RSB_NULL_INIT_OPTIONS ! Note: using C_NULL_PTR instead of the previous lines because of http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59411 TYPE(C_PTR),PARAMETER :: EO = c_null_ptr TYPE(C_PTR),PARAMETER :: IO = c_null_ptr INTEGER(KIND=C_INT),TARGET::IONE=1 res = rsb_lib_init(io) res = rsb_lib_set_opt(rsb_io_want_verbose_tuning,c_loc(ione)) CALL blas_sparse_mod_example(res) IF (res.LT.0) failed = failed + 1 IF (res.EQ.0) passed = passed + 1 CALL blas_sparse_io_example(res) IF (res.LT.0) failed = failed + 1 IF (res.EQ.0) passed = passed + 1 res = rsb_lib_exit(eo) print *, "FAILED:", failed print *, "PASSED:", passed IF (failed .GT. 0) THEN stop 1 END IF END PROGRAM examples/fortran_rsb_fi.F90: ! ! Copyright (C) 2008-2022 Michele Martone ! ! This file is part of librsb. ! ! librsb is free software; you can redistribute it and/or modify it ! under the terms of the GNU Lesser General Public License as published ! by the Free Software Foundation; either version 3 of the License, or ! (at your option) any later version. ! ! librsb is distributed in the hope that it will be useful, but WITHOUT ! ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ! FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public ! License for more details. ! ! You should have received a copy of the GNU Lesser General Public ! License along with librsb; see the file COPYING. ! If not, see <http://www.gnu.org/licenses/>. ! !> @file. !! @brief RSB.F90-based usage: !! rsb_mtx_alloc_from_coo_const(), !! rsb_tune_spmm(), !! rsb_file_mtx_save(), !! rsb_spmv(), !! ... !! \include fortran_rsb_fi.F90 SUBROUTINE rsb_mod_example1(res) ! Example using an unsymmetric matrix specified as COO, and autotuning, built at once. USE rsb USE iso_c_binding IMPLICIT NONE INTEGER ::res INTEGER,TARGET :: istat = 0, i INTEGER :: transt = rsb_transposition_n ! INTEGER(KIND=RSB_IDX_KIND) :: incx = 1, incy = 1 REAL(KIND=8),target :: alpha = 3, beta = 1 ! 1 1 ! 1 1 ! declaration of VA,IA,JA INTEGER(KIND=RSB_IDX_KIND) :: nnz = 4 INTEGER(KIND=RSB_IDX_KIND) :: nr = 2 INTEGER(KIND=RSB_IDX_KIND) :: nc = 2 INTEGER(KIND=RSB_IDX_KIND) :: nrhs = 1 INTEGER :: order = rsb_flag_want_column_major_order ! rhs layout INTEGER :: flags = rsb_flag_noflags INTEGER(KIND=RSB_IDX_KIND),TARGET :: IA(4) = (/0, 1, 1,0/) INTEGER(KIND=RSB_IDX_KIND),TARGET :: JA(4) = (/0, 0, 1,1/) REAL(KIND=8),target :: va(4) = (/1,1,1,1/) REAL(KIND=8),target :: x(2) = (/1, 1/)! reference x REAL(KIND=8),target :: cy(2) = (/9, 9/)! reference cy after REAL(KIND=8),target :: y(2) = (/3, 3/)! y will be overwritten TYPE(C_PTR),TARGET :: mtxAp = c_null_ptr ! matrix pointer REAL(KIND=8) :: tmax = 2.0 ! tuning max time INTEGER :: titmax = 2 ! tuning max iterations INTEGER,TARGET :: ont = 0 ! optimal number of threads !TYPE(C_PTR),PARAMETER :: EO = RSB_NULL_EXIT_OPTIONS !TYPE(C_PTR),PARAMETER :: IO = RSB_NULL_INIT_OPTIONS ! Note: using C_NULL_PTR instead of the previous lines because of http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59411 TYPE(C_PTR),PARAMETER :: EO = c_null_ptr TYPE(C_PTR),PARAMETER :: IO = c_null_ptr INTEGER,TARGET :: errval res = 0 errval = rsb_lib_init(io) IF (errval.NE.rsb_err_no_error) GOTO 9997 mtxap = rsb_mtx_alloc_from_coo_const(c_loc(va),c_loc(ia),c_loc(ja)& &,nnz,& & rsb_numerical_type_double,nr,nc,1,1,flags,c_loc(istat)) IF (istat.NE.rsb_err_no_error) GOTO 9997 istat = rsb_file_mtx_save(mtxap,c_null_char) ! Structure autotuning: istat = rsb_tune_spmm(c_loc(mtxap),c_null_ptr,c_null_ptr,titmax,& & tmax,& & transt,c_loc(alpha),c_null_ptr,nrhs,order,c_loc(x),nr,& & c_loc(beta),c_loc(y),nc) IF (istat.NE.rsb_err_no_error) GOTO 9997 ! Thread count autotuning: istat = rsb_tune_spmm(c_null_ptr,c_null_ptr,c_loc(ont),titmax,& & tmax,& & transt,c_loc(alpha),mtxap,nrhs,order,c_loc(x),nr,c_loc(beta),& & c_loc(y),nc) print *, "Optimal number of threads:", ont y(:) = (/3, 3/)! restoring reference y (rsb_tune_spmm has overwritten it) IF (istat.NE.rsb_err_no_error) GOTO 9997 istat = rsb_file_mtx_save(mtxap,c_null_char) IF (istat.NE.rsb_err_no_error) GOTO 9997 istat = rsb_spmv(transt,c_loc(alpha),mtxap,c_loc(x),incx,& & c_loc(beta),c_loc(y),incy) IF (istat.NE.rsb_err_no_error) GOTO 9997 DO i = 1, 2 IF (y(i).NE.cy(i)) print *, "type=d dims=2x2 sym=g diag=g & &blocks=1x1 usmv alpha= 3 beta= 1 incx=1 incy=1 trans=n is not ok" IF (y(i).NE.cy(i)) GOTO 9997 END DO print*,"type=d dims=2x2 sym=g diag=g blocks=1x1 usmv alpha= 3& & beta= 1 incx=1 incy=1 trans=n is ok" IF ( res .NE.rsb_err_no_error) GOTO 9997 GOTO 9998 9997 res = -1 9998 CONTINUE mtxap = rsb_mtx_free(mtxap) IF (istat.NE.rsb_err_no_error) res = -1 ! 9999 CONTINUE errval=rsb_lib_exit(eo) ! librsb finalization IF (errval.NE.rsb_err_no_error)& & stop "error calling rsb_lib_exit" print *, "rsb module fortran test is ok" istat = rsb_perror(c_null_ptr,istat) end SUBROUTINE rsb_mod_example1 SUBROUTINE rsb_mod_example2(res) ! Example using an unsymmetric matrix specified as COO, and autotuning, built piecewise. USE rsb USE iso_c_binding IMPLICIT NONE INTEGER,TARGET :: errval INTEGER :: res INTEGER :: transt = rsb_transposition_n ! no transposition INTEGER(KIND=RSB_IDX_KIND) :: incX = 1, incb = 1 ! X, B vectors increment REAL(KIND=8),target :: alpha = 3,beta = 1 INTEGER(KIND=RSB_IDX_KIND) :: nnzA = 4, nra = 3, nca = 3 ! nonzeroes, rows, columns of matrix A INTEGER(KIND=RSB_IDX_KIND),TARGET :: IA(4) = (/1, 2, 3, 3/) ! row indices INTEGER(KIND=RSB_IDX_KIND),TARGET :: JA(4) = (/1, 2, 1, 3/) ! column indices INTEGER(C_SIGNED_CHAR) :: typecode = rsb_numerical_type_double INTEGER :: flags =rsb_flag_default_matrix_flags+rsb_flag_symmetric REAL(KIND=8),target :: va(4) = (/11.0, 22.0, 13.0, 33.0/) ! coefficients REAL(KIND=8),target :: x(3) = (/ 0, 0, 0/) REAL(KIND=8),target :: b(3) = (/-1.0, -2.0, -2.0/) TYPE(C_PTR),TARGET :: mtxAp = c_null_ptr TYPE(C_PTR) :: mtxApp = c_null_ptr REAL(KIND=8),target :: etime = 0.0 !TYPE(C_PTR),PARAMETER :: EO = RSB_NULL_EXIT_OPTIONS !TYPE(C_PTR),PARAMETER :: IO = RSB_NULL_INIT_OPTIONS ! Note: using C_NULL_PTR instead of the previous lines because of http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59411 TYPE(C_PTR),PARAMETER :: EO = c_null_ptr TYPE(C_PTR),PARAMETER :: IO = c_null_ptr errval = rsb_lib_init(io) ! librsb initialization IF (errval.NE.rsb_err_no_error) & & stop "error calling rsb_lib_init" #if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 5) #define RSB_SKIP_BECAUSE_OLD_COMPILER 1 #endif #ifndef RSB_SKIP_BECAUSE_OLD_COMPILER mtxap = rsb_mtx_alloc_from_coo_begin(nnza,typecode,nra,nca,flags,& & c_loc(errval)) ! begin matrix creation errval = rsb_mtx_set_vals(mtxap,& & c_loc(va),c_loc(ia),c_loc(ja),nnza,flags) ! insert some nonzeroes mtxapp = c_loc(mtxap) ! Old compilers like e.g.: Gfortran 4.4.7 will NOT compile this. IF (errval.NE.rsb_err_no_error) & & stop "error calling rsb_mtx_set_vals" errval = rsb_mtx_alloc_from_coo_end(mtxapp) ! end matrix creation IF (errval.NE.rsb_err_no_error) & & stop "error calling rsb_mtx_alloc_from_coo_end" errval = rsb_spmv(transt,c_loc(alpha),mtxap,c_loc(x),& & incx,c_loc(beta),c_loc(b),incb) ! X := X + (3) * A * B IF (errval.NE.rsb_err_no_error)& & stop "error calling rsb_spmv" mtxap = rsb_mtx_free(mtxap) ! destroy matrix ! The following is optional and depends on configure options, so it is allowed to fail errval = rsb_lib_get_opt(rsb_io_want_librsb_etime,c_loc(etime)) IF (errval.EQ.rsb_err_no_error)& & print*,"Time spent in librsb is:",etime ! IF (errval.NE.0)STOP "error calling rsb_lib_get_opt" errval = rsb_err_no_error IF (errval.NE.rsb_err_no_error) & & stop "error calling rsb_mtx_free" #else print*,"You have an old Fortran compiler not supporting C_LOC." print*,"Skipping a part of the test" #endif errval=rsb_lib_exit(eo) ! librsb finalization IF (errval.NE.rsb_err_no_error)& & stop "error calling rsb_lib_exit" print *, "rsb module fortran test is ok" res = errval end SUBROUTINE rsb_mod_example2 SUBROUTINE rsb_mod_example3(res) ! Example using a symmetric matrix specified as CSR, and autotuning, built at once. USE rsb USE iso_c_binding IMPLICIT NONE INTEGER ::res INTEGER,TARGET :: istat = 0, i INTEGER :: transt = rsb_transposition_n ! INTEGER(KIND=RSB_IDX_KIND) :: incx = 1, incy = 1 REAL(KIND=8),target :: alpha = 4, beta = 1 ! 11 21 ! 21 22 ! declaration of VA,IP,JA INTEGER(KIND=RSB_IDX_KIND), PARAMETER :: nnz = 3 INTEGER(KIND=RSB_IDX_KIND), PARAMETER :: nr = 2 INTEGER(KIND=RSB_IDX_KIND), PARAMETER :: nc = 2 INTEGER(KIND=RSB_IDX_KIND), PARAMETER :: nrhs = 1 INTEGER :: order = rsb_flag_want_column_major_order ! rhs layout INTEGER :: flags = rsb_flag_noflags + rsb_flag_symmetric + & & rsb_flag_fortran_indices_interface ! optional flags INTEGER(KIND=RSB_IDX_KIND),TARGET :: IP(3) = (/1, 2, 4/) INTEGER(KIND=RSB_IDX_KIND),TARGET :: JA(3) = (/1, 1, 2/) REAL(KIND=8),target :: va(3) = (/11,21,22/) ! lower triangle coefficients REAL(KIND=8),target :: x(2) = (/1, 2/)! reference x REAL(KIND=8),target :: cy(2) = (/215.0, 264.0/)! reference cy after REAL(KIND=8),target :: y(2) = (/3, 4/)! y will be overwritten TYPE(C_PTR),TARGET :: mtxAp = c_null_ptr ! matrix pointer REAL(KIND=8) :: tmax = 2.0 ! tuning max time INTEGER :: titmax = 2 ! tuning max iterations INTEGER,TARGET :: ont = 0 ! optimal number of threads TYPE(C_PTR),PARAMETER :: EO = c_null_ptr TYPE(C_PTR),PARAMETER :: IO = c_null_ptr INTEGER,TARGET :: errval errval = rsb_lib_init(io) ! librsb initialization IF (errval.NE.rsb_err_no_error) & & stop "error calling rsb_lib_init" res = 0 mtxap = rsb_mtx_alloc_from_csr_const(c_loc(va),c_loc(ip),c_loc(ja)& &,nnz,rsb_numerical_type_double,nr,nc,1,1,flags,c_loc(istat)) IF (istat.NE.rsb_err_no_error) GOTO 9997 istat = rsb_file_mtx_save(mtxap,c_null_char) ! Structure autotuning: istat = rsb_tune_spmm(c_loc(mtxap),c_null_ptr,c_null_ptr,titmax,& & tmax,& & transt,c_loc(alpha),c_null_ptr,nrhs,order,c_loc(x),nr,& & c_loc(beta),c_loc(y),nc) IF (istat.NE.rsb_err_no_error) GOTO 9997 ! Thread count autotuning: istat = rsb_tune_spmm(c_null_ptr,c_null_ptr,c_loc(ont),titmax,& & tmax,& & transt,c_loc(alpha),mtxap,nrhs,order,c_loc(x),nr,c_loc(beta),& & c_loc(y),nc) print *, "Optimal number of threads:", ont y(:) = (/3, 4/)! restoring reference y (rsb_tune_spmm has overwritten it) IF (istat.NE.rsb_err_no_error) GOTO 9997 istat = rsb_file_mtx_save(mtxap,c_null_char) IF (istat.NE.rsb_err_no_error) GOTO 9997 istat = rsb_spmv(transt,c_loc(alpha),mtxap,c_loc(x),incx,& & c_loc(beta),c_loc(y),incy) print *, y IF (istat.NE.rsb_err_no_error) GOTO 9997 DO i = 1, 2 IF (y(i).NE.cy(i)) print *, "type=d dims=2x2 sym=s diag=g & &blocks=1x1 usmv alpha= 4 beta= 1 incx=1 incy=1 trans=n is not ok" IF (y(i).NE.cy(i)) GOTO 9997 END DO print*,"type=d dims=2x2 sym=s diag=g blocks=1x1 usmv alpha= 4& & beta= 1 incx=1 incy=1 trans=n is ok" GOTO 9998 errval=rsb_lib_exit(eo) ! librsb finalization IF (errval.NE.rsb_err_no_error)& & stop "error calling rsb_lib_exit" print *, "rsb module fortran test is ok" 9997 res = -1 9998 CONTINUE mtxap = rsb_mtx_free(mtxap) IF (istat.NE.rsb_err_no_error) res = -1 ! 9999 CONTINUE istat = rsb_perror(c_null_ptr,istat) end SUBROUTINE rsb_mod_example3 PROGRAM main USE rsb IMPLICIT NONE INTEGER :: res = rsb_err_no_error, passed = 0, failed = 0 CALL rsb_mod_example1(res) IF (res.LT.0) failed = failed + 1 IF (res.EQ.0) passed = passed + 1 CALL rsb_mod_example2(res) IF (res.LT.0) failed = failed + 1 IF (res.EQ.0) passed = passed + 1 CALL rsb_mod_example3(res) IF (res.LT.0) failed = failed + 1 IF (res.EQ.0) passed = passed + 1 print *, "FAILED:", failed print *, "PASSED:", passed IF (failed.GT.0) THEN stop 1 END IF END PROGRAM examples/backsolve.c: /* Copyright (C) 2008-2021 Michele Martone This file is part of librsb. librsb is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. librsb is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with librsb; see the file COPYING. If not, see <http://www.gnu.org/licenses/>. */ /*! \ingroup rsb-examples @file @author Michele Martone @brief C triangular solve example program. Uses #rsb_spsv(),#rsb_tune_spsm(). Based on <rsb.h>. \include hello.c */ #include <rsb.h> /* librsb header to include */ #include <stdio.h> /* printf() */ int main(const int argc, char * const argv[]) { /*! A Hello-RSB program. This program shows how to use the rsb.h interface correctly to: - initialize the library using #rsb_lib_init() - allocate (build) a single sparse matrix in the RSB format using #rsb_mtx_alloc_from_coo_const(), with implicit diagonal - print information obtained via #rsb_mtx_get_info_str() - multiply the triangular matrix using #rsb_spmv() - autotune the matrix for rsb_spsv with #rsb_tune_spsm() - solve the triangular system using #rsb_spsv() - deallocate the matrix using #rsb_mtx_free() - finalize the library using #rsb_lib_exit() In this example, we use #RSB_DEFAULT_TYPE as matrix type. This type depends on what was configured at library build time. * */ const int bs = RSB_DEFAULT_BLOCKING; const int brA = bs, bcA = bs; const RSB_DEFAULT_TYPE one = 1; const rsb_type_t typecode = RSB_NUMERICAL_TYPE_DEFAULT; const rsb_nnz_idx_t nnzA = 7; /* matrix nonzeroes count */ const rsb_coo_idx_t nrA = 6; /* matrix rows count */ const rsb_coo_idx_t ncA = 6; /* matrix columns count */ /* nonzero row indices coordinates: */ const rsb_coo_idx_t IA[] = {1,2,3,4,5,6,1}; /* nonzero column indices coordinates: */ const rsb_coo_idx_t JA[] = {1,2,3,4,5,6,6}; const RSB_DEFAULT_TYPE VA[] = {1,1,1,1,1,1,1};/*values of nonzeroes*/ RSB_DEFAULT_TYPE X[] = { 0,0,0,0,0,0 }; /* X vector's array */ const RSB_DEFAULT_TYPE B[] = { 1,1,1,1,1,1 }; /* B */ struct rsb_mtx_t *mtxAp = NULL; /* matrix structure pointer */ char ib[200]; int i; rsb_err_t errval = RSB_ERR_NO_ERROR; const rsb_int_t wvat = 1; /* want verbose autotuning; see documentation of RSB_IO_WANT_VERBOSE_TUNING */ printf("Hello, RSB!\n"); printf("Initializing the library...\n"); if((errval = rsb_lib_init(RSB_NULL_INIT_OPTIONS)) != RSB_ERR_NO_ERROR) { printf("Error initializing the library!\n"); goto err; } printf("Correctly initialized the library.\n"); errval = rsb_lib_set_opt(RSB_IO_WANT_VERBOSE_TUNING, &wvat ); if( (errval) != RSB_ERR_NO_ERROR ) { printf("Error setting option!\n"); goto err; } mtxAp = rsb_mtx_alloc_from_coo_const( VA,IA,JA,nnzA,typecode,nrA,ncA,brA,bcA, RSB_FLAG_DEFAULT_RSB_MATRIX_FLAGS /* force rsb */ | RSB_FLAG_DUPLICATES_SUM/* sum dups */ | RSB_FLAG_UNIT_DIAG_IMPLICIT/* ask diagonal implicit */ | RSB_FLAG_TRIANGULAR /* need triangle for spsv */ | RSB_FLAG_FORTRAN_INDICES_INTERFACE /* treat indices as 1-based */ , &errval); if((!mtxAp) || (errval != RSB_ERR_NO_ERROR)) { printf("Error while allocating the matrix!\n"); goto err; } printf("Correctly allocated a matrix with %ld nonzeroes.\n", (long int)nnzA); printf("Summary information of the matrix:\n"); /* print out the matrix summary information */ rsb_mtx_get_info_str(mtxAp,"RSB_MIF_MATRIX_INFO__TO__CHAR_P", ib,sizeof(ib)); printf("%s",ib); printf("\nMatrix printout:\n"); rsb_file_mtx_save(mtxAp, NULL); if((errval = rsb_spmv(RSB_TRANSPOSITION_N,&one,mtxAp,B,1,&one,X,1)) != RSB_ERR_NO_ERROR ) { printf("Error performing a multiplication!\n"); goto err; } printf("\nWe have a unitary vector:\n"); rsb_file_vec_save(NULL, typecode, B, nrA); printf("\nMultiplying matrix by unitary vector we get:\n"); rsb_file_vec_save(NULL, typecode, X, nrA); errval = rsb_tune_spsm(&mtxAp, NULL, NULL, 0, 0, RSB_TRANSPOSITION_N, &one, NULL, 1, RSB_FLAG_WANT_COLUMN_MAJOR_ORDER, NULL, nrA, NULL, NULL, nrA); if( (errval) != RSB_ERR_NO_ERROR ) { printf("Error performing autotuning!\n"); goto err; } if((errval = rsb_spsv(RSB_TRANSPOSITION_N,&one,mtxAp,X,1,X,1)) != RSB_ERR_NO_ERROR ) { printf("Error performing triangular solve!\n"); goto err; } printf("\nBacksolving we should get a unitary vector:\n"); rsb_file_vec_save(NULL, typecode, X, nrA); for(i=0;i<nrA;++i) if(X[i]!=one) { printf("Warning! Result vector not unitary!:\n"); errval = RSB_ERR_INTERNAL_ERROR; goto err; } printf("All done.\n"); rsb_mtx_free(mtxAp); printf("Correctly freed the matrix.\n"); if((errval = rsb_lib_exit(RSB_NULL_EXIT_OPTIONS)) != RSB_ERR_NO_ERROR) { printf("Error finalizing the library!\n"); goto err; } printf("Correctly finalized the library.\n"); printf("Program terminating with no error.\n"); return EXIT_SUCCESS; err: rsb_perror(NULL,errval); printf("Program terminating with error.\n"); return EXIT_FAILURE; } examples/bench.sh: #!/bin/bash # # Copyright (C) 2008-2022 Michele Martone # # This file is part of librsb. # # librsb is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published # by the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # librsb is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public # License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with librsb; see the file COPYING. # If not, see <http://www.gnu.org/licenses/>. # Benchmark rsbench and postprocess results. # \ingroup rsb-examples # @file # @author Michele Martone # @brief Benchmark invocation from shell script. # set -e set -x which rsbench BRF=test.rpr # invoke rsbench and produce a performance record, using all types and one thread rsbench -oa -Ob --bench --lower 100 --as-symmetric --types ':' -n 1 --notranspose --compare-competitors --verbose --verbose --write-performance-record=${BRF} # examine tuning renderings (produced by --verbose --verbose) ls -ltr ${BRF/.rpr/}-tuning* # convert the performance record to text form rsbench --read-performance-record ${BRF} > ${BRF/rpr/txt} ls -ltr ${BRF/rpr/txt} # convert the performance record to LaTeX table document form RSB_PR_WLTC=2 RSB_PR_SR=0 rsbench --read-performance-record ${BRF} > ${BRF/rpr/tex} which latex || exit 0 # to compile LaTeX document which kpsepath || exit 0 # to check LaTeX packages find `kpsepath tex | sed 's/!!//g;s/:/\n/g;'` -name sciposter.cls || exit 0 # need sciposter class, usually in texlive-science find `kpsepath tex | sed 's/!!//g;s/:/\n/g;'` -name translator.sty || exit 0 # need sciposter class, usually in texlive-latex-recommended # convert the LaTeX table into a DVI (may as well use pdflatex for PDF) latex -interaction=batchmode -file-line-error ${BRF/rpr/tex} # convert the performance record to GNUPLOT plots which gnuplot || exit 0 RSB_PRD_STYLE_PLT_PFN=${BRF/rpr/} RSB_PRD_STYLE_PLT_FMT=1 RSB_PR_SR=2 rsbench --read-performance-record ${BRF} > ${BRF/rpr/gnu} # convert the GNUPLOT plots into PDF ls -ltr ${BRF/rpr/gnu} gnuplot ${BRF/rpr/gnu} # convert the performance record to GNUPLOT plots, different way RSB_PRD_STYLE_PLT_PFN=${BRF/rpr/} RSB_PRD_STYLE_PLT_FMT= RSB_PR_SR=2 rsbench --read-performance-record ${BRF} > ${BRF/rpr/gnu} gnuplot ${BRF/rpr/gnu} ls -ltr ${BRF/.rpr/}*.png ls -ltr ${BRF/.rpr/}*.eps ls -ltr ${BRF} ${BRF/rpr/tex} ${BRF/rpr/dvi} ${BRF/rpr/txt} # clean up rm ${BRF/rpr/}{aux,log,out,gnu} rm ${BRF/.rpr/}*{.png,.eps} rm ${BRF} ${BRF/rpr/tex} ${BRF/rpr/dvi} ${BRF/rpr/txt} exit Most of the snippets in the documentation come from examples/snippets.c.
Author
librsb was written by Michele Martone; this documentation has been generated by Doxygen.
SEE ALSO
rsb-examples rsb-spblas.h rsb.h rsb.hpp