Intel® oneAPI Math Kernel Library
Ask questions and share information with other developers who use Intel® Math Kernel Library.

Sparse index base for export csr

marcsolal
Beginner
969 Views

I do not understand how is working the sparse_index_base in mkl_sparse_d_export_csr. It looks to me that the exported arrays are independant of what is chosen for sparse_index_base parameter. To explain, I am generating two csr sparse matrices using base one indexing. When I am exporting the csr arrays for one matrix the result always corresponds to one indexing independently of the parameter used for mkl_sparse_d_export_csr (SPARSE_INDEX_BASE_ZERO or SPARSE_INDEX_BASE_ONE). I am multiplying my two matrices using mkl_sparse_spmm. It looks the result of the multiplication is always in index base 0 independently of the parameter for the exporting function.

These are my results. The product is always in base 0 and the original matrix is exported in the same base it was generated. Can you please clarify, This is confusing. I am also attaching my code.

Thanks,

Marc

RESULTS:

PRODUCT

 row_start    0 3 7 12 17 22 27 32 37 41 
 row_end      3 7 12 17 22 27 32 37 41 44 
 col_indx     0 1 2 0 1 2 3 0 1 2 3 4 1 2 3 4 5 2 3 4 5 6 3 4 5 6 7 4 5 6 7 8 5 6 7 8 9 6 7 8 9 7 8 9 

MATRIX2
 row_start    1 4 8 13 18 23 28 33 38 42 
 row_end      4 8 13 18 23 28 33 38 42 45 
 col_indx     1 2 3 1 2 3 4 1 2 3 4 5 2 3 4 5 6 3 4 5 6 7 4 5 6 7 8 5 6 7 8 9 6 7 8 9 10 7 8 9 10 8 9 10 

 

#include <iostream>
using namespace std;
#include "mkl.h"
int main() {
	MKL_INT nRows=10;
	MKL_INT* rows=new MKL_INT[nRows];
	MKL_INT* cols=new MKL_INT [nRows];
//	MKL_Complex16* permutData=new MKL_Complex16[nRows];
	double *permutData=new double[nRows];
	for (int i=0;i<nRows;i++){
		rows=i+1;
		cols=i+1;
		permutData=1.0;
	}

	sparse_matrix_t MATRIX1;
	sparse_status_t ok=mkl_sparse_d_create_coo (&MATRIX1,SPARSE_INDEX_BASE_ONE,nRows,nRows, nRows, rows,cols,permutData);
	if (ok==SPARSE_STATUS_SUCCESS){
		cout<<"Matrix done\n";
		cout.flush();
	}
	else{
		cout<<"Problem in handle creation";
		cout.flush();
	}

	MKL_INT* rows2=new MKL_INT[5*nRows];
	MKL_INT* cols2=new MKL_INT [5*nRows];
	double *Data=new double[5*nRows];
	MKL_INT nnz=0;
	for (int i=0;i<10;i++){
		for (int j=0;j<10;j++){
			if (abs(i-j)<=2){
				rows2[nnz]=i+1;
				cols2[nnz]=j+1;
				Data[nnz]=i-j;
				nnz++;
			}
		}
	}
	cout<<"nnz :"<<nnz<<'\n';
	sparse_matrix_t MATRIX2;
	ok=mkl_sparse_d_create_coo (&MATRIX2,SPARSE_INDEX_BASE_ONE,nRows,nRows, nnz, rows2,cols2,Data);
	if (ok==SPARSE_STATUS_SUCCESS){
		cout<<"Matrix done\n";
		cout.flush();
	}
	else{
		cout<<"Problem in handle creation";
		cout.flush();
	}
	sparse_matrix_t MATRIX1CSR;
	ok=mkl_sparse_convert_csr(MATRIX1,SPARSE_OPERATION_NON_TRANSPOSE,&MATRIX1CSR);
	if (ok!=SPARSE_STATUS_SUCCESS){
		cout<<"Problem in conversion\n";
		cout.flush();
	}
	sparse_matrix_t MATRIX2CSR;
	ok=mkl_sparse_convert_csr(MATRIX2,SPARSE_OPERATION_NON_TRANSPOSE,&MATRIX2CSR);
	if (ok!=SPARSE_STATUS_SUCCESS){
		cout<<"Problem in conversion\n";
		cout.flush();
	}
	sparse_matrix_t PRODUCT;
	ok= mkl_sparse_spmm(SPARSE_OPERATION_NON_TRANSPOSE,MATRIX1CSR,MATRIX2CSR,&PRODUCT);
	if (ok!=SPARSE_STATUS_SUCCESS){
		cout<<"Problem in matrix export\n";
		cout.flush();
	}
	MKL_INT nRowsPROD,nColsPROD;
	MKL_INT* rows_start;
	MKL_INT* rows_end;
	MKL_INT* col_indx;
	double* values;
	sparse_index_base_t indexing=SPARSE_INDEX_BASE_ONE;
	ok=mkl_sparse_d_export_csr(PRODUCT,&indexing,&nRowsPROD,&nColsPROD,&rows_start,&rows_end,&col_indx,&values);
	cout<<"\nPRODUCT";
	cout<<"\n row_start\t";
	for (int i=0;i<nRowsPROD;i++){
		cout<<rows_start<<" ";
	}
	cout<<"\n row_end  \t";
	for (int i=0;i<nRowsPROD;i++){
		cout<<rows_end<<" ";
	}
	cout<<"\n col_indx \t";
	for (int i=0;i<nnz;i++){
		cout<<col_indx<<" ";
	}

	cout<<'\n';

	MKL_INT nRows2,nCols2;
	MKL_INT* rows_start2;
	MKL_INT* rows_end2;
	MKL_INT* col_indx2;
	double* values2;
	sparse_index_base_t indexing2=SPARSE_INDEX_BASE_ZERO;
	ok=mkl_sparse_d_export_csr(MATRIX2CSR,&indexing2,&nRows2,&nCols2,&rows_start2,&rows_end2,&col_indx2,&values2);
	cout<<"\nMATRIX2";
	cout<<"\n row_start\t";
	for (int i=0;i<nRows2;i++){
		cout<<rows_start2<<" ";
	}
	cout<<"\n row_end  \t";
	for (int i=0;i<nRows2;i++){
		cout<<rows_end2<<" ";
	}
	cout<<"\n col_indx \t";
	for (int i=0;i<nnz;i++){
		cout<<col_indx2<<" ";
	}
	cout<<'\n';
	return 0;
}
0 Kudos
6 Replies
Ying_H_Intel
Employee
969 Views

Hello,

Thanks for the report. It is real good question.  the parameter indexing in the function mkl_sparse_d_export_csr was output parameter, not a input parameter. so it seems the function always return 0 based csr matrix.  We will check in detail and get back to you later.

Best Regards,

Ying

0 Kudos
Alexander_K_Intel2
969 Views

Hi,

Ying is correct, indexing in export routines is output parameter so it filled after export execution it correspond to indexing that used for internal data

Thanks,

Alex 

0 Kudos
marcsolal
Beginner
969 Views

I did not see it. It was obvious to me it had to be an input parameter to let me decide the indexing I like. It appears that he indexing is changed to 1 based when multiplying two sparse matrices. I will add a test inside my code.

Thanks a lot,

Marc 

0 Kudos
marcsolal
Beginner
969 Views

 Another question on the same topic. I am exporting csr to use my matrix in PARDISO. Is there a way to make sure the column indexes are sorted or do I need to sort it myself after exporting.

Thanks

0 Kudos
Alexander_K_Intel2
969 Views

Hi,

In current version of MKL you need to sort csr format to garantee correctness of input pardiso data

Thanks,

Alex 

0 Kudos
marcsolal
Beginner
969 Views

I understand that. Is there any way to do this sorting inspector executor interface to sparse blas routines? I see that many regular sparse blas routines have sorting options. It would be nice to have something similar when using inspector executor.

Thanks,

Marc

0 Kudos
Reply