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

Access Violation Error while using dgesvd for c on Visual Studio

Matthew_C_3
Beginner
439 Views

Hello, while running the following code on Visual Studio 2015:

 

#include <thread>
#include <mkl.h>
#include <random>
#include <ctime>

const int MatrixLayout = LAPACK_COL_MAJOR;

int GetIndex(int i, int j, int m, int n);
void Initialize2DArray( double** matrix, int rows, int columns );
void PopulateRandMatrix( double **& matrix, int m, int n );
/*Wraps inputs intended for svdcmp to those accepted by the MKL library.*/
int wrapperForSVD( double **u, int m, int n, double *w, double **v );
#define M 500
#define N 400

int main() {
   int m = M;
   int n = N;
   double** A = new double*;
   double* w = new double[(m>n)?n:m];
   double** V = new double*;

   Initialize2DArray( A, m, n );
   Initialize2DArray( V, n, n );

   PopulateRandMatrix( A, m, n );

   int getReturn = wrapperForSVD( A, m, n, w, V );

}

/*Wraps inputs intended for svdcmp to those accepted by the MKL library.*/
int wrapperForSVD( double **u, int m, int n, double *w, double **v )
{
   mkl_verbose( 1 );
   const unsigned int NumberOfThreads = std::thread::hardware_concurrency() > 0 ? (int)std::thread::hardware_concurrency() : 4;
   //Return only variable
   const int ReturnError = 1;
   const char JobUVt = 'A';
   lapack_int lda = (MatrixLayout == LAPACK_COL_MAJOR) ? m : n;
   lapack_int ldu = m;
   lapack_int ldvt = n;

   //save old thread value and set threads locally incase of future omp threadding of application
   int oldThreadNumber = mkl_set_num_threads_local( NumberOfThreads );


   double* aOneDArray = (double*)malloc( m*n * sizeof( double ) );//new double[m*n];
   if (!aOneDArray)
      return ReturnError;

   //convert 2d matrix to 1d array
   for (int i = 0; i < m; i++)
      for (int j = 0; j < n; j++)
         aOneDArray[GetIndex( i, j, m, n )] = u;

   double * uOneDArray = (double*)malloc( ldu*m * sizeof( double ) );//new double[ldu*m];
   double * vOneDArray = (double*)malloc( ldvt*n * sizeof( double ) );//new double[ldvt*n];
   double * superb = (double*)malloc( sizeof( double )*(m > n) ? n-2 : m-2 );//new double[(m>n)?n:m];
   if (!uOneDArray || !vOneDArray || !superb)
      return ReturnError;

   int testFailConvergence = LAPACKE_dgesvd( MatrixLayout, JobUVt, JobUVt, m, n, aOneDArray, lda, w, uOneDArray, ldu, vOneDArray, ldvt, superb );


   //if matrix converged
   if (testFailConvergence == 0) {
      //convert 1d arrays to 2d arrays
      for (int i = 0; i < m; i++)
         for (int j = 0; j < n; j++)
            u = uOneDArray[GetIndex( i, j, m, n )];
      int smallerOfMN = (m < n) ? m : n;
      for (int i = 0; i < smallerOfMN; i++)
         for (int j = 0; j < smallerOfMN; j++)
            v = vOneDArray[GetIndex( i, j, smallerOfMN, smallerOfMN )];
   }
   else
      testFailConvergence = ReturnError;

   free( aOneDArray ); //delete[] oneDArray;
   free( uOneDArray ); //delete[] uOneDArray;
   free( vOneDArray ); //delete[] vOneDArray;
   free( superb ); //delete[] superb;

   //reset thread count
   mkl_set_num_threads_local( oldThreadNumber );

   return testFailConvergence;

}


//Maps the correct index from a 2d array to a 1d array
//NOTE: Fucntion is dependent upon MatrixLayout and will return the correct
//layout for both row major and column major re-mapping
int GetIndex(int i, int j, int m, int n)
{
   if (MatrixLayout == LAPACK_ROW_MAJOR)
      return (i*n) + j;
   else
      return (j*m) + i;
}

void Initialize2DArray(double ** matrix, int rows, int columns)
{
   for (int i = 0; i < rows; i++)
      matrix = new double[columns];
   return;
}

void PopulateRandMatrix(double **& matrix, int m, int n)
{

   double** old = nullptr;
   std::srand(std::time(NULL));
   if (matrix != nullptr)
      old = matrix;
   matrix = new double*;

   for (int i = 0; i < m; i++) {
      if (old != nullptr)
         delete[] old;
      matrix = new double;
      for (int j = 0; j < n; j++) {
         double randOut = std::rand();
         matrix = randOut;
      }
   }
}

I get the following error:

Exception thrown at 0x013A1C0B in DebugSVD.exe: 0xC0000005: Access violation writing location 0x00AC1000.

While the error message informs us that this is an Access violation, it is virtually useless in helping determine where the access violation is stemming from. Visual Studio is only able to show me disassembly, so debugging in that way is impossible as well.

The program outputs the following (because mkl_verbose is set to one) before throwing the error:

MKL_VERBOSE Intel(R) MKL 2017.0 Update 3 Product build 20170413 for 32-bit Intel(R) Advanced Vector Extensions 2 (Intel(R) AVX2) enabled processors, Win 2.30GHz intel_thread
MKL_VERBOSE DGESVD(A,A,500,400,00B60040,500,0055E008,00CF0040,500,00EE0040,400,003FF524,-1,0) 32.05ms CNR:OFF Dyn:1 FastMM:1 TID:0  NThr:8
MKL_VERBOSE DGESVD(A,A,500,400,00B60040,500,0055E008,00CF0040,500,00EE0040,400,01231080,46000,0) 3.98s CNR:OFF Dyn:1 FastMM:1 TID:0  NThr:8

 

My settings are as follows: MKL is enabled in the Visual Studio project and set to Parallel. The only other changes are that I copied libiomp5md.dll into the project folder.

I appreciate any help debugging my problem! Thank you so much.

0 Kudos
2 Replies
Gennady_F_Intel
Moderator
439 Views

Matthew, the similar behavior with 64 bit case? have you tried this?

0 Kudos
Gennady_F_Intel
Moderator
439 Views

pls update line #59 by the following once: 

double * superb = (double*)malloc( sizeof( double )*((m > n) ? n-1 : m-1));

 

0 Kudos
Reply