[英]Error in Lapack routine SGELS using an interface and allocatable WORK array
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
数组的查询例程,例如shape
、 size
、 is_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.经过几次排列后,这是代码的最小工作示例。
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
(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
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.
% gcc --version (1c01947)fortran-alpha
gcc (Spack GCC) 10.2.0
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
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
How do I fix the interface and the call to allow the use of an allocatable
WORK
array?如何修复接口和调用以允许使用
allocatable
的WORK
数组?
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.