LAPACK declaration mismatch when including both MKL and Blaze

Issue #114 resolved
Jannik Schürg created an issue

Hi Klaus,

I tried to link the repo version of Blaze with Intel MKL and got the following error during building. I included Blaze as well as the MKL headers.

error: more than one instance of overloaded function "dgesvdx_" has "C" linkage
  void dgesvdx_( const char* jobu, const char* jobvt, const char* range, const MKL_INT* m,

I am on Mac OS using Intel MKL 2017.4.181. I dug into this and if I replace the forward declarations in Blaze, for example in gesvdx.h, with #include <mkl_lapack.h> it works. Relevant part from math/lapack/clapack/gesvdx.h:

//=================================================================================================
//
//  LAPACK FORWARD DECLARATIONS
//
//=================================================================================================

//*************************************************************************************************
/*! \cond BLAZE_INTERNAL */
extern "C" {

void sgesvdx_( char* jobu, char* jobv, char* range, int* m, int* n, float*  A, int* lda, float*  vl, float*  vu, int* il, int* iu, int* ns, float*  s, float*  U, int* ldu, float*  V, int* ldv, float*  work, int* lwork, int* iwork, int* info );
void dgesvdx_( char* jobu, char* jobv, char* range, int* m, int* n, double* A, int* lda, double* vl, double* vu, int* il, int* iu, int* ns, double* s, double* U, int* ldu, double* V, int* ldv, double* work, int* lwork, int* iwork, int* info );
void cgesvdx_( char* jobu, char* jobv, char* range, int* m, int* n, float*  A, int* lda, float*  vl, float*  vu, int* il, int* iu, int* ns, float*  s, float*  U, int* ldu, float*  V, int* ldv, float*  work, int* lwork, float*  rwork, int* iwork, int* info );
void zgesvdx_( char* jobu, char* jobv, char* range, int* m, int* n, double* A, int* lda, double* vl, double* vu, int* il, int* iu, int* ns, double* s, double* U, int* ldu, double* V, int* ldv, double* work, int* lwork, double* rwork, int* iwork, int* info );

}
/*! \endcond */
//*************************************************************************************************

The problem seems to be that the MKL declares some of these pointers as const and additionally uses MKL_INT instead of int, which can be different for example if the 64bit interface of the MKL is chosen in my case.

I did not check this but it seems I get the error for every LAPACK function Blaze declares.

So I think that I have to make sure to pick the version of the MKL where MKL_INT is identical to int (if even possible). And, I can not use both headers in the same compilation unit.

A fix might include generalising the integer type in Blaze and allowing custom LAPACK header files? Or at least adding a static assert which checks that int and MKL_INT have the same size?

Best regards,

Jannik Schürg

Comments (8)

  1. Klaus Iglberger

    Hi Jannik!

    Thanks a lot for pointing out this problem. We will investigate and try to resolve the issue as quickly as possible.

    Best regards,

    Klaus!

  2. Klaus Iglberger

    Hi Jannik!

    Thanks again for pointing out this problem. Unfortunately we did not encounter this problem before, therefore your help is highly appreciated.

    We were able to reproduce it with the MKL 14, 15, and 2017.x. The underlying problem is the lack of a standard C interface for LAPACK. The general advice to overcome this problem is to build on the standardized Fortran interface (see for instance this article). Blaze provides such a C interface and forward declares all Fortran functions as C functions. Apparently Intel provides a similar, proprietary C interface via the <mkl_lapack.h> header file, which unfortunately is in contradiction to the advice and therefore to the Blaze interface.

    In order to decide which is the best course of action we would like to get your input: Why do you include the <mkl_lapack.h> header? Do you call LAPACK functions via this interface? If yes, would it be possible for you to use the Blaze interface instead (see the wiki for an overview of the available wrapper functions)? If no, which functions are missing or for what other reason? Do you use the 64-bit interface for a specific reason? Thanks a lot for your feedback!

    Best regards,

    Klaus!

  3. Jannik Schürg reporter

    Hi Klaus,

    thanks for your prompt efforts and your explanation.

    Of course I can provide my input/motivation. Actually I am not using the 64bit for a specific reason at this moment. I am working on a prototype which has a focus on parallelisation. When I read Intel's documentation on 32bit vs 64bit, I chose the 64bit version for two reasons, first I thought it can be switched easily and second, although unlikely for the moment, the software might be used for large datasets which can not be addressed by a 32bit integer. The size_t type has 64bit, too. Since it is used in Blaze for indexing, if I am correct, the option to use it for a call to LAPACK might be interesting for Blaze?

    Regarding the LAPACK header from MKL I wanted to setup a minimal working example and just included <mkl.h>, which resulted in the error: I am interested in measuring some experiments with packed symmetric matrices, which I think are not supported by Blaze, and if a combination is possible. In general I liked the idea to be able to call any LAPACK or BLAS routine directly and wanted to set this up.

    Kind regards,

    Jannik

  4. Klaus Iglberger

    Summary

    The fix to improve the compatibility between the C/C++ LAPACK interfaces of the Blaze library and Intel's MKL has been implemented, tested, and documented as required. It is immediately available via cloning the Blaze repository and will be officially released in Blaze 3.2.

    Details

    It is now possible to include the <mkl.h> header before any Blaze header. Blaze will detect this and use the provided interface from the MKL. It is not possible, however, to include the <mkl.h> header after the Blaze headers since in this case Blaze cannot detect that the MKL is present.

    Please note that Blaze is still restricted to the 32-bit version of the MKL (LP64) and does not enable you to use the 64-bit version (IPL64). At this time it seems to be unlikely that the number of elements goes beyond 2^31-1, as this would result in 8.5TB of shared memory for single precision and 17TB of shared memory for double precision for a single vector or matrix.

  5. Jannik Schürg reporter

    Hi Klaus,

    thank you very much!

    I just tried it and I get the following error:

    In file included from ./blaze/blaze/math/lapack/gesvdx.h(52),
                     from ./blaze/blaze/math/dense/SVD.h(50),
                     from ./blaze/blaze/math/DenseMatrix.h(52),
                     from ./blaze/blaze/math/CustomMatrix.h(45),
                     from ./blaze/blaze/Math.h(50),
                     from ./blaze/blaze/Blaze.h(43),
                     from test.cpp(3):
    ./blaze/blaze/math/lapack/clapack/gesvdx.h(484): error: argument of type "ET={double} *" is incompatible with parameter of type "MKL_Complex16 *"
                   reinterpret_cast<ET*>( work ), &lwork, rwork, iwork, info );
    

    The source code is

    #include <mkl.h>
    #include <blaze/Blaze.h>
    
    int main() { }
    

    compiled with icpc -mkl -std=c++14 test.cpp.

    The reason seems to be that in my case INTEL_MKL_VERSION is 20170000, whereas Blaze does check for INTEL_MKL_VERSION > 20170000.

    EDIT: I am on a Linux machine at the moment with a bit older version of the MKL.

    Kind regards,

    Jannik

  6. Klaus Iglberger

    Hi Jannik!

    Thanks again for pointing this out. I fixed the problem, please update from the current repository. Sorry for the inconvenience,

    Best regards,

    Klaus!

  7. Log in to comment