在 C++ 中存储大矩阵(犰狳)
Posted
技术标签:
【中文标题】在 C++ 中存储大矩阵(犰狳)【英文标题】:Storing big matrices in C++ (Armadillo) 【发布时间】:2013-09-20 16:08:11 【问题描述】:我在 C++ 中使用 Armadillo 库来存储/计算大型矩阵。我的理解是应该动态地(在堆上)存储大型数组/矩阵。
假设我声明一个矩阵
mat X;
并将大小设置为(例如)500 行,500 列,随机条目:
X.randn(500,500);
尽管没有使用new
或delete
,犰狳是否会动态存储X
(即在堆上)?我问的原因是,似乎犰狳允许我将变量声明为:
mat::fixed<n_rows, n_cols>
其中,我quote:“一般比动态内存分配要快,但是以后不能(直接或间接)改变矩阵的大小”。
不管上述情况——我应该使用这个吗:
mat A;
A.set_size(n-1,n-1);
或者这个:
mat *A = new mat;
(*A).set_size(n-1,n-1);
其中 n 介于 1000 或 100000 之间,并且事先不知道。
【问题讨论】:
100000*100000*4
大约 40 GB,这可能需要虚拟内存并带来一大堆问题。
一般我建议不要使用指针,因为它们很容易出错:它们经常导致内存泄漏或内存损坏。指针通常只在经过良好测试的库中有用,而不是在用户代码中。将对象传递给函数时,最好使用引用。要存储一组对象,请使用包含指针的 C 数组的容器类 instead。
【参考方案1】:
犰狳是否动态存储 X(即在堆上),尽管没有 使用
new
或delete
.?
是的。库代码中会有某种形式的new
或delete
。你只是没有从外面注意到它。
我问的原因是因为它似乎是犰狳 允许我将变量声明为 (
mat::fixed
...)
您必须查看源代码才能了解这里到底发生了什么。我的猜测是它具有某种内部逻辑,可以根据大小决定如何处理事物。不过,对于小型矩阵,您通常会使用 mat::fixed
。
接下来,你应该使用
mat A(n-1,n-1);
如果您当时已经知道尺寸。在某些情况下,
mat A;
A.set_size(n-1,n-1);
也可能没问题。
我想不出将第二个选项与@987654331@ 指针一起使用的充分理由。首先,像犰狳这样的库在内部处理它们的内存分配,开发人员非常小心地把它弄好。此外,即使库中的内存代码被破坏,您的想法new mat
也无法修复它:您将为mat
对象分配内存,但该对象肯定相当小。很大一部分可能隐藏在 mat
类中的成员变量 T* data
之类的东西后面,您无法从外部影响它的分配方式。
我最初错过了您对n
大小的评论。正如 Mikhail 所说,处理 100000x100000 矩阵需要比简单地考虑实例化它们的方式更加小心。
【讨论】:
感谢您写得很好的解释。关于大 n:不过,我的想法是否正确,如果我可以访问具有 512GB 内存(不是硬盘空间)的计算机——它会运行良好吗? @user2432701 我认为它会运行良好(假设单个进程没有内存限制!)。但是您还必须考虑运行时间!如果你尝试更复杂的东西,它很可能在我们的有生之年不会完成。 再次感谢您的建议。当您说“我想不出将第二个选项与 mat * 指针一起使用的充分理由”时——好吧,当我需要存储大量大型矩阵时,是否可以接受?如果不是,为什么? @fushsialatitude 一般来说,我不会推荐它。mat
的簿记数据似乎约为 160 字节 (sizeof(mat)
)。与大型矩阵的数据块(500x500x8 字节 = 2MB)相比,这是最小的。所以我个人会为大量的大矩阵推荐std::vector<mat>
。
您还可以使用犰狳的field class 来存储多个矩阵,例如。 field<mat>
。 std::vector<mat>
的优势在于 field<mat>
可以引用 2D 布局中的存储对象,即。你可以有一个矩阵矩阵。也可以使用.save() 将field<mat>
对象存储为文件。以上是关于在 C++ 中存储大矩阵(犰狳)的主要内容,如果未能解决你的问题,请参考以下文章