我用scipy.linalg.cython_lapack.syev
计算对称矩阵的特征值分解。从doc I found开始,我需要传递一个名为WORK的数组:
WORK是DOUBLE PRECISION数组,尺寸(MAX(1,LWORK)) 退出时,如果INFO = 0,则WORK(1)返回最佳LWORK。
但是,我无法看到它的作用(无法理解执行后的值是什么),也不知道它用于什么。这个参数的目的是什么?
答案 0 :(得分:4)
使用来自scipy.linalg.cython_lapack的dsyev()
的cython接口是有意义的:numpy eigh
wraps dsyevs和scipy 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()
等功能,其中仍需要参数work
和lwork
。因此,如果通过不在调用之间释放WORK
来在类似大小上多次调用例程,则可以减少分配数量,但是用户必须自己执行此操作(请参阅此example)。此外,调用LAPACK函数source of ILAENV
来计算WORK
的优化大小,具有以下文字:
这个版本提供了一组应该很好的参数, 但目前可用的许多表现并非最佳 电脑。建议用户修改此子例程进行设置 使用该选项调整其特定机器的参数 和参数中的问题大小信息。
因此,测试WORK的大小大于工作区查询返回的大小可以提高性能。
实际上,LAPACK中的许多函数都包含WORK
和LWORK
参数。如果您通过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
来查询建议的大小,也会出现这种情况。