I am using the zgesdd routine to find the singular value decomposition for a matrix, however, for certain sizes of the matrix the routine will cause an access violation (segmentation fault) and the program will be forced to stop by the OS (Win10 64bit).
Regardless of the compilation options (whether or not I allow AVX2 extensions or not) the call stack points to
mkl_blas_avx2_dgemm_kernel_0_b0()
To the best of my knowledge my CPU (i7-4720HQ) should support AVX2 routines (although I wouldn't expect them to be called if I specify that they should not be used).
It seems that zgesvd does not share the same issue and appears to be working fine for me.
Some sizes that cause a crash:
191 by 354 (354x191 would be the output of the code below, not really the standard when it comes to matrices, I know)
282 by 498 (498x282)
242 by 420 (242x420)
The above were found with the following code, you may also directly input those values into the test_matrix constructor and the crash will (or it did for me) always happen.
#include <iostream> #include <random> #include <ctime> #include <new> #include <tuple> #include <mkl/mkl.h> #include <mkl/mkl_lapack.h> #include <mkl/mkl_blas.h> class matrix { public: ll x, y; MKL_Complex16* mat; matrix() { x = y = 0; mat = NULL; } matrix(ll X, ll Y) { x = X; y = Y; mat = new MKL_Complex16[x * y](); } ~matrix() { x = y = 0; if (mat != NULL) delete[] mat; } void set(ll X, ll Y) { x = X; y = Y; if (mat != NULL) delete[] mat; mat = new MKL_Complex16[x * y](); } void clear() { x = y = 0; if (mat != NULL) { delete[] mat; mat = NULL; } } } class test_matrix { public: matrix data; test_matrix(int x, int y) { data.set(x, y); for (int i = 0; i < x * y; i++) { data.mat[i].real = i + 1; } } ~test_matrix() { data.clear(); //Don't really need this... } }; tuple<matrix*, double*, matrix*, ll> matrixSVD(matrix* in) { ll ssize = in->y < in->x ? in->y : in->x; matrix* U = new matrix(in->y, in->y); matrix* VT = new matrix(in->x, in->x); double* S = new double[ssize](); #ifndef _TEST_SVD LAPACKE_zgesdd(LAPACK_ROW_MAJOR, 'A', in->y, in->x, in->mat, in->x, S, U->mat, U->x, VT->mat, VT->x); #endif #ifdef _TEST_SVD double* sp = new double[5 * ssize](); LAPACKE_zgesvd(LAPACK_ROW_MAJOR, 'A', 'A', in->y, in->x, in->mat, in->x, S, U->mat, in->y, VT->mat, in->x, sp); delete[] sp; #endif return make_tuple(U, S, VT, ssize); } int main(void) { mt19937_64 gen(clock()); uniform_int_distribution<int> dist(1, 500); for (int i = 0; i < 10000; i++) { int i1 = dist(gen), i2 = dist(gen); cout << i << ": "<< i1 << 'x'<< i2 << '\n'; test_matrix tmt(i1, i2); matrix* U; double* S; matrix* VT; ll s; tie(U, S, VT, s) = matrixSVD(&tmt.data); delete U; delete VT; delete[] S; } return 0; }
Pardon the messy code, it was just a test. It might still be that the fault is mine, but since it works when I change to zgesvd, that is unlikely. Any and all suggestions are of course welcome.
Thank you for your time.