C++ 嵌套向量在c++;
我想弄明白为什么我的应用程序占用了太多内存。这是:C++ 嵌套向量在c++;,c++,vector,nested,memory-consumption,C++,Vector,Nested,Memory Consumption,我想弄明白为什么我的应用程序占用了太多内存。这是: #include <iostream> #include <sstream> #include <string> #include <exception> #include <algorithm> #include <vector> #include <utility> #include <assert.h> #include <limits.
#include <iostream>
#include <sstream>
#include <string>
#include <exception>
#include <algorithm>
#include <vector>
#include <utility>
#include <assert.h>
#include <limits.h>
#include <time.h>
#include <tchar.h>
#include <random>
typedef unsigned __int32 uint;
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
vector<vector<uint>> arr(65536 * 16, vector<uint>());
mt19937 mt;
mt.seed(time(NULL));
uniform_int<uint> generator(0, arr.size() - 1);
for (uint i = 0; i < 10000000; i++)
{
for (uint j = 0; j < 16; j++)
{
uint bucketIndex = generator(mt);
arr[bucketIndex].push_back(i);
}
}
uint cap = 0;
for (uint i = 0; i < arr.size(); i++)
{
cap += sizeof(uint) * arr[i].capacity() + sizeof(arr[i]);
}
cap += sizeof(vector<uint>) * arr.capacity() + sizeof(vector<vector<uint>>);
cout << "Total bytes: " << cap << endl;
cout << "Press any key..." << endl;
cin.get();
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
typedef unsigned_uuint32 uint;
使用名称空间std;
int _tmain(int argc,_TCHAR*argv[]
{
向量arr(65536*16,向量();
mt19937mt;
mt.seed(时间(空));
均匀整数生成器(0,arr.size()-1);
对于(uint i=0;i<10000000;i++)
{
对于(uint j=0;j<16;j++)
{
uint Bucketinex=发电机(mt);
arr[bucketIndex]。推回(i);
}
}
uint cap=0;
对于(uint i=0;i cout这是因为每个向量包含三个指针(或它们的道德和大小等价物):begin、begin+size和begin+capacity。因此,当一个向量包含大量其他小向量时,每个内部向量会浪费三个字(在64位系统上是24字节)
由于每个内部向量的begin()指向一个单独的分配,因此您需要支付N倍的分配开销,这可能是另外几个字节
相反,您可能希望分配一个大区域,并将其视为二维数组。或者使用提供此类功能的众多库中的一个。如果内部向量大小不同,则这将不起作用,但通常它们都是一个大小,因此您确实需要一个二维“矩形”这是因为每个向量包含三个指针(或它们的道德和大小等价物):begin、begin+size和begin+capacity。因此,当一个向量包含大量其他小向量时,每个内部向量都会浪费三个字(在64位系统中为24字节)
由于每个内部向量的begin()指向一个单独的分配,因此您需要支付N倍的分配开销,这可能是另外几个字节
相反,您可能希望分配一个大区域,并将其视为二维数组。或者使用提供此类功能的众多库中的一个。如果内部向量大小不同,则这将不起作用,但通常它们都是一个大小,因此您确实需要一个二维“矩形”无论如何,不是向量向量。问题是您不知道数组的确切大小,否则您可以在实际填充向量之前使用reserve
设置向量容量,这样可以避免碎片。请尝试以下方法:
生成随机种子(time(NULL)
)并将其保存以供以后使用
创建一个数组大小为65536*16
的std::vector
,并将其中的所有整数/计数器初始化为零,让我们将此数组/向量命名为“vec_size”。我们将使用此数组存储/查找稍后创建/填充的数组大小
使用步骤#1中获取的种子初始化随机生成器
运行您的算法(嵌套for循环),但不要像arr[bucketinex]那样将项目存储到2D向量中。在代码中向后推(i);
只需增加vec\u大小[bucketinex]
计数器
现在我们知道了所有向量的大小
创建您的arr
向量
对于arr
中的所有子向量,使用vec\u size
向量中找到的相应大小调用向量的reserve
方法。这应该有效地预先分配向量,并且可以避免重新分配
使用步骤1中存储的相同种子初始化随机生成器
运行您的算法。现在将数据推送到向量中不会重新分配,因为它们的存储已经由您的reserve
调用分配
在这里,我们利用了一个事实,即您正在使用一个伪随机生成器,如果从同一个种子开始运行两次,它将给出非常相同的数字序列
注意:通常当内存效率是目标时,解决方案会做两次工作:首先计算最终数据的不同维度,然后非常有效地/紧凑地分配空间然后填充有效分配的存储。通常您必须牺牲一些东西。问题是您不知道阵列的确切大小,否则您可以在实际填充之前使用reserve
设置向量容量,这样可以避免碎片。尝试以下方法:
生成随机种子(time(NULL)
)并将其保存以供以后使用
创建一个数组大小为65536*16
的std::vector
,并将其中的所有整数/计数器初始化为零,让我们将此数组/向量命名为“vec_size”。我们将使用此数组存储/查找稍后创建/填充的数组大小
使用步骤#1中获取的种子初始化随机生成器
运行您的算法(嵌套for循环),但不要像arr[bucketinex]那样将项目存储到2D向量中。在代码中向后推(i);
只需增加vec\u大小[bucketinex]
计数器
现在我们知道了所有向量的大小
创建您的arr
向量
对于arr
中的所有子向量,使用vec\u size
向量中找到的相应大小调用向量的reserve
方法。这应该有效地预先分配向量,并且可以避免重新分配
使用步骤1中存储的相同种子初始化随机生成器
运行您的算法。现在将数据推送到向量中不会重新分配,因为它们的存储已经由您的reserve
调用分配
在这里,我们利用了一个事实,即您使用的是一个伪随机生成器,它给出了非常简单的sam
Total bytes: 690331672 // boost::container::vector::shrink_to_fit()
Total bytes: 1120033816 // std::vector
#include <iostream>
#include <exception>
#include <algorithm>
#include <vector>
#include <utility>
#include <cassert>
#include <cstdint>
#include <random>
#include <boost/optional.hpp>
#include <boost/container/vector.hpp>
using boost::container::vector;
using boost::optional;
int main()
{
vector<vector<uint32_t>> arr(1<<20);
std::mt19937 mt;
mt.seed(time(NULL));
std::uniform_int_distribution<uint32_t> generator(0, arr.size() - 1);
for (uint32_t i = 0; i < 10000000; i++)
{
for (uint32_t j = 0; j < 16; j++)
{
auto& bucket = arr[generator(mt)];
//if (!bucket) bucket = vector<uint32_t>();
bucket.push_back(i);
}
}
for(auto& i : arr)
i.shrink_to_fit();
uint32_t cap = 0;
for (uint32_t i = 0; i < arr.size(); i++)
{
cap += sizeof(uint32_t) * arr[i].capacity() + sizeof(arr[i]);
}
cap += sizeof(vector<uint32_t>) * arr.capacity() + sizeof(arr);
std::cout << "Total bytes: " << cap << std::endl;
std::cout << "Press any key..." << std::endl;
std::cin.get();
}
--------------------------------------------------------------------------------
Command: ./test
Massif arguments: (none)
ms_print arguments: massif.out.4193
--------------------------------------------------------------------------------
MB
822.7^ #
| @@#
| @@@@#:
| @@@@@@#:
| @@@@@@@@#:
| :@@@@@@@@@@@#:
| :::::@@:@@@@@@@@@@@#:
| @@:: ::@ :@@@@@@@@@@@#:
| @@@@@:: ::@ :@@@@@@@@@@@#:
| @@@ @@@:: ::@ :@@@@@@@@@@@#:
| :::@@@@ @@@:: ::@ :@@@@@@@@@@@#:
| @@@:::: @@@@ @@@:: ::@ :@@@@@@@@@@@#:
| @@@@@ :::: @@@@ @@@:: ::@ :@@@@@@@@@@@#:
| @@@@ @@@ :::: @@@@ @@@:: ::@ :@@@@@@@@@@@#:
| @@@:@@@@ @@@ :::: @@@@ @@@:: ::@ :@@@@@@@@@@@#:
| @@@@@@ :@@@@ @@@ :::: @@@@ @@@:: ::@ :@@@@@@@@@@@#:
| @@@@ @@@ :@@@@ @@@ :::: @@@@ @@@:: ::@ :@@@@@@@@@@@#:
| @@@@@@@@ @@@ :@@@@ @@@ :::: @@@@ @@@:: ::@ :@@@@@@@@@@@#:
| :::::::@@ @@@@@ @@@ :@@@@ @@@ :::: @@@@ @@@:: ::@ :@@@@@@@@@@@#:
| ::@:@:::: ::: @@ @@@@@ @@@ :@@@@ @@@ :::: @@@@ @@@:: ::@ :@@@@@@@@@@@#:
0 +----------------------------------------------------------------------->Gi
0 69.85