我需要在我的c ++代码中使用lapack和blas,我想在linux系统中链接MKL,ACML或默认的lapack和blas。不幸的是,他们在c中有不同的惯例。例如,MKL(mkl_blas.h)中的zdotc是
zdotc(&result, &n, x, &incx, y, &incy);
从默认的lapack调用zdotc,blas(fortran版本)是:
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);
有什么建议吗?好的解决方案谢谢你的帮助。
答案 0 :(得分:1)
供应商提供的BLAS和LAPACK实现通常包含具有尾随下划线的符号,因为这是Fortran 77编译器最初工作的方式。现代gfortran行为也是为兼容性添加了尾随下划线,但有-fno-underscoring
option可以将其关闭。
对于使用gfortran编译的代码,例如参考BLAS和LAPACK,您可以选择是直接返回复杂值还是使用间接result
指针参数。要获得间接行为,请使用-ff2c
进行编译。默认的gfortran行为是直接返回复杂值。
避免代码中宏和包装的最简单方法是在名称中使用尾随下划线,并在添加的第一个参数中假设复杂结果的间接返回值。这将与供应商库兼容。然后使用-ff2c
编译BLAS和LAPACK以使其在那里工作。
为了获得最大的灵活性,您可以使用环绕功能。在包装器中,您只需要担心是否直接返回复杂的参数,您不需要为每个不同的库进行特殊处理。
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
(我认为)。
答案 1 :(得分:0)
我在我的c ++代码中使用lapack而我还没有遇到过这个问题。您可以查看cosmo++库。查看source / matrix_impl.cpp文件。我有一个extern "C"
块,其中包含我需要的函数,以_
结尾。我已经针对lapack / blas以及MKL编译了这段代码而没有任何问题。我使用过gcc和intel编译器。它还使用framework Accelerate
在我的Mac上编译。