Search code examples
cmatlabmexblas

Use BLAS library in C Mex-File


I am trying to use the BLAS library for my C-Mex-Code to analyze performance differences with and without BLAS. However, I couldn't figure out how to use BLAS correctly without getting compile errors/warnings (and eventually Matlab Crashes).

Below is a sample code where I would like to calculate a vector product using the ddot()-function of Blas ( https://software.intel.com/de-de/node/468398#D4E53C70-D8FA-4095-A800-4203CAFE64FE ):

  #include <mex.h>
  #include <math.h>
  #include <blas.h>

  void TestBlas(double *L, double *R, mwSize n)
  {

      int one = 1;
      double sum = ddot(&n,L,&one,L,&one);

      //Output Matrix R not defined, just for test purposes...

  } 

  void mexFunction( int nlhs, mxArray *plhs[],
                    int nrhs, const mxArray *prhs[])
  {
      double *inMatrix;               /* 1xN input matrix */
      size_t ncols;                   /* size of matrix */
      long *ncolsPr;                  /* output matrix */
      double *outMatrix;              /* output matrix */

      inMatrix = mxGetPr(prhs[0]);
      ncols = mxGetN(prhs[0]);

      /* create the output matrix */
      plhs[0] = mxCreateDoubleMatrix(1,(mwSize)ncols,mxREAL);
      outMatrix = mxGetPr(plhs[0]);

      TestBlas(inMatrix,outMatrix,(mwSize)ncols);
  }

The compiler warnings I receive are:

 >> mex -largeArrayDims TestBlas.c -lmwblas
  Building with 'Xcode with Clang'.
  /Users/jhess/Dropbox/Uni/E-Technik Master/Forschungspraxis Machine Learning/Matlab/TestBlas.c:9:23: warning: passing 'mwSize *' (aka 'unsigned long *') to parameter of type 'const ptrdiff_t *' (aka 'const long *') converts between pointers to integer types with different sign [-Wpointer-sign]
      double sum = ddot(&n,L,&one,L,&one);
                        ^~
  /Applications/MATLAB_R2015a.app/extern/include/blas.h:559:22: note: passing argument to parameter 'n' here
      const ptrdiff_t *n,
                       ^
  /Users/jhess/Dropbox/Uni/E-Technik Master/Forschungspraxis Machine Learning/Matlab/TestBlas.c:9:28: warning: incompatible pointer types passing 'int *' to parameter of type 'const ptrdiff_t *' (aka 'const long *') [-Wincompatible-pointer-types]
      double sum = ddot(&n,L,&one,L,&one);
                             ^~~~
  /Applications/MATLAB_R2015a.app/extern/include/blas.h:561:22: note: passing argument to parameter 'incx' here
      const ptrdiff_t *incx,
                       ^
  /Users/jhess/Dropbox/Uni/E-Technik Master/Forschungspraxis Machine Learning/Matlab/TestBlas.c:9:35: warning: incompatible pointer types passing 'int *' to parameter of type 'const ptrdiff_t *' (aka 'const long *') [-Wincompatible-pointer-types]
      double sum = ddot(&n,L,&one,L,&one);
                                    ^~~~
  /Applications/MATLAB_R2015a.app/extern/include/blas.h:563:22: note: passing argument to parameter 'incy' here
      const ptrdiff_t *incy
                       ^
  3 warnings generated.

  MEX completed successfully.

It seems to be something like I am passing wrong variable-types (or pointer-types?) to the BLAS-function but I just couldn't figure out how to fix it. Can somebody have a look please? Many thanks!


Solution

  • If my suspicion is correct, you just have to define the proper types of the integers involved in your code:

      #include <mex.h>
      #include <math.h>
      #include <blas.h>
    
      void TestBlas(double *L, double *R, mwSignedIndex n) //changed
      {
    
          mwSignedIndex one = 1; //changed
          double sum = ddot(&n,L,&one,L,&one);
    
          //Output Matrix R not defined, just for test purposes...
    
      } 
    
      void mexFunction( int nlhs, mxArray *plhs[],
                        int nrhs, const mxArray *prhs[])
      {
          double *inMatrix;               /* 1xN input matrix */
          size_t ncols;                   /* size of matrix */
          long *ncolsPr;                  /* output matrix */
          double *outMatrix;              /* output matrix */
    
          inMatrix = mxGetPr(prhs[0]);
          ncols = mxGetN(prhs[0]);
    
          /* create the output matrix */
          plhs[0] = mxCreateDoubleMatrix((mwSize)1,(mwSize)ncols,mxREAL); //changed
          outMatrix = mxGetPr(plhs[0]);
    
          TestBlas(inMatrix,outMatrix,(mwSignedIndex)ncols); //changed
      }
    

    In my experience you have to be especially careful with literal constants appearing in the function calls, so note the cast of 1 to (mwSize), which mxCreateDoubleMatrix expects.