简体   繁体   English

使用接口和可分配 WORK 数组的 Lapack 例程 SGELS 中的错误

[英]Error in Lapack routine SGELS using an interface and allocatable WORK array

Problem:问题:

Using an explicit interface for Lapack ( http://www.netlib.org/lapack/ ) routines simplifies coding.为 Lapack ( http://www.netlib.org/lapack/ ) 例程使用显式接口可简化编码。 There is a problem with routines like SGELS ( https://www.netlib.org/lapack/explore-3.1.1-html/sgels.f.html ) which require a WORK ( https://www.netlib.org/lapack/lug/node117.html ) array of variable size. There is a problem with routines like SGELS ( https://www.netlib.org/lapack/explore-3.1.1-html/sgels.f.html ) which require a WORK ( https://www.netlib.org/ lapack/lug/node117.html ) 可变大小数组。 Fixing the size of the WORK array to a large number is successful, but defeats the economy of Lapack.WORK数组的大小固定为一个大数是成功的,但会破坏 Lapack 的经济性。

But I am unable to use an allocatable array for WORK .但我无法为WORK使用allocatable的数组。

The usual error message is something like通常的错误信息类似于

Program received signal SIGSEGV: Segmentation fault - invalid memory reference.

Fortran query routines on the WORK array such as shape , size , is_contiguous and bounds checking are successful. Fortran 对WORK数组的查询例程,例如shapesizeis_contiguous和边界检查成功。 But any attempt to print a value from the array produces a segmentation fault.但是任何从数组中打印值的尝试都会产生分段错误。

After several permutations, here is a minimal working example of the code.经过几次排列后,这是代码的最小工作示例。

Code代码

Main program主程序

program mwe

    use mLapackInterfaceSGELS, only : sgels
    implicit none

    integer, parameter :: n = 2

    real, dimension ( : ),     allocatable :: work
    real, dimension ( : , : ), allocatable :: AstarA, Astarb

    integer :: nrhs = 0, lda = 0, ldb = 0, lwork = 0, info = 0

        lda = n
        ldb = n
        nrhs = 1
        lwork = -1

        allocate ( Astarb ( 1 : n, 1 : 1 ) )
        allocate ( AstarA ( 1 : n, 1 : n ) )
        allocate ( work ( 1 : 2 ) )

        Astarb ( 1 : n, 1 )     = [ 466.7, 2898.]
        AstarA ( 1 : n, 1 : n ) = reshape ( [ [ 9., 45. ], [ 45., 285.] ], [ n, n ] )
        work ( 1 : 2 ) = 0.0

        write ( * , * ) "work array before query = ", work

        call sgels( trans = 'No transpose', m = n, n = n, nrhs = nrhs, A = AstarA, lda = lda, b = Astarb, ldb = ldb, &
                    work = work, lwork = -1, info = info )

        write ( * , * ) "out: shape ( work ) = ", shape ( work )
        write ( * , * ) "lbound ( work ) = ", lbound ( work )
        write ( * , * ) "ubound ( work ) = ", ubound ( work )
        write ( * , * ) "size ( work ) = ", size ( work )
        write ( * , * ) "is_contiguous ( work ) = ", is_contiguous ( work )
        write ( * , * ) "work array after query = ", work

    stop
end program mwe

Interface module接口模块

(As seen in Numerical Methods with Modern Fortran, Richard Hanson, Tim Hopkins, Listing 2.5. ( https://my.siam.org/Store/Product/viewproduct/?ProductId=24372445 )) (如使用现代 Fortran 的数值方法中所见,Richard Hanson,Tim Hopkins,清单 2.5。( https://my.siam.org/Store/Product/viewproduct/?ProductId=24372445 ))

module mLapackInterfaceSGELS

    implicit none

    interface lapack_sgels

        subroutine sgels ( trans, m, n, nrhs, A, lda, b, ldb, work, lwork, info )
            integer,           intent ( in )    :: m, n, nrhs, lda, ldb, lwork
            integer,           intent ( out )   :: info
            real, allocatable, intent ( out )   :: work ( : )
            real,              intent ( inout ) :: A ( 1 : lda , 1 : n ), b ( 1 : ldb , 1 : nrhs )
            character,         intent ( in )    :: trans
        end subroutine sgels

    end interface lapack_sgels

end module mLapackInterfaceSGELS

Output from code Output 来自代码

The line which causes the error is:导致错误的行是:

write ( * , * ) "work array after query = ", work

The output from the code is:代码中的 output 是:

 work array before query =    0.00000000       0.00000000    
 out: shape ( work ) =            2
 lbound ( work ) =            1
 ubound ( work ) =            2
 size ( work ) =            2
 is_contiguous ( work ) =  T

Program received signal SIGSEGV: Segmentation fault - invalid memory reference.

Compiler version编译器版本

% gcc --version                                                                        (1c01947)fortran-alpha
gcc (Spack GCC) 10.2.0

Compilation汇编

gfortran -g -c -Og -pedantic -Wall -Warray-temporaries -Wextra -Waliasing -Wsurprising -Wimplicit-procedure -Wintrinsics-std -Wfunction-elimination -Wc-binding-type -Wrealloc-lhs-all -Wuse-without-only -Wconversion-extra -fno-realloc-lhs -ffpe-trap=denormal,invalid,zero -fbacktrace -fmax-errors=5 -fcheck=all -fcheck=do -fcheck=pointer -fno-protect-parens -faggressive-function-elimination -fdiagnostics-color=auto -finit-derived -o m-lapack-interface-sgels.o m-lapack-interface-sgels.f08
gfortran -g -c -Og -pedantic -Wall -Warray-temporaries -Wextra -Waliasing -Wsurprising -Wimplicit-procedure -Wintrinsics-std -Wfunction-elimination -Wc-binding-type -Wrealloc-lhs-all -Wuse-without-only -Wconversion-extra -fno-realloc-lhs -ffpe-trap=denormal,invalid,zero -fbacktrace -fmax-errors=5 -fcheck=all -fcheck=do -fcheck=pointer -fno-protect-parens -faggressive-function-elimination -fdiagnostics-color=auto -finit-derived -o mwe.o mwe.f08

Execution执行

Two different Lapack libraries were used.使用了两个不同的 Lapack 库。 Both produced the same failure.两者都产生了同样的失败。

/usr/local/lib
gfortran -g -L/usr/local/lib -llapack -lblas -o mwe m-lapack-interface-sgels.o mwe.o
Apple Accelerate framework 苹果加速框架
./mwe 2>&1 | tee output.txt 

Tip: Consider redirecting the output to avoid overrunning the screen buffer:提示:考虑重定向 output 以避免溢出屏幕缓冲区:

 ./mwe 2>&1 | tee output.txt

Question问题

How do I fix the interface and the call to allow the use of an allocatable WORK array?如何修复接口和调用以允许使用allocatableWORK数组?

Reference: 参考:

Parameter corruption when interfacing FORTRAN lapack routine 连接 FORTRAN lapack 例程时参数损坏

Segmentation error in fortran LAPACK routine fortran LAPACK 例程中的分段错误

You seem to be somewhat confused about how LAPACK routines work.您似乎对 LAPACK 例程的工作方式有些困惑。 Showing their vintage they never do any memory management for you, you have to allocate all memory yourself before you call the routines.展示他们的年份,他们从不为您做任何 memory 管理,您必须在调用例程之前自己分配所有 memory。 Thus a dummy argument can never be allocatable for a LAPACK routine - and I have to say I would find it hard to trust any book that claims the above is the correct interface.因此,虚拟参数永远不能分配给 LAPACK 例程——我不得不说,我很难相信任何声称上述是正确接口的书。

So your interface is wrong.所以你的界面是错误的。 But also are you confused about how workspace queries work in LAPACK?但是您是否对 LAPACK 中的工作区查询如何工作感到困惑? The routine doesn't allocate any memory for you - you call it once with the workspace argument sent to -1 to indicate that this is a workspace query, as documented at sgles documentation page , and this call will return the required size of the workspace array in work( 1 ).该例程不会为您分配任何 memory - 您调用它一次,将工作空间参数发送到 -1 以指示这是一个工作空间查询,如sgles 文档页面所述,此调用将返回所需的工作空间大小工作中的数组(1)。 You then allocate the work array to the correct size, and finally call the routine again with the correct arguments for the workspace.然后,您将工作数组分配给正确的大小,最后使用工作区的正确 arguments 再次调用例程。 It's all a bit clunky, again showing LAPACK's age, but I hope the above is clear都是有点笨拙,再次显示LAPACK的年龄,但希望上面说清楚

Below is what I think is a correct version of what you want to do.以下是我认为您想要做的正确版本。 Note I have made a couple of other small changes to your LAPACK interface to make it what I think is the fully correct version, and I have also removed the unnecessary initialisation of a lot of your variables - this is a bad habit to get into, it can mask bugs, or at least make them harder to find, and worse is often more or less incompatible with threaded programming, an important form of parallelism that I personally think all Fortran programmers should have some familiarity with.请注意,我对您的 LAPACK 界面进行了一些其他小的更改,以使其成为我认为完全正确的版本,并且我还删除了许多变量的不必要初始化 - 这是一个不好的习惯,它可以掩盖错误,或者至少使它们更难找到,更糟糕的是通常或多或少与线程编程不兼容,我个人认为所有 Fortran 程序员都应该熟悉的一种重要的并行性形式。

ijb@ijb-Latitude-5410:~/work/stack$ cat sgles.f90
module mLapackInterfaceSGELS

  implicit none

  interface lapack_sgels

     subroutine sgels ( trans, m, n, nrhs, A, lda, b, ldb, work, lwork, info )
       integer,   intent ( in )    :: m, n, nrhs, lda, ldb, lwork
       integer,   intent ( out )   :: info
       real,      intent ( out )   :: work ( * )
       real,      intent ( inout ) :: A ( 1 : lda , * ), b ( 1 : ldb , * )
       character, intent ( in )    :: trans
     end subroutine sgels

  end interface lapack_sgels

end module mLapackInterfaceSGELS

program mwe

  use mLapackInterfaceSGELS, only : sgels
  implicit none

  integer, parameter :: n = 2

  real, dimension ( : ),     allocatable :: work
  real, dimension ( : , : ), allocatable :: AstarA, Astarb

  Real, Dimension( 1:1 ) :: r_lwork 
  
  integer :: nrhs, lda, ldb, lwork, info

  lda = n
  ldb = n
  nrhs = 1
  lwork = -1

  allocate ( Astarb ( 1 : n, 1 : 1 ) )
  allocate ( AstarA ( 1 : n, 1 : n ) )

  Astarb ( 1 : n, 1 )     = [ 466.7, 2898.]
  AstarA ( 1 : n, 1 : n ) = reshape ( [ [ 9., 45. ], [ 45., 285.] ], [ n, n ] )

  call sgels( trans = 'No transpose', m = n, n = n, nrhs = nrhs, A = AstarA, lda = lda, b = Astarb, ldb = ldb, &
       work = r_lwork, lwork = -1, info = info )
  lwork = Nint( r_lwork( 1 ) )
  Allocate( work( 1:lwork ) )
  call sgels( trans = 'No transpose', m = n, n = n, nrhs = nrhs, A = AstarA, lda = lda, b = Astarb, ldb = ldb, &
       work = work, lwork = lwork, info = info )

  write ( * , * ) "out: shape ( work ) = ", shape ( work )
  write ( * , * ) "lbound ( work ) = ", lbound ( work )
  write ( * , * ) "ubound ( work ) = ", ubound ( work )
  write ( * , * ) "size ( work ) = ", size ( work )
  write ( * , * ) "is_contiguous ( work ) = ", is_contiguous ( work )
  write ( * , * ) "work array after query = ", work

  stop
end program mwe
ijb@ijb-Latitude-5410:~/work/stack$ gfortran --version
GNU Fortran (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

ijb@ijb-Latitude-5410:~/work/stack$ gfortran -Wall -Wextra -fcheck=all -std=f2018 -O -g sgles.f90 -lopenblas
ijb@ijb-Latitude-5410:~/work/stack$ ./a.out
 out: shape ( work ) =           66
 lbound ( work ) =            1
 ubound ( work ) =           66
 size ( work ) =           66
 is_contiguous ( work ) =  T
 work array after query =    66.0000000       0.00000000       4192.00000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000       0.00000000    

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM