如何使用 C++ 将 Eigen 稀疏矩阵转换为数组?
Posted
技术标签:
【中文标题】如何使用 C++ 将 Eigen 稀疏矩阵转换为数组?【英文标题】:How to convert an Eigen sparse matrix into an array in C++ using the? 【发布时间】:2015-07-02 11:37:57 【问题描述】:我使用 Eigen 包在 C++ 中创建了一个稀疏矩阵 mat
。矩阵工作正常,但我试图将其转换为数组以用作位图。 mat
的大小为N+1。
天真地,我尝试了以下操作:
double zmat[N+1][N+1];
for(int i=0; i<=N; i++)
for(int j=0; j<=N; j++)
zmat[i][j]=mat.coeffRef(i,j);
但这在我调试时给了我一个例外:
Unhandled exception at 0x0116B2C7 in Open_GL_test.exe: 0xC00000FD: Stack overflow (parameters: 0x00000000, 0x001D2000).
有什么想法吗?
【问题讨论】:
N
的值是多少?它一定很大,你遇到了堆栈溢出。
你为什么使用这个N+1
符号?恕我直言,zmat[N][N]
和 i<N
/j<N
更干净
@CoryKramer N = 600 在这个例子中。
@tobi303 该矩阵用于建立一维有限元问题。我让 N 表示段数,所以有 N+1 个点。
【参考方案1】:
double zmat[N+1][N+1];
这就是给您带来麻烦的原因。在函数中将大矩阵声明为局部变量并不是一个好主意。局部变量在堆栈上分配。许多机器将堆栈的大小限制为少量数据。在我的机器上,堆栈限制约为 8 兆字节。这意味着N
的值大于大约一千将立即导致堆栈溢出。 N
的值大于几百(但小于一千)将导致在调用树的下方某处难以跟踪堆栈溢出。
不要在堆栈上分配大量数据。一些替代方案是
在命名空间范围内声明变量, 使用new
和delete
分配(随后释放)矩阵,
使用普通的 Eigen 矩阵,它会为您执行 new
和 delete
。
【讨论】:
【参考方案2】:David Hammen's 答案是正确的(double zmat[N+1][N+1];
对于堆栈来说太大了)。但是,我觉得有必要为您的使用付出两分钱。
双循环不必要地冗长且缓慢。更糟糕的是,在矩阵的每个元素上使用coeffref
实际上会使矩阵有效地密集。在documentation for coeffRef
中它说:
如果元素不存在,则通过 insert(Index,Index) 函数将其插入,如果不存在,该函数本身会将矩阵转换为非压缩形式。 如果元素不存在,这是一个 O(log(nnz_j)) 操作(二分查找)加上 insert(Index,Index) 函数的成本。
这意味着它不仅冗长,而且会增加您的内存需求并可能成为瓶颈。您可以改为使用
MatrixXd::Map(&zmat[0], (N+1), (N+1)) = mat.toDense();
或
MatrixXd::Map(zmat, (N+1), (N+1)) = mat.toDense(); // double zmat = new ...
这不仅更具可读性,而且效率也更高。
【讨论】:
这行不通。需要双循环,因为mat.coeffRef(i,j)
是一个稀疏矩阵。
糟糕,错过了。固定。以上是关于如何使用 C++ 将 Eigen 稀疏矩阵转换为数组?的主要内容,如果未能解决你的问题,请参考以下文章