Свободная память от длинного вектора - PullRequest
1 голос
/ 30 июня 2011

Что я хотел сделать, так это освободить память, используемую vector (скажем, vector<vector<int>>), и я использовал трюк подкачки, то есть v.swap(vector<vector<int>>()).

Однако то, что я заметил, что трюк подкачки хорошо работает для коротких векторов, но НЕ для длинных, например, я попробовал один вектор длиной 10 000 000, который занял 1,4 ГБ в памяти, после свопа еще 1,0G не выпущен.

Ниже приведен код, который я использовал для тестирования.

Спасибо заранее за любую идею!

#include <iostream>
#include <vector>

using namespace std;

typedef unsigned long long     int64;

int main()
{
    {
        vector<vector<int64>> batch;
        {
            vector<int64> v;
            for (size_t i = 0; i < 12; ++i)
                v.push_back(8000000000);
            for (size_t i = 0; i < 10000000; ++i)
                batch.push_back(v);
        }
        cout << "pause 1" << endl;
        cin.ignore();
        {
            vector<vector<int64>> tmp;
            batch.swap(tmp);
            // I tried several things here.
            //tmp.swap(batch);
            //batch.clear();
            //batch.shrink_to_fit();
            //batch = tmp;
        }
        cout << "pause 2" << endl;
        cin.ignore();
    }
    cout << "pause 3" << endl;
    cin.ignore();
}

Ответы [ 2 ]

1 голос
/ 30 июня 2011

Вероятно, ваша реализация CRT решила, что было бы лучше не возвращать эту память операционной системе на тот случай, если вам понадобятся еще 12 непрерывных выделений по 80 МБ.

1 голос
/ 30 июня 2011

Джеймс, In silico и Макс все правы в своих замечаниях. Вы ожидаете, что память будет освобождена при вызове batch.swap(tmp), поскольку tmp пусто. Я только что запустил вашу программу на 64-битном Linux, скомпилированную с помощью gcc 4.6.0. При наблюдении за потреблением памяти сверху, уходит 2 ГБ -> 1,8 ГБ -> 1,8 ГБ. Однако при добавлении batch2 и заполнении его после pause 2, как при заполнении batch, потребление памяти не увеличивается. Запуск версии, в которой batch.swap(tmp) закомментирован, таким образом, фактически имея два огромных вектора, потребление памяти составляет 2 ГБ -> 3,2 ГБ -> 2,8 ГБ -> 2,8 ГБ.

Вот полный код с добавленной опцией командной строки:

#include <iostream>
#include <vector>
#include <string.h>

using namespace std;

typedef unsigned long long     int64;

int main(int argc, char** argv)
{
    bool no_swap = (argc > 1 && strcmp(argv[1], "-noswap") == 0); 
    {
        vector<vector<int64> > batch;
        vector<vector<int64> > batch2;
        {
            vector<int64> v;
            for (size_t i = 0; i < 12; ++i)
                v.push_back(8000000000);
            for (size_t i = 0; i < 10000000; ++i)
                batch.push_back(v);
        }
        cout << "pause 1" << endl;
        cin.ignore();
        {
            vector<vector<int64> > tmp;
            if (no_swap) {
                cout << "NOT calling batch.swap(tmp)" << endl;
            } else {                    
                cout << "calling batch.swap(tmp)" << endl;
                batch.swap(tmp);
            }
        }
        cout << "pause 2" << endl;
        cin.ignore();
        {
            vector<int64> v2;
            for (size_t i = 0; i < 12; ++i)
                v2.push_back(8000000000);
            for (size_t i = 0; i < 10000000; ++i)
                batch2.push_back(v2);
        }
        cout << "pause 3" << endl;
        cin.ignore();
    }
    cout << "pause 4" << endl;
    cin.ignore();
}

Некоторое объяснение этого поведения можно найти здесь и здесь . Из последнего:

При использовании распределитель может распределять и освобождать, используя стратегии, определенные реализацией. и эвристика. Из-за этого каждый вызов элемента allocate объекта allocator функция может не вызывать глобальный оператор new. Эта ситуация также дублируется для вызовов функции-члена освобождения.

Согласно этому документу, кэширование можно отключить, установив GLIBCXX_FORCE_NEW, но у меня это не работает ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...