- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi all,
I have two questions about memory management of sparse_matrix_t :
1. When I create a matrix handle using routine mkl_sparse_?_create_csr, the handle will copy all data to new memory blocks? Or it only save the pointers in handle? If it copy all data to new block, and the routine mkl_sparse_destroy will free these memory blocks or not ?
2. As the result of routine mkl_sparse_spmm , is it created in mkl routines?I will call destroy routine for it ? And then the internal data like column indexes array and matrix values array should be free expicit or not?
By the way, I found routines declared in header file : mkl_sparse_?_set_value, but they are not found in manual. And there are comment about these routines:
/* update existing value in the matrix ( for internal storage only, should not work with user-allocated matrices) */
It means I can not using them in my code?
Thanks,
Tianxiong Lu
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
Please see my comments below
Thanks,
Alex
> When I create a matrix handle using routine mkl_sparse_?_create_csr, the handle will copy all data to new memory blocks? Or it only save the pointers in handle?
It save pointer in handle only.
> 2. As the result of routine mkl_sparse_spmm , is it created in mkl routines?I will call destroy routine for it ? And then the internal data like column indexes array and matrix values array should be free expicit or not?
Didn't got it. This function return sparse_matrix_t *C which contain result of multiplication and could be used in further routines and/or export routine.
> By the way, I found routines declared in header file : mkl_sparse_?_set_value, but they are not found in manual. And there are comment about these routines:
/* update existing value in the matrix ( for internal storage only, should not work with user-allocated matrices) */
It means I can not using them in my code?
This function allow you to change value of matrix in sparse_matrix structure so i don't see any barrier to use it in your code
Thanks,
Tianxiong Lu
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Alex,
1. What does the means "should not work with user-allocated matrices“ ?Maybe I can ignore it.
2. -- Didn't got it. This function return sparse_matrix_t *C which contain result of multiplication and could be used in further routines and/or export routine.
Did you mean that MKL will free struct C ? Or I should destroy it while program finished.
Thanks,
Tianxiong Lu
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
1. What does the means "should not work with user-allocated matrices“ ?Maybe I can ignore it. - yes, just ignore i
2. Did you mean that MKL will free struct C.
In the end of the program you need to call mkl_sparse_destroy ( C ) routine to free struct C
Thanks,
Alex
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Tianxiong,
Just update the thread.
There is new example, sparse_sppm.c added in MKL 11.3 update 3, in which we show how to use mkl_sparse_spmm and mkl_sparse_export_csr.
There also is shown how to work with attendant arrays and memory for them.
You are welcomed to try it.
Cheers,
Ying
/*******************************************************************************
* Copyright 2013-2016 Intel Corporation All Rights Reserved.
*
* The source code, information and material ("Material") contained herein is
* owned by Intel Corporation or its suppliers or licensors, and title to such
* Material remains with Intel Corporation or its suppliers or licensors. The
* Material contains proprietary information of Intel or its suppliers and
* licensors. The Material is protected by worldwide copyright laws and treaty
* provisions. No part of the Material may be used, copied, reproduced,
* modified, published, uploaded, posted, transmitted, distributed or disclosed
* in any way without Intel's prior express written permission. No license under
* any patent, copyright or other intellectual property rights in the Material
* is granted to or conferred upon you, either expressly, by implication,
* inducement, estoppel or otherwise. Any license under such intellectual
* property rights must be express and approved by Intel in writing.
*
* Unless otherwise agreed by Intel in writing, you may not remove or alter this
* notice or any other notice embedded in Materials by Intel or Intel's
* suppliers or licensors in any way.
*******************************************************************************/
/******************************************************************************
*
* Consider the matrix A
*
* | 10 11 0 0 0 |
* | 0 0 12 13 0 |
* A = | 15 0 0 0 14 |,
* | 0 16 17 0 0 |
* | 0 0 0 18 19 |
*
* and diagonal matrix B
*
* | 5 0 0 0 0 |
* | 0 6 0 0 0 |
* B = | 0 0 7 0 0 |.
* | 0 0 0 8 0 |
* | 0 0 0 0 9 |
*
* Both matrices A and B are stored in a zero-based compressed sparse row (CSR) storage
* scheme with three arrays (see 'Sparse Matrix Storage Schemes' in the
* Intel Math Kernel Library Developer Reference) as follows:
*
* values_A = ( 10 11 12 13 15 14 16 17 18 19 )
* columns_A = ( 0 1 2 3 0 4 1 2 3 4 )
* rowIndex_A = ( 0 2 4 6 8 10 )
*
* values_B = ( 5 6 7 8 9 )
* columns_B = ( 0 1 2 3 4 )
* rowIndex_B = ( 0 1 2 3 4 5 )
*
* The example computes two scalar products :
*
* < (A*B)*x , y > = left, using MKL_SPARSE_D_SPMM and CBLAS_DDOT.
* < B*x , (A^t)*y > = right, using MKL_SPARSE_D_MV and CBLAS_DDOT.
*
* These products should result in the same value. To obtain matrix C,
* use MKL_SPARSE_D_EXPORT_CSR and print the result.
*
******************************************************************************/
#include <stdio.h>
#include <assert.h>
#include <math.h>
#include "mkl.h"
int main() {
#define M 5
#define NNZ 10
#define ALIGN 128
/* To avoid constantly repeating the part of code that checks inbound SparseBLAS functions' status,
use macro CALL_AND_CHECK_STATUS */
#define CALL_AND_CHECK_STATUS(function, error_message) do { \
if(function != SPARSE_STATUS_SUCCESS) \
{ \
printf(error_message); fflush(0); \
status = 1; \
goto memory_free; \
} \
} while(0)
/* Declaration of values */
double *values_A = NULL, *values_B = NULL, *values_C = NULL;
MKL_INT *columns_A = NULL, *columns_B = NULL, *columns_C = NULL;
MKL_INT *rowIndex_A = NULL, *rowIndex_B = NULL, *pointerB_C = NULL, *pointerE_C = NULL;
double *rslt_mv = NULL, *rslt_mv_trans = NULL, *x = NULL, *y = NULL;
double left, right, residual;
MKL_INT rows, cols, i, j, ii, status;
sparse_index_base_t indexing;
struct matrix_descr descr_type_gen;
sparse_matrix_t csrA = NULL, csrB = NULL, csrC = NULL;
/* Allocation of memory */
values_A = (double *)mkl_malloc(sizeof(double) * NNZ, ALIGN);
columns_A = (MKL_INT *)mkl_malloc(sizeof(MKL_INT) * NNZ, ALIGN);
rowIndex_A = (MKL_INT *)mkl_malloc(sizeof(MKL_INT) * (M + 1), ALIGN);
values_B = (double *)mkl_malloc(sizeof(double) * M, ALIGN);
columns_B = (MKL_INT *)mkl_malloc(sizeof(MKL_INT) * M, ALIGN);
rowIndex_B = (MKL_INT *)mkl_malloc(sizeof(MKL_INT) * (M + 1), ALIGN);
x = (double *)mkl_malloc(sizeof(double) * M, ALIGN);
y = (double *)mkl_malloc(sizeof(double) * M, ALIGN);
rslt_mv = (double *)mkl_malloc(sizeof(double) * M, ALIGN);
rslt_mv_trans = (double *)mkl_malloc(sizeof(double) * M, ALIGN);
/* Set values of the variables*/
descr_type_gen.type = SPARSE_MATRIX_TYPE_GENERAL;
status = 0, ii = 0;
//Matrix A
for( i = 0; i < NNZ; i++ )
values_A = i + 10;
for( i = 0; i < NNZ; i++ )
columns_A = i % 5;
rowIndex_A[0] = 0;
for( i = 1; i < M + 1; i++ )
rowIndex_A = rowIndex_A[i - 1] + 2;
//Matrix B
for( i = 0; i < M; i++ )
values_B = i + 5;
for( i = 0; i < M; i++ )
columns_B = i % 5;
for( i = 0; i < M + 1; i++ )
rowIndex_B = i;
//Vectors x and y
for( i = 0; i < M; i++ )
{
x = 1.0; y = 1.0;
}
/* Printing usable data */
printf( "\n\n_______________Example program for MKL_SPARSE_D_SPMM_________________\n\n" );
printf( " COMPUTE A * B = C, where matrices are stored in CSR format\n" );
printf( "\n MATRIX A:\nrow# : (value, column) (value, column)\n" );
for( i = 0; i < M; i++ )
{
printf("row#%d:", i + 1); fflush(0);
for( j = rowIndex_A; j < rowIndex_A[i+1]; j++ )
{
printf(" (%5.0f, %6d)", values_A[ii], columns_A[ii] ); fflush(0);
ii++;
}
printf( "\n" );
}
ii = 0;
printf( "\n MATRIX B:\nrow# : (value, column)\n" );
for( i = 0; i < M; i++ )
{
printf("row#%d:", i + 1); fflush(0);
for( j = rowIndex_B; j < rowIndex_B[i+1]; j++ )
{
printf(" (%5.0f, %6d)", values_B[ii], columns_B[ii] ); fflush(0);
ii++;
}
printf( "\n" );
}
printf( "\n Check the resultant matrix C, using two scalar products\n" );
printf( " (values of these scalar products must match).\n" );
/* Prepare arrays, which are related to matrices.
Create handles for matrices A and B stored in CSR format */
CALL_AND_CHECK_STATUS(mkl_sparse_d_create_csr( &csrA, SPARSE_INDEX_BASE_ZERO, M, M, rowIndex_A, rowIndex_A+1, columns_A, values_A ),
"Error after MKL_SPARSE_D_CREATE_CSR, csrA \n");
CALL_AND_CHECK_STATUS(mkl_sparse_d_create_csr( &csrB, SPARSE_INDEX_BASE_ZERO, M, M, rowIndex_B, rowIndex_B+1, columns_B, values_B ),
"Error after MKL_SPARSE_D_CREATE_CSR, csrB \n");
/* Compute C = A * B */
CALL_AND_CHECK_STATUS(mkl_sparse_spmm( SPARSE_OPERATION_NON_TRANSPOSE, csrA, csrB, &csrC ),
"Error after MKL_SPARSE_SPMM \n");
/* Analytic Routines for MKL_SPARSE_D_MV.
HINTS: provides estimate of number and type of upcoming matrix-vector operations
OPTIMIZE: analyze sparse matrix; choose proper kernels and workload balancing strategy */
CALL_AND_CHECK_STATUS(mkl_sparse_set_mv_hint( csrA, SPARSE_OPERATION_TRANSPOSE, descr_type_gen, 1 ),
"Error after MKL_SPARSE_SET_MV_HINT, csrA \n");
CALL_AND_CHECK_STATUS(mkl_sparse_set_mv_hint( csrB, SPARSE_OPERATION_NON_TRANSPOSE, descr_type_gen, 1 ),
"Error after MKL_SPARSE_SET_MV_HINT, csrB \n");
CALL_AND_CHECK_STATUS(mkl_sparse_set_mv_hint( csrC, SPARSE_OPERATION_NON_TRANSPOSE, descr_type_gen, 1 ),
"Error after MKL_SPARSE_SET_MV_HINT, csrC \n");
CALL_AND_CHECK_STATUS(mkl_sparse_optimize( csrA ),
"Error after MKL_SPARSE_OPTIMIZE, csrA \n");
CALL_AND_CHECK_STATUS(mkl_sparse_optimize( csrB ),
"Error after MKL_SPARSE_OPTIMIZE, csrB \n");
CALL_AND_CHECK_STATUS(mkl_sparse_optimize( csrC ),
"Error after MKL_SPARSE_OPTIMIZE, csrC \n");
/* Execution Routines */
/* Step 1:
Need to compute the following variables:
rslt_mv = C * x
left = <rslt_mv, y> */
CALL_AND_CHECK_STATUS(mkl_sparse_d_mv( SPARSE_OPERATION_NON_TRANSPOSE, 1.0, csrC, descr_type_gen, x, 0.0, rslt_mv ),
"Error after MKL_SPARSE_D_MV, csrC*x \n");
left = cblas_ddot( M, rslt_mv, 1, y, 1 );
/* Step 2:
Need to compute the following variables:
rslt_mv = B * x
rslt_mv_trans = (A)^t * y
right = <rslt_mv, rslt_mv_trans> */
CALL_AND_CHECK_STATUS(mkl_sparse_d_mv( SPARSE_OPERATION_NON_TRANSPOSE, 1.0, csrB, descr_type_gen, x, 0.0, rslt_mv ),
"Error after MKL_SPARSE_D_MV, csrB*x \n");
CALL_AND_CHECK_STATUS(mkl_sparse_d_mv( SPARSE_OPERATION_TRANSPOSE, 1.0, csrA, descr_type_gen, y, 0.0, rslt_mv_trans),
"Error after MKL_SPARSE_D_MV, csrA*y \n");
right = cblas_ddot( M, rslt_mv, 1, rslt_mv_trans, 1);
/* Step 3:
Compare values obtained for left and right */
residual = fabs(left - right)/(fabs(left)+1);
printf( "\n The difference between < C*x , y > and < B*x , (A^t)*y > = %g,\n", residual );
printf( " which means that MKL_SPARSE_D_SPMM arrived correct at a solution.\n" );
/* Printing OUTPUT DATA */
CALL_AND_CHECK_STATUS(mkl_sparse_d_export_csr( csrC, &indexing, &rows, &cols, &pointerB_C, &pointerE_C, &columns_C, &values_C ),
"Error after MKL_SPARSE_D_EXPORT_CSR \n");
printf( "\n RESULTANT MATRIX C:\nrow# : (value, column) (value, column)\n" );
ii = 0;
for( i = 0; i < M; i++ )
{
printf("row#%d:", i + 1); fflush(0);
for( j = pointerB_C; j < pointerE_C; j++ )
{
printf(" (%5.0f, %6d)", values_C[ii], columns_C[ii] ); fflush(0);
ii++;
}
printf( "\n" );
}
printf( "_____________________________________________________________________ \n" );
/* Deallocate memory */
memory_free:
//Release matrix handle. Not necessary to deallocate arrays for which we don't allocate memory: values_C, columns_C, pointerB_C, and pointerE_C.
//These arrays will be deallocated together with csrC structure.
if( mkl_sparse_destroy( csrC ) != SPARSE_STATUS_SUCCESS)
{ printf(" Error after MKL_SPARSE_DESTROY, csrC \n");fflush(0); status = 1; }
//Deallocate arrays for which we allocate memory ourselves.
mkl_free(rslt_mv_trans); mkl_free(rslt_mv); mkl_free(x); mkl_free(y);
//Release matrix handle and deallocate arrays for which we allocate memory ourselves.
if( mkl_sparse_destroy( csrA ) != SPARSE_STATUS_SUCCESS)
{ printf(" Error after MKL_SPARSE_DESTROY, csrA \n");fflush(0); status = 1; }
mkl_free(values_A); mkl_free(columns_A); mkl_free(rowIndex_A);
if( mkl_sparse_destroy( csrB ) != SPARSE_STATUS_SUCCESS)
{ printf(" Error after MKL_SPARSE_DESTROY, csrB \n");fflush(0); status = 1; }
mkl_free(values_B); mkl_free(columns_B); mkl_free(rowIndex_B);
return status;
}
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page