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;icout这是因为每个向量包含三个指针(或它们的道德和大小等价物):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