简体   繁体   中英

call lapack and blas in c++

I need to use lapack and blas in my c++ code, I want to link either MKL, ACML, or default lapack and blas in linux systems. Unfortunately, they have different convention in c. For example, zdotc in MKL ( mkl_blas.h ) is

zdotc(&result, &n, x, &incx, y, &incy);

and call zdotc from default lapack and blas (fortran version) is:

result = zdotc_(&n, x, &incx, y, &incy);

If I want my code to use either MKL, ACML, or default lapack blas. I need to write a wrap for this:

#ifdef FORTRAN_NO_UNDERSCORE
    #define F77NAME(x) x
#else
    #define F77NAME(x) x##_
#endif

complex<double> zdotc_wrap(int n, const complex<double>*x, int incx, const complex<double>*y, int incy) 
{
  #if defined(USE_MKL)
    complex<double> result;
    zdotc(&result, &n, x, &incx, y, &incy)
    return result;
  #elif defined(USE_LAPACK_BLAS)
    return F77NAME(zdotc)(&n, x, &incx, y, &incy);
  #elif defined(USE_ACML)
    ...
  #endif
}

While there are so many functions, it costs time to write wraps for each of them. I hope there is one unique convention of them. If you are using lapack and blas in your code, how do you solve this problem? Do you have a wrap for all the functions? If there is a wrap, it will be great if you can share that with me.


Update:

I find one way to solve this problem:

#ifndef FORTRAN_COMPLEX_FUNCTIONS_RETURN_VOID
extern complex<double> zdotc(
#else
extern void zdotc(complex<double>* retval,
#endif
    const int *n,
    const complex<double> *zx,
    const int *incx,
    const complex<double> *zy,
    const int *incy
);

Then I can call this function by:

complex<double> result;
#ifndef FORTRAN_COMPLEX_FUNCTIONS_RETURN_VOID
result = zdotc(
#else
zdotc(&result,
#endif
&n, x, &incx, y, &incy);

Any suggestions? Better solutions? Thank you for your help.

Vendor supplied BLAS and LAPACK implementations usually include symbols with the trailing underscore, because that is how Fortran 77 compilers worked originally. The modern gfortran behavior is to also add the trailing underscore for compatibility, but there is the -fno-underscoring option to turn it off.

For code you compile yourself with gfortran such as the reference BLAS and LAPACK, you can choose whether to return complex values directly or by using the indirect result pointer argument. To get the indirect behavior, compile with -ff2c . The default gfortran behavior is to return complex values directly.

The simplest way to avoid the macros and wraps in your code is to assume trailing underscores in the names and indirect return values for complex results in an added first argument. That will be compatible with vendor libraries. Then compile BLAS and LAPACK with -ff2c to make it work there.

For maximum flexibility you can use wrap functions. Within the wrapper you should only need to worry about whether complex arguments are returned directly or not, you should not need special handling for each different library.

complex<double> zdotc_wrap(int n, const complex<double>*x, int incx, const complex<double>*y, int incy) 
{
  #if defined(FORTRAN_COMPLEX_FUNCTIONS_RETURN_VOID)
    complex<double> result;
    zdotc_(&result, &n, x, &incx, y, &incy);
    return result;
  #else
    return zdotc_(&n, x, &incx, y, &incy);
  #endif
}

In BLAS there are only a handful of functions that need to be wrapped: CDOTU CDOTC ZDOTU ZDOTC . In LAPACK there are just CLADIV ZLADIV (I think).

I am using lapack in my c++ code and I haven't had that issue. You can check the cosmo++ library. Look at the source/matrix_impl.cpp file. I have an extern "C" block which contains the functions I need, ending with _ . I have compiled this code against lapack/blas as well as MKL with no issues. I have used gcc and intel compilers. It also compiles on my mac with framework Accelerate .

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