我试图找到使用带有lapack的Fortran的nxn Hermitian矩阵的逆和本征函数。
如何为lda
,lwork
,liwork
和lrwork
等参数选择最佳值。我浏览一些例子并找到这些选择
integer,parameter::lda=nh
integer,parameter::lwork=2*nh+nh*nh
integer,parameter::liwork=3+5*nh
integer,parameter::lrwork=1 + 5*nh + 2*nh*nh
其中nh
是矩阵的维度。我还找到了lwork=16*nh
的另一个例子。我怎样才能确定最佳选择?此时,我正在处理500x500埃尔米特矩阵(最大值)。
我发现this documentation暗示
工作
(工作空间)REAL数组,维度(LWORK)
退出时,如果INFO = 0,则WORK(1)返回最佳LWORK。
LWORK
(输入)INTEGER
数组WORK的维度。 LWORKmax(1,N)。
为获得最佳性能LWORKN* NB,其中NB是ILAENV返回的最佳块大小。
对于给定的矩阵维度,是否可以使用WORK
或ILAENV
找出最佳块大小?
我正在使用gfortran和ifort与mkl。
修改
基于@percusse和@kvantour's answer的评论,这里有一个示例代码
character,parameter::jobz="v",uplo="u"
integer, parameter::nh=15
complex*16::m(nh,nh),m1(nh,nh)
integer,parameter::lda=nh
integer::ipiv(nh),info
complex*16::work(1)
real*8::rwork(1), w(nh)
integer::iwork(1)
real*8::x1(nh,nh),x2(nh,nh)
call random_seed()
call random_number(x1)
call random_number(x2)
m=cmplx(x1,x2)
m1=conjg(m)
m1=transpose(m1)
m=(m+m1)/2.0
call zheevd(jobz,uplo,nh,m,lda,w,work,-1,rwork,-1,iwork, -1,info)
print*,"info : ", info
print*,"lwork: ", int(work(1)) , 2*nh+nh*nh
print*,"lrwork:", int(rwork(1)) , 1 + 5*nh + 2*nh*nh
print*,"liwork:", int(iwork(1)) , 3+5*nh
end
info:0
lwork:255 255
工作:526 526
liwork:78 78
答案 0 :(得分:3)
我不确定你的意思“是否有可能使用WORK
或ILAENV
找出特定机器架构的最佳块大小?” 。但是,您可以找到特定问题的最佳值。
EG。如果要使用cheev
找到复杂Hermitian矩阵的特征值,可以让例程返回值:
subroutine CHEEV( JOBZ, UPLO, N, A, LDA, W, WORK, LWORK, RWORK, INFO )
character , intent(in) :: JOBZ
character , intent(in) :: UPLO
integer , intent(in) :: N
complex, dimension(lda,*), intent(inout) :: A
integer , intent(in) :: LDA
real , dimension(*) , intent(out) :: W
complex, dimension(*) , intent(out) :: WORK
integer , intent(in) :: LWORK
real , dimension(*) , intent(out) :: RWORK
integer , intent(out) :: INFO
然后documentation明确指出(建议过去这更容易阅读):
WORK
是COMPLEX
数组,维(MAX(1,LWORK))
退出时,如果INFO = 0
,则WORK(1)
会返回最佳LWORK
。
LWORK
是INTEGER
数组WORK
的长度。LWORK >= max(1,2*N-1)
。 为了获得最佳效率,LWORK >= (NB+1)*N
, 其中NB
是CHETRD
返回的ILAENV
的块大小。如果LWORK = -1
,则假定工作空间查询;例程 仅计算WORK
数组的最佳大小,返回 此值作为WORK
数组的第一个条目,并且没有错误 与LWORK
相关的邮件由XERBLA
发出。
所以你需要做的就是
call cheev(jobz, uplo, n, a, lda, w, work, -1, rwork, info)
lwork=int(work(1))
dallocate(work)
allocate(work(lwork))
call cheev(jobz, uplo, n, a, lda, w, work, lwork, rwork, info)