在 C++ 中调用 lapack 和 blas
call lapack and blas in c++
我需要在我的 C++ 代码中使用 lapack 和 blas,我想在 linux 系统中 link MKL、ACML 或默认的 lapack 和 blas。不幸的是,它们在 c 中有不同的约定。例如,MKL ( mkl_blas.h ) 中的 zdotc 是
zdotc(&result, &n, x, &incx, y, &incy);
并从默认的 lapack 和 blas(fortran 版本)调用 zdotc 是:
result = zdotc_(&n, x, &incx, y, &incy);
如果我希望我的代码使用 MKL、ACML 或默认的 lapack blas。我需要为此写一个包装:
#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
}
虽然有这么多功能,但为每个功能编写包装会花费时间。我希望它们有一个独特的约定。如果你在代码中使用了 lapack 和 blas,你如何解决这个问题?你有所有功能的包装吗?如果有包裹,如果你能和我分享就太好了。
更新:
我找到了解决这个问题的方法:
#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
);
然后我可以通过以下方式调用这个函数:
complex<double> result;
#ifndef FORTRAN_COMPLEX_FUNCTIONS_RETURN_VOID
result = zdotc(
#else
zdotc(&result,
#endif
&n, x, &incx, y, &incy);
有什么建议吗?更好的解决方案?感谢您的帮助。
我在我的 C++ 代码中使用了 lapack,我没有遇到过这个问题。您可以查看 cosmo++ 库。查看 source/matrix_impl.cpp 文件。我有一个 extern "C"
块,其中包含我需要的函数,以 _
结尾。我已经针对 lapack/blas 和 MKL 编译了这段代码,没有任何问题。我用过 gcc 和 intel 编译器。它还在我的 mac 和 framework Accelerate
上编译。
供应商提供的 BLAS 和 LAPACK 实现通常包括带有尾随下划线的符号,因为这是 Fortran 77 编译器最初的工作方式。现代的 gfortran 行为也是添加尾随下划线以实现兼容性,但有 -fno-underscoring
option 将其关闭。
对于您自己使用 gfortran 编译的代码,例如引用 BLAS 和 LAPACK,您可以选择是直接 return 复数值还是使用间接 result
指针参数。要获得间接行为,请使用 -ff2c
进行编译。默认的 gfortran 行为是直接 return 复数值。
避免代码中的宏和换行的最简单方法是在名称中假定尾随下划线,并在添加的第一个参数中假定复杂结果的间接 return 值。这将与供应商库兼容。然后用 -ff2c
编译 BLAS 和 LAPACK 使其在那里工作。
为了获得最大的灵活性,您可以使用换行函数。在包装器中,您只需要担心是否直接 returned 复杂参数,您不需要对每个不同的库进行特殊处理。
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
}
在 BLAS 中,只有少数函数需要包装:CDOTU CDOTC ZDOTU ZDOTC
。在 LAPACK 中只有 CLADIV ZLADIV
(我认为)。
我需要在我的 C++ 代码中使用 lapack 和 blas,我想在 linux 系统中 link MKL、ACML 或默认的 lapack 和 blas。不幸的是,它们在 c 中有不同的约定。例如,MKL ( mkl_blas.h ) 中的 zdotc 是
zdotc(&result, &n, x, &incx, y, &incy);
并从默认的 lapack 和 blas(fortran 版本)调用 zdotc 是:
result = zdotc_(&n, x, &incx, y, &incy);
如果我希望我的代码使用 MKL、ACML 或默认的 lapack blas。我需要为此写一个包装:
#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
}
虽然有这么多功能,但为每个功能编写包装会花费时间。我希望它们有一个独特的约定。如果你在代码中使用了 lapack 和 blas,你如何解决这个问题?你有所有功能的包装吗?如果有包裹,如果你能和我分享就太好了。
更新:
我找到了解决这个问题的方法:
#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
);
然后我可以通过以下方式调用这个函数:
complex<double> result;
#ifndef FORTRAN_COMPLEX_FUNCTIONS_RETURN_VOID
result = zdotc(
#else
zdotc(&result,
#endif
&n, x, &incx, y, &incy);
有什么建议吗?更好的解决方案?感谢您的帮助。
我在我的 C++ 代码中使用了 lapack,我没有遇到过这个问题。您可以查看 cosmo++ 库。查看 source/matrix_impl.cpp 文件。我有一个 extern "C"
块,其中包含我需要的函数,以 _
结尾。我已经针对 lapack/blas 和 MKL 编译了这段代码,没有任何问题。我用过 gcc 和 intel 编译器。它还在我的 mac 和 framework Accelerate
上编译。
供应商提供的 BLAS 和 LAPACK 实现通常包括带有尾随下划线的符号,因为这是 Fortran 77 编译器最初的工作方式。现代的 gfortran 行为也是添加尾随下划线以实现兼容性,但有 -fno-underscoring
option 将其关闭。
对于您自己使用 gfortran 编译的代码,例如引用 BLAS 和 LAPACK,您可以选择是直接 return 复数值还是使用间接 result
指针参数。要获得间接行为,请使用 -ff2c
进行编译。默认的 gfortran 行为是直接 return 复数值。
避免代码中的宏和换行的最简单方法是在名称中假定尾随下划线,并在添加的第一个参数中假定复杂结果的间接 return 值。这将与供应商库兼容。然后用 -ff2c
编译 BLAS 和 LAPACK 使其在那里工作。
为了获得最大的灵活性,您可以使用换行函数。在包装器中,您只需要担心是否直接 returned 复杂参数,您不需要对每个不同的库进行特殊处理。
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
}
在 BLAS 中,只有少数函数需要包装:CDOTU CDOTC ZDOTU ZDOTC
。在 LAPACK 中只有 CLADIV ZLADIV
(我认为)。