我在c ++中的std :: vector遇到内存问题。这是我的代码:
#include <iostream>
#include <vector>
int main () {
std::vector< std::vector<float> > mesh_points_A;
int N=10;
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
std::vector<float> xyz;
xyz.push_back(i);
xyz.push_back(j);
xyz.push_back(0.3);
mesh_points_A.push_back(xyz);
}
}
return 0;
}
当我将N增加到10000或更高时,我的内存用完了...但是我认为我做的事情完全错误,因为例如,如果我将python与numpy数组一起使用,这将很容易...
非常感谢。
编辑:这是原始代码。上面的代码只是为了更好地说明问题而进行的简化。问题是,是否有可能在保持N = 10000的情况下在不耗尽内存的情况下创建许多Surface对象(在代码中当前有两个)。
// classes example compile with c++ -o Surface Surface.cpp -std=c++11
#include <iostream>
#include <vector>
#include <array>
class Surface {
private:
std::vector< std::array<float,3> > mesh_points_A;
public:
float R;
float z; // z position if the suface
int n_A; //number of area mesh points mesh_points_A.size()
Surface(int nxA, float R , float z);
};
Surface::Surface(int nxA, float R,float z)
: z(z)
, R(R)
{
float dxA= 2*R/(nxA*1.0-1.0);
//determine n_A,
n_A=0;
for(int i=0;i<nxA;i++){
float x = -R+i*dxA;
for(int j=0;j<nxA;j++){
float y = -R+j*dxA;
if(x*x+y*y<R*R){
n_A+=1;
}
}
}
std::cout<<"Number of area mesh points: "<<n_A<<std::endl;
mesh_points_A.reserve(n_A);
for(int i=0;i<nxA;i++){
float x = -R+i*dxA;
for(int j=0;j<nxA;j++){
float y = -R+j*dxA;
if(x*x+y*y<R*R){
std::array<float,3> xyz{ {x,y,z} };
mesh_points_A.push_back(xyz);
}
}
}
}
int main () {
int N= 20000;
Surface s1(N,0.1,0.0);
Surface s2(N,0.1,0.1);
return 0;
}
答案 0 :(得分:4)
您的媒介需要连续重新分配更多内存以保持增长。它通过保留更大的新内存区域并复制旧数据来做到这一点。这取决于实现方式,要保留多少内存,但是典型的策略是分配两倍的内存(libstdc ++会这样做)。
这意味着,在最坏的情况下,您的总内存需求可能是原始内存需求的 3倍:
假设您的向量当前包含90,000,000个元素,不幸的是,它的容量也为90,000,000 1 。要插入第90,000,001st个元素,std::vector
现在会保留两倍的内存-180,000,000,将所有旧元素复制过来,然后破坏旧数组。
因此,即使“仅”需要100,000,000个元素,您也必须短暂地为270,000,000个元素分配存储。即使您的100M向量仅需要3.35 GiB,这也相当于大约9.10 GiB。
可以通过将以下行放在嵌套的初始化循环前面来完全避免这种情况:
mesh_points_A.reserve(N * N);
1 实际上,容量可能是2的幂,例如2 26 = 67,108,864;仍需要调整6.75 GiB的内存大小。
答案 1 :(得分:3)
std::vector
具有根据需要动态更改大小的灵活性。一如既往,灵活性是有代价的。通常,该价格很小,可以轻松忽略,尽管在这种情况下,当您使用std::vector<float>
与std::array<float,3>
时,由于您拥有1亿个元素,因此差异非常大。例如,如果我们运行以下代码:
std::vector<float> v;
for( auto f : { 1.0, 2.0, 3.0 } ) v.push_back(f);
std::cout << sizeof(v) << "-" << v.capacity() << std::endl;
std::cout << sizeof(std::array<float,3>) << std::endl;
我们可以看到,在此平台上,std::vector<float>
本身占用24个字节,并且如果您使用固定大小的结构,它会动态地为4个浮点数分配内存-16个字节与3个浮点数-12个字节一样。因此,在您的情况下,差异将是:
1 std::vector - ( 24 + 16 ) * 100 000 000 = 4 000 000 000
2 std::array - 12 * 100 000 000 = 1 200 000 000
2 800000000或大约2Gb的内存。
但是std::vector
的末尾还有另一个价格-它必须在连续空间中分配所有数据。通常在大小达到当前大小时通过重新分配容量来完成。在这种情况下,这意味着创建此数据的内存需求可以轻松翻一番以上-假设如果容量达到5000万,并且vector需要重新分配,那么它将创建另一个内存块,比如说1亿,同时保留前一个内存块(因此您的内存必须容纳1.5亿个元素)并进行复制。而且没有内存碎片问题。
因此,建议的解决方案是将std::array<float,3>
用于内部数据(或具有三个元素的struct
)并将std::deque
作为外部容器,或者如果您必须使用std::vector
分配预先存储足够的元素。