Хороший класс массива C ++ для быстрого и эффективного использования больших массивов данных? - PullRequest
8 голосов
/ 18 марта 2010

Исходя из предыдущего вопроса, касающегося ограничений на использование кучи , я ищу хороший стандартный класс C ++ для работы с большими массивами данных таким образом, чтобы он занимал не только память, но и скорость. Я выделял массив с помощью одного malloc / HealAlloc, но после нескольких попыток с использованием различных вызовов продолжал нарушать фрагментацию кучи. Таким образом, я пришел к выводу, что помимо переноса на 64-битный, я использую механизм, который позволяет мне иметь большой массив, охватывающий несколько меньших фрагментов памяти. Я не хочу, чтобы выделение на элемент было очень неэффективным, поэтому планируется написать класс, который переопределяет оператор [], и выбрать соответствующий элемент на основе индекса. Есть ли уже приличный класс, чтобы сделать это, или мне лучше покататься?

Насколько я понимаю, и некоторые гуглят , 32-битный процесс Windows теоретически может обрабатывать до 2 ГБ. Теперь, если у меня установлено 2 ГБ, а различные другие процессы и службы занимают около 400 МБ, как вы думаете, сколько полезной памяти разумно ожидать, чтобы моя программа могла получить из кучи?

В настоящее время я использую различные варианты Visual C ++.

Редактировать Согласно сообщению Пойты, я попробовал std :: deque , используя следующий тест на VS2008;

#include <deque>
using namespace std;
struct V    
{
    double  data[11];
};

struct T
{
    long    data[8];    
};


void    dequeTest()
{
    deque<V> VQ;
    deque<T> TQ;

    V defV;
    T defT;

    VQ.resize(4000000,defV);
    TQ.resize(8000000,defT);
}

Общий объем памяти для вышеуказанных данных составляет 608 МБ, если я использую прямой malloc или HeapAlloc, и занимает <1 секунду. Первоначально размер файла deque составлял 950 МБ, а затем медленно начал снижаться. Спустя 15 минут dequeTest () завершил работу, использовав всего 6 МБ памяти для процесса, который, вероятно, был больше связан со временем выполнения. Я также пытался заполнить deque, используя различные варианты push, но производительность была настолько плохой, что мне пришлось вырваться раньше. Я мог бы обеспечить лучший распределитель, чем по умолчанию, чтобы получить гораздо лучший ответ, но на первый взгляд deque не является классом для этой работы. Обратите внимание, что это также может относиться к реализации deque в MS VS2008, так как в этом классе, похоже, много всего, что сильно зависит от реализации, когда дело касается производительности. </p>

Время написать свой собственный класс больших массивов, я считаю.

Второе редактирование: Выделение меньших сумм позволило сразу получить 1,875 ГБ с использованием следующего:

#define TenMB 1024*1024*10

void    SmallerAllocs()
{

    size_t Total = 0;
    LPVOID  p[200];
    for (int i = 0; i < 200; i++)
    {
        p[i] = malloc(TenMB);
        if (p[i])
            Total += TenMB; else
            break;
    }
    CString Msg;
    Msg.Format("Allocated %0.3lfGB",Total/(1024.0*1024.0*1024.0));
    AfxMessageBox(Msg,MB_OK);
}

Окончательное редактирование Я решил принять пост Пойты и различные комментарии после него не потому, что я буду использовать класс deque напрямую, а скорее для массива в качестве понятия колоды карт в комментарии, которые последовали. Это должно быть простым для реализации с O (1) произвольным доступом к элементам, основанным на фиксированном количестве элементов в блоке, что мне и нужно. Спасибо всем за отзывы!

Ответы [ 4 ]

11 голосов
/ 18 марта 2010

Вы пробовали использовать std::deque? В отличие от std::vector, который использует одно выделение огромной кучи, deque обычно выделяется небольшими порциями, но все же обеспечивает амортизацию индексации с постоянным временем через operator[].

5 голосов
/ 18 марта 2010

Насколько редок этот массив? Если в нем много пустого (неиспользуемого) пространства, вы можете выбрать другой подход. ответ на этот вопрос предлагает карту stl.

Если это не редкость (как упомянуто в комментариях), одна вещь, на которую вы можете обратить внимание, так как вы работаете в Windows, использует отображенный в память файл . Хотя ваша ОС может быть 32-разрядной, ваша файловая система - нет. Это, конечно, означает, что произойдет обмен, который может быть немного медленнее, чем если бы вы действительно могли поместить весь этот проклятый предмет в RAM.

Кроме того, вам действительно следует подумать о том, чтобы довести системную оперативную память до максимума (3 ГБ в 32-битной Windows, я полагаю), чтобы посмотреть, исправит ли это вашу проблему. Это должно стоить вам всего около 100 долларов, и вы тратите намного больше, чем в человеко-часах, просто беспокоясь об этом.

3 голосов
/ 18 марта 2010

С точки зрения вашей программы у вас всегда есть 2 ГБ свободного места при запуске, независимо от того, что еще происходит в системе. Я не верю, что Windows предоставляет способ обнаружить, если ваша память выгружается на диск или нет. Что касается ваших структур данных, похоже, вы описываете нечто похожее на реализацию deque в STL.

1 голос
/ 19 марта 2010

std :: deque делает именно то, что вы описываете, но обычно с гранулярностью размера страницы ОС (то есть, выделяемые куски обычно составляют 4 кБ).

Если вы недовольны производительностью deque по умолчанию, вы можете написать собственный распределитель, который захватывает большие куски, то есть получает по 1 МБ или более за раз.

Как уже говорили другие, виртуальное адресное пространство вашего процесса полностью не зависит от всех других процессов, поэтому вы можете адресовать 2 ГБ независимо от того, что еще происходит в вашей системе. Операционная система будет обменивать ваши страницы памяти на / с диска по мере необходимости, чтобы соответствовать ограничениям объема установленной памяти и всех процессов, конкурирующих за нее. Это произойдет при размере страницы 4 КБ, независимо от размера ваших чанков.

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