简体   繁体   中英

using MKL sparse matrix vector multiply

does any one has a simple C++ code example of using MKL sparse matrix vector multiply routine? I need to use "mkl_zcsrsymv" to multiply a complex symmetric matrix (stored in lower triangular) with a complex vector, but I couldn't find a single demonstrative example on this. Unable to compile my code for complex case.

Read the documentation for mkl_zcsrsymv on Intel's homepage . Here symmetric is to be taken literally! (It does not mean Hermitian)

Compile with icpc -mkl test.c for maximal convenience.

#include <stdio.h>
#include "mkl_spblas.h"

int main()
{
  /* Matrix in CRS format
   *
   * { {  0,  0,  i } 
   *   {  0, -1,  2 } 
   *   {  i,  2,  0 } } 
   */
  int m = 3;
  MKL_Complex16 a[] = { {0,1}, {-1,0}, {2,0}, {0,1}, {2,0} };
  int ia[] = { 0, 1, 3, 5 };
  int ja[] = { 2, 1, 2, 0, 1 };

  MKL_Complex16 x[] = { {1,0}, {2,0}, {3,0} };
  MKL_Complex16 y[] = { {0,0}, {0,0}, {0,0} };

  char uplo = 'L';
  // Use MKL to compute
  // y = A*x
  mkl_cspblas_zcsrsymv(&uplo, &m, a, ia, ja, x, y);

  printf("y = { (%g,%g), (%g,%g), (%g,%g) }\n",
         y[0].real, y[0].imag,
         y[1].real, y[1].imag,
         y[2].real, y[2].imag
    );
}

Output is y = { (0,3), (4,0), (4,1) } . Check it on WolframAlpha .


Here is also an example for mkl_dcsrmv .

#include <stdio.h>
#include "mkl_spblas.h"

int main()
{
  /* Matrix in CRS format
   *
   * { { 0,  0,  1 } 
   *   { 0, -1,  2 } 
   *   { 1,  0,  0 } } 
   */
  int m = 3;
  int k = 3;
  double val[] = { 1, -1, 2, 1 };
  int indx[]   = { 2, 1, 2, 0 };
  int pntrb[]  = { 0, 1, 3 };
  int pntre[]  = { 1, 3, 4 };

  double x[] = { 1, 2, 3 };
  double y[] = { 0, 0, 0 };

  double alpha = 1;
  double beta  = 0;
  char transa = 'N';
  char matdescra[] = {
    'G', // type of matrix
    ' ', // triangular indicator (ignored in multiplication)
    ' ', // diagonal indicator (ignored in multiplication)
    'C'  // type of indexing
  };

  // Use MKL to compute
  // y = alpha*A*x + beta*y
  mkl_dcsrmv(&transa, &m, &k, &alpha, matdescra, val, indx, pntrb, pntre, x, &beta, y);

  printf("y = { %g, %g, %g }\n", y[0], y[1], y[2]);
}

Output is y = { 3, 4, 1 } . Check it on WolframAlpha .


While playing with this I found out that this is directly compatible with Armadillo . This makes it very convenient to use in C++. Here I first generate a random symmetric matrix with Armadillo and convert it to sparse. This I multiply with a random vector. Finally I compare the result to Armadillo's sparse matrix-vector product. The precision differs quite substantially.

#include <iostream>
#include <armadillo>
#define MKL_Complex16 arma::cx_double
#include "mkl_spblas.h"

int main()
{
  /* Matrix in CRS format
   *
   * { {  0,  0,  i } 
   *   {  0, -1,  2 } 
   *   {  i,  2,  0 } } 
   */
  int dim = 1000;
  arma::sp_cx_mat a(arma::randu<arma::cx_mat>(dim,dim));
  a += a.st();
  arma::cx_vec x = arma::randu<arma::cx_vec>(dim);
  arma::cx_vec y(dim);

  char uplo = 'L';
  // Use MKL to compute
  // y = A*x
  mkl_cspblas_zcsrsymv(&uplo, &dim,
                       a.values, (int*)a.col_ptrs, (int*)a.row_indices,
                       x.memptr(), y.memptr());

  std::cout << std::boolalpha
            << arma::approx_equal(y, a*x, "absdiff", 1e-10)
            << '\n';
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM