首页 > 解决方案 > 在 Fortran 中为 Lapack 使用显式接口:链接查找模块文件失败

问题描述

问题

为Lapack添加外部接口后,与消息链接时代码失败

Undefined symbols for architecture x86_64:
  "___msolutionsvd_MOD_dgesvd", referenced from:
      ___msolutionsvd_MOD_svd_pseudoinverse_solve_sub in m-solution-svd.o

似乎链接器正在寻找我的安装DGESVD.mod中未包含的文件。openblas

代码

这有效

模块module mSolutionSVD使用了声明

external DGESVD

指向 BLAS 例程并contains subroutine svd_pseudoinverse_solve_sub 调用DGESVD.

这失败了

声明被显式接口替换

    interface lapack
        module subroutine DGESVD ( JOBU, JOBVT, M, N, A, LDA, S, U, LDU, VT, LDVT, WORK, LWORK, INFO )
            character ( kind = kindA, len = 1 ), intent ( in )    :: JOBU, JOBVT
            integer ( kind = ip ),               intent ( in )    :: M, N, LDA, LDU, LWORK
            integer ( kind = ip ),               intent ( out )   :: INFO
            real ( kind = rp ),                  intent ( out )   :: S ( : ), U ( : , : ), VT ( : , : ), WORK ( : )
            real ( kind = rp ),                  intent ( inout ) :: A ( : , : )
        end subroutine DGESVD
    end interface lapack

背景

kind 语句来自具有以下语句的例程:

use, intrinsic :: iso_fortran_env, only : INT8, REAL64
integer, parameter :: kindA = kind ( 'A' ) 
integer, parameter :: rp = selected_real_kind ( REAL64 )
integer, parameter :: ip = selected_int_kind  ( INT64 )

问题

我们可以为 Lapack 使用外部接口而无需重新编译 Lapack 吗?

标签: externallapackblasexplicit-interface

解决方案


您的代码存在三个问题,其中两个与您的问题无关。

首先,数据类型的定义应该是

use, intrinsic :: iso_fortran_env, only : INT64, REAL64
integer, parameter :: kindA = kind ( 'A' ) 
integer, parameter :: rp = REAL64
integer, parameter :: ip = INT64

这是因为预定义的常量已经代表了行列,而辅助函数INT64期望得到有效的小数位数。REAL64selected_*_kind

其次,你的界面没有指定参数LDVT

第三,也是最重要的,您声明DGESVD为 a module subroutine,通过它您说子例程位于当前模块中。但事实并非如此。Lapack 子程序不在任何模块中。因此,您需要module从接口定义中省略关键字。

注意:如果数据类型kindA,rpip定义在同一个模块中,那么在module从接口声明中删除关键字后,您还需要添加该行

import kindA, ip, rp

就在原型线下方subroutine DGESVD (...


推荐阅读