c++ - 在c++中调用lapack和blas

标签 c++ lapack blas

我需要在我的 C++ 代码中使用 lapack 和 blas,我想链接 MKL、ACML 或 Linux 系统中默认的 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);

有什么建议吗?更好的解决方案?感谢您的帮助。

最佳答案

供应商提供的 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 (我认为)。

关于c++ - 在c++中调用lapack和blas,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39984179/

相关文章:

c++ - 使用二分查找错了吗?

c++ - 将 make_shared 与 shared_ptr<T> 一起使用仅对 T < 56 字节有益?

c++ - Lapack 链接错误,使用 -fPIC 重新编译

c - Scalapack中处理器子集的不相交网格及其通信

c - BLAS 的 catlas_saxpby 的 vector 乘法无法正常工作

C++ 多线程类方法

c++ - 既不调用复制也不移动构造函数

scala - 使用 LAPACK-BLAS DGEMM 的矩阵点积

f# - MathNet.Numerics 不使用 Mkl native 提供程序

windows - CFFI 没有加载依赖库?