Предварительное выделение памяти с C++ в среде реального времени

У меня есть функция, которая получает входной буфер n байты и потребности вспомогательный буфер n байты для обработки данного входного буфера.

(Я знаю, что вектор выделяет память во времени выполнения, скажем, что я использую вектор, который использует статическую предварительно выделенную память. Предположите, что это не вектор STL.)

Обычный подход

void processData(vector<T> &vec) {
    vector<T> &aux = new vector<T>(vec.size()); //dynamically allocate memory
    // process data
}
//usage:
processData(v)

Так как я работаю в среде реального времени, я хочу предварительно выделить всю память, в которой я буду когда-либо нуждаться заранее.

Буфер выделяется только однажды при запуске. Я хочу это каждый раз, когда я выделяю вектор, я автоматически выделю вспомогательный буфер для моего processData функция.

Я могу сделать что-то похожее с шаблонной функцией

static void _processData(vector<T> &vec,vector<T> &aux) {
     // process data
}
template<size_t sz>
void processData(vector<T> &vec) {
    static aux_buffer[sz];
    vector aux(vec.size(),aux_buffer); // use aux_buffer for the vector
    _processData(vec,aux);
}
// usage:
processData<V_MAX_SIZE>(v);

Однако работание много с шаблонами не является большой забавой (теперь, давайте перекомпилируем все, так как я изменил комментарий!), и это вынуждает меня сделать некоторую бухгалтерию каждый раз, когда я использую эту функцию.

Есть ли какие-либо более хорошие проекты вокруг этой проблемы?

7
задан Elazar Leibovich 12 May 2010 в 13:12
поделиться

8 ответов

Я не понимаю, как вы можете получить именно то, что описываете. Что-то вроде этого могло бы стать для вас хорошим компромиссом.

void processData(vector<T>& vec)
{
    static vector<T> aux(vec.size());
    if (vec.size() > aux.size()) {
       aux.resize(vec.size());
    }
    ...
}
3
ответ дан 7 December 2019 в 05:18
поделиться

Я думаю, вы могли бы предварительно -allocate и mlock () достаточно большой пул памяти при запуске, а затем использовать обычные контейнеры STL с распределителями пула памяти ( Boost из FSBA или ваши собственные).

Я изучал это для нашего программного обеспечения реального времени, но тесты показали, что распределение памяти на нашем оборудовании достаточно быстрое для наших целей.

1
ответ дан 7 December 2019 в 05:18
поделиться

Возможно, вы можете переопределить операторы new и delete, но тогда вам придется управлять всей своей памятью самостоятельно. В начале вы можете выделить столько памяти, сколько хотите:

void* operator new (std::size_t size) throw (std::bad_alloc);
void* operator new[] (std::size_t size) throw (std::bad_alloc);
void operator delete (void* ptr) throw ();
void operator delete[] (void* ptr) throw ();
0
ответ дан 7 December 2019 в 05:18
поделиться

vector aux(vec.size(),aux_buffer); // используем aux_buffer для вектора

Это новое в STL? Или пользовательское расширение?

Типичным решением было бы использование пользовательского аллокатора. Однако это не обязательно "красивее" в коде.

Некоторые вводные слайды (предупреждение: powerpoint!)
Wikipedia
Google

1
ответ дан 7 December 2019 в 05:18
поделиться

допустим, я использую вектор. который использует статическую предварительно выделенную память

Тогда вы должны быть в состоянии получить размер (или максимальный размер) предварительно выделенной памяти во время компиляции. Если бы такой вектор имел свой размер как аргумент шаблона, то работа с функцией processData была бы проще.

template<class T, size_t sz>
class vector 
{ 
 enum { size = sz } //either max size
...
}

template<class Vector>
static void _processData(Vector &vec,Vector &aux)
{
     // process data
}
template<class Vector>
void processData(Vector &vec) {
    static aux_buffer[Vector::size];
    //no need to pass size into constructor, as Vector type knows it already
    Vector aux(aux_buffer); // use aux_buffer for the vector
    _processData(vec,aux);
}
// usage:
vector<int, 30> v1;
vector<float, 40> v2;
//no need to specify template parameter explicitly
//every call uses its own function instance and its own buffer of different size
processData(v1);
processData(v2);
1
ответ дан 7 December 2019 в 05:18
поделиться

Не могли бы вы создать небольшую структуру, содержащую ваш вектор и буфер такого же размера? Тогда ваш вектор будет нести свой буфер обработки вместе с собой, куда бы он ни направлялся. Если вы передадите его по ссылке или указателю, вам следует избежать накладных расходов на копирование. Псевдокод следует ниже:

struct Container
{
    vector<T> vec;
    vector<T> buf;

    Container(int size)
    {
        vec.reserve(size);
        buf.reserve(size);
    }
};

Любая функция, которая в настоящее время принимает ваш аргумент вектора, затем примет Контейнер .

0
ответ дан 7 December 2019 в 05:18
поделиться

Даже если вам это удастся, это может не достичь того, чего вы хотите. В зависимости от того, какую ОС вы используете и как она реализует виртуальную память, вы можете обнаружить, что вы получаете ленивое выделение , при котором только часть вашего распределения памяти фактически выделяется и отображается изначально, а дальнейшие страницы отображаются позже. в результате ошибок страниц. Если в вашей ОС есть mlock или аналогичный, вы можете обойти это.

1
ответ дан 7 December 2019 в 05:18
поделиться

Вам нужно беспокоиться не о векторе , а о распределителе памяти.

Вы могли бы идеально создать распределитель памяти, который предварительно выделяет ее память, а затем передает ее вектору при его построении, для этого и нужен параметр шаблона Alloc !

И чтобы убедиться, что память не выделена «виртуально», прикоснитесь к ней при выделении.

scoped_array<byte> buffer = new byte[SIZE];
memset(buffer.get(), 0, SIZE);

Теперь вам «просто» нужно реализовать собственный распределитель, который ссылается на этот пул памяти и передать его векторной реализации :)

1
ответ дан 7 December 2019 в 05:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: