我使用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);
}
}
但是当我调试时,这给了我一个例外:
Open_GL_test.exe中0x0116B2C7处的未处理异常:0xC00000FD:堆栈溢出(参数:0x00000000,0x001D2000)。
有什么想法吗?
答案 0 :(得分:3)
N
这就是导致你麻烦的原因。在函数中将大矩阵声明为局部变量并不是一个好主意。局部变量在堆栈上分配。许多机器将堆栈的大小限制为少量数据。在我的机器上,堆栈限制大约是8兆字节。这意味着大于约一千的N
值将立即导致堆栈溢出。值new
大于几百(但小于一千)将导致在调用树的下游某处出现难以跟踪的堆栈溢出。
不要在堆栈上分配大量数据。
是一些替代方案delete
和new
,delete
和{{1}}。答案 1 :(得分:1)
David Hammen's回答是正确的(double zmat[N+1][N+1];
对于堆栈来说太大了)。但是,我觉得有必要在使用方面投入两分钱。
双循环不必要地冗长和缓慢。更糟糕的是,在矩阵的每个元素上使用coeffref
实际上使矩阵有效地密集。在coeffRef
MatrixXd::Map(&zmat[0], (N+1), (N+1)) = mat.toDense();
中,它说:
如果元素不存在则通过插入(索引,索引)函数插入它,如果不是这种情况,它本身会将矩阵转换为非压缩形式。
这是一个O(log(nnz_j))操作(二进制搜索)加上插入(索引,索引)函数的成本(如果该元素尚不存在)。
这意味着它不仅冗长,而且会增加您的内存需求并可能成为瓶颈。您可以改为使用
MatrixXd::Map(zmat, (N+1), (N+1)) = mat.toDense(); // double zmat = new ...
或
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "[App name].settings")
这不仅更具可读性,而且效率更高。