LAPACK例程中WORK参数的用途是什么?

时间:2017-10-07 08:50:32

标签: python cython lapack lapacke

我用scipy.linalg.cython_lapack.syev计算对称矩阵的特征值分解。从doc I found开始,我需要传递一个名为WORK的数组:

  

WORK是DOUBLE PRECISION数组,尺寸(MAX(1,LWORK))             退出时,如果INFO = 0,则WORK(1)返回最佳LWORK。

但是,我无法看到它的作用(无法理解执行后的值是什么),也不知道它用于什么。这个参数的目的是什么?

2 个答案:

答案 0 :(得分:4)

使用来自scipy.linalg.cython_lapack的dsyev()的cython接口是有意义的:numpy eigh wraps dsyevsscipy eigh wraps dsyevr()。但是,遵循dsyev()的Fortran原型,必须提供数组WORK。

WORK需要数组syev供内部使用(期望LWORK = -1}。

LAPACK写在Fortran 77和{langage does not support dynamic allocation on the heap in its standards中!动态分配可能是平台形式依赖的,也可能是由特定的编译器扩展提供的。因此,编写LAPACK以便用户可以使用他/她想要的任何东西:静态数组,在堆栈上分配的数组或在堆上分配的数组。

实际上,对库中WORK数组的大小进行硬编码会触发两个尴尬的情况。数组太大,没有增加内存占用,或者数组太小,导致性能不佳或出错(分段错误......)。结果,内存管理留给库的用户。向用户提供了一些帮助,因为如果LWORK = -1提供了阵列的最佳大小。

如果动态分配可用,LAPACK函数最常见的用法是首先使用LWORK = -1执行工作区查询,然后使用返回值分配正确大小的WORK数组,最后调用LAPACK的例程来获得预期的结果。 LAPACK的高端包装器(如LAPACKE)具有这样的功能:看看source of LAPACKE for function LAPACKE_dsyev()!它调用函数LAPACKE_dsyev_work的两倍,该函数调用LAPACK_dsyev(包裹dsyev())。

Wrappers仍然具有LAPACKE_dsyev_work()等功能,其中仍需要参数worklwork。因此,如果通过不在调用之间释放WORK来在类似大小上多次调用例程,则可以减少分配数量,但是用户必须自己执行此操作(请参阅此example)。此外,调用LAPACK函数source of ILAENV来计算WORK的优化大小,具有以下文字:

  

这个版本提供了一组应该很好的参数,     但目前可用的许多表现并非最佳     电脑。建议用户修改此子例程进行设置     使用该选项调整其特定机器的参数     和参数中的问题大小信息。

因此,测试WORK的大小大于工作区查询返回的大小可以提高性能。

实际上,LAPACK中的许多函数都包含WORKLWORK参数。如果您通过alloc在文件夹lapack-3.7.1 / SRC中搜索grep -r "alloc" . ,则输出仅包含注释行:

    ./zgejsv.f:*>          Length of CWORK to confirm proper allocation of workspace.
    ./zgejsv.f:*>            In both cases, the allocated CWORK can accommodate blocked runs
    ./zgejsv.f:*>          Length of RWORK to confirm proper allocation of workspace.
    ./zgesdd.f:*       minimal amount of workspace allocated at that point in the code,
    ./zhseqr.f:*     ==== NL allocates some local workspace to help small matrices
    ./dhseqr.f:*     ==== NL allocates some local workspace to help small matrices
    ./dgesdd.f:*       minimal amount of workspace allocated at that point in the code,
    ./shseqr.f:*     ==== NL allocates some local workspace to help small matrices
    ./chseqr.f:*     ==== NL allocates some local workspace to help small matrices
    ./sgesdd.f:*       minimal amount of workspace allocated at that point in the code,
    ./sgejsv.f:*>          Length of WORK to confirm proper allocation of work space.
    ./cgejsv.f:*>          Length of CWORK to confirm proper allocation of workspace.
    ./cgejsv.f:*>            In both cases, the allocated CWORK can accommodate blocked runs
    ./cgejsv.f:*>          Length of RWORK to confirm proper allocation of workspace.
    ./dgejsv.f:*>          Length of WORK to confirm proper allocation of work space.
    ./cgesdd.f:*       minimal amount of workspace allocated at that point in the code,

它表明LAPACK的核心不能通过像allocate这样的命令处理堆上的动态内存分配,对于大型数组是useful:用户必须自己关心它。

答案 1 :(得分:1)

syev在计算过程中需要额外的空间,调用者必须提供此内存(work数组)。

计算所需的额外内存量极少,但是如果您能够分配更多内存,计算将从中获利并且速度更快。

工作数组的最小大小应为(nb +2)n,其中nb是块大小(可以通过ilaenv计算)。

通常,一个人提供更多的记忆:一个人知道最佳大小,因为矩阵的结构是已知的,或者通过syev调用lwork = -1,这将返回最佳大小(在{{ 1}}数组):

work

double query; int lwork = -1; dsyev(..., &query, lwork);//query the work-size (error handling missing) lwork=(int) query; //cast the returned double to int to get the size .... - 内容的大部分内容只是一些垃圾,我想你可以通过查看数据来获得对算法工作的一些见解 - 但这是依赖于实现的。

但是,work的第一个条目将是工作数组的建议大小,如果您通过设置work来查询建议的大小,也会出现这种情况。