在R语言的Fortran文件中使用blas/Lapack

5hcedyr0  于 2023-01-06  发布在  R语言
关注(0)|答案(1)|浏览(269)

我有以下问题。我有一个文件,比如说file.f90,其中我实现了一些Fortran子例程,比如说foo。然后我使用“R CMD SHLIB file.f90”编译这些函数。为了在一个单独的R文件中使用函数foo,我使用dyn.load(“foo.dll”)并将其命名为.Fortran(“foo”,...)。
到目前为止一切顺利。但是现在我需要使用一些在Lapack中实现的函数。
我不知道该怎么做,也不知道该去哪里看看。我只试过调用“R CMD SHLIB file.f90 -llapack”,但已经出现了一个错误,说没有找到llapack。任何提示都将不胜感激!!
编辑:在在座各位的帮助下,我终于找到了问题的答案。我不得不说,这个解决方案相当简单,但由于我是一个新手,所以在这些方面还是花了一些时间。下面是我针对Windows 11和R Studio 4.1的解决方案
假设我们的R会话/项目具有路径PATH_PROJ,例如“C:\Users\Myname\Documents\MyProject”。然后我创建了一个名为“f90 files”的新文件夹,我打算在其中保存所有Fortran函数,因此PATH_PROJ\f90files。接下来,我需要我的R的Lapack PATH_LAPACK的路径,例如“C:\Program Files\R\R-4.1.2\bin\x64\Rlapack.dll”。
在PATH_PROJ\f90文件中,我按照Jean-Claude Arbaut的建议实现了Fortran子例程:

subroutine eigvals(n, a, vre, vim, info)
    implicit none
    integer :: n, info
    integer, parameter :: lwork = 65536
    double precision :: a(n, n), vre(n), vim(n)
    double precision, save :: work(lwork)

    call dgeev("n", "n", n, a, n, vre, vim, 0d0, 1, 0d0, 1, work, lwork, info)
end subroutine

接下来,我启动了Windows命令提示符并键入

gfortran -shared PATH_LAPACK PATH_PROJ\f90files\eigvals.f90 -o PATH_PROJ\f90files\eigvals.so -o PATH_PROJ\f90files\eigvals.dll

并且还

gfortran -shared PATH_LAPACK PATH_PROJ\f90files\eigvals.f90 -o PATH_PROJ\f90files\eigvals.so

(也许这可以一次完成?)
有了这个,所有的都被很好地编译了。在R中,我使用

dyn.load("PATH_PROJ\f90files\eigvals.dll")

最后,使用下面给出的实现,我运行了

eigvals <- function(a) {
  if (is.matrix(a) && is.double(a) && nrow(a) == ncol(a)) {
    n <- nrow(a)
    s <- .Fortran("eigvals", n = as.integer(n), a = a, vre = double(n), vim = double(n), info = 0L)
    structure(complex(real = s$vre, imaginary = s$vim), info = s$info)
  } else stop("Invalid input")
}

eigvals(a)

瞧,我们完成了!再次感谢大家!

byqmnocz

byqmnocz1#

您要查找的库是R-4.2.2\bin\x64目录中的Rblas.dll和Rlapack.dll(用您的版本替换4.2.2)。
这里有一个例子,让我们用LAPACK的dgeev来计算特征值。
Fortran文件eigvals.f90。这里为了简化,lwork是一个常量,但是在“真实的”代码中,你必须更小心地这样做。

subroutine eigvals(n, a, vre, vim, info)
    implicit none
    integer :: n, info
    integer, parameter :: lwork = 65536
    double precision :: a(n, n), vre(n), vim(n)
    double precision, save :: work(lwork)

    call dgeev("n", "n", n, a, n, vre, vim, 0d0, 1, 0d0, 1, work, lwork, info)
end subroutine

使用以下命令之一编译(根据需要更改路径)。如果您在Windows上,请从Rtools bash窗口执行此操作。在Linux上,扩展名是.so而不是. dll。

gfortran -shared -L/c/App/R/R-4.2.2/bin/x64 eigvals.f90 -lRlapack -o eigvals.dll
R CMD SHLIB eigvals.f90 -lRlapack

在R中,现在可以这样做,假设您将setwd()指向包含DLL的目录:

a <- matrix(c(2, 9, 4, 7, 5, 3, 6, 1, 8), 3, 3, byrow = T)

dyn.load("eigvals.dll")
is.loaded("eigvals")

eigvals <- function(a) {
  if (is.matrix(a) && is.double(a) && nrow(a) == ncol(a)) {
    n <- nrow(a)
    s <- .Fortran("eigvals", n = as.integer(n), a = a, vre = double(n), vim = double(n), info = 0L)
    structure(complex(real = s$vre, imaginary = s$vim), info = s$info)
  } else stop("Invalid input")
}

eigvals(a)

注意.Fortran中子例程参数的数量和类型,否则可能会使R崩溃。还要注意,必须调用Fortran子例程,而不是函数。
如果您在Windows上使用R-4.2和Rtools 4.2,还有一个额外的技巧:编译器不再位于默认目录中。请参见this。首先,您必须在Rtools bash窗口中执行以下操作:

export PATH=/x86_64-w64-mingw32.static.posix/bin:$PATH

如果从Windows命令提示符使用编译器,则必须相应地修改PATH环境变量。

相关问题