我想创建一个大小为10 6 ×10 6 元素的二维整数数组。为此,我正在使用boost库:
boost::multi_array<int, 2> x(boost::extents[1000000][1000000]);
但它引发了以下异常:
在抛出'std :: bad_alloc'实例后终止调用 what():std :: bad_alloc
请告诉我如何解决问题。
答案 0 :(得分:5)
你真的不想分配一个巨大的数组。它的内存大约是4TB。
根据您对该阵列的处理方式,您应该考虑两个选项:
外部数据结构。阵列将写在硬盘上。最近访问的部分也在RAM中,因此根据您访问它的方式,它可以非常快,但当然永远不会像在RAM中完全一样快。查看STXXL的外部数据结构。
此方法的优点是可以访问数组中的所有元素(与您将看到的第二种方法相反)。然而,问题仍然存在:即使在硬盘驱动器上,4TB也非常大,至少如果你在谈论一般的桌面应用程序。
稀疏数据结构。如果您实际上只需要该数组中的一些项目,但是您想要在10⁶⁶10⁶大小的空间内处理这些项目,请不要使用一个数组,但像地图或两者的组合:在“块”中分配数组,比方说1024 x 1024元素。将这些块放入映射中,同时引用块索引(坐标除以1024)作为映射中的键。
此方法的优点是您不必链接到另一个库,因为它可以由您自己轻松编写。但是,它的缺点是,如果访问分布在整个坐标空间10⁶⁶10⁶或甚至需要所有值的元素,它也会使用大约4TB(甚至更多)的内存。它只适用于您实际只能访问这个巨大的“虚拟”阵列的智能部分。
以下(未经测试的)C ++代码应该证明这一点:
class Sparse2DArray
{
struct Coord {
int x, y;
Coord(int x, int y) : x(x), y(y) {}
bool operator<(const Coord &o) const { return x < o.x || (x == o.x && y < o,y); } // required for std::map
};
static const int BLOCKSIZE = 1024;
std::map<Coord, std::array<std::array<int,BLOCKSIZE>,BLOCKSIZE> blocks;
static Coord block(Coord c) {
return coord(c.x / BLOCKSIZE, c.y / BLOCKSIZE);
}
static Coord blockSubCoord(Coord c) {
return coord(c.x % BLOCKSIZE, c.y % BLOCKSIZE);
}
public:
int & operator[](int x, int y) {
Coord c(x, y);
Coord b = block(c);
Coord s = blockSubCoord(c);
return blocks[b][s.x][s.y];
}
};
您可以使用std::map
(哈希映射)代替std::unordered_map
,但必须为operator<
类型定义哈希函数而不是Coord
(或使用std::pair
代替。)
答案 1 :(得分:2)
当您以这种方式创建数组时,它将在堆栈上创建,并且堆栈的大小有限。因此,您的程序将崩溃,因为它没有足够的空间来分配那么大的数组。
有两种方法可以解决这个问题,你可以使用new关键字在heap上创建数组但是你必须删除它后面的内容,否则你会有内存泄漏,同时要小心,因为堆具有更大的内存大小,然后堆栈仍然是有限的。
另一种方法是让你在std::vector
内使用std::vector
并让它为你处理内存。
答案 2 :(得分:0)
您打算创建一个10 6 ×10 6 矩阵?如果你试图创建一个稀疏矩阵(即10个sup <6>有限元的传热问题的扩散矩阵),那么你应该看看使用现有的线性代数库。例如,trilinos项目支持解决大型稀疏矩阵,例如您可能尝试创建的稀疏矩阵。