crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

6 страниц V  « < 2 3 4 5 6 >  
Ответить в данную темуНачать новую тему
> Создание быстродействующего распределителя памяти, для std::vector или замена глобальных операций выделения памяти
AD
  опции профиля:
сообщение 30.6.2009, 14:59
Сообщение #31


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Влад, исходя из твоих слов, следует заменить глобальные new и delete!

P.S. Изначально, именно для ускорения работы программы и затеялась вся канитель!

Сообщение отредактировал AD - 30.6.2009, 15:01
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Tonal
  опции профиля:
сообщение 1.7.2009, 8:47
Сообщение #32


Активный участник
***

Группа: Участник
Сообщений: 452
Регистрация: 6.12.2007
Из: Новосибирск
Пользователь №: 34

Спасибо сказали: 69 раз(а)




Репутация:   17  


Цитата(AD @ 30.6.2009, 18:09) *
Странно, как-то не очень помогло. Или я что-то забыл?
...
В чем еще могут быть проблемы? Что-то еще следует дописать?

Ты выделяешь столько памяти, сколько просит клиент (std::vector). Ровно это же и делает стандартный аллокатор. Т.е. ты ничего не выигрываешь.
Для того, чтобы получить эффект, нужно изменить стратегии выделения - например выделять память сразу большими блоками, а потом раздавать на них место. :)
Попробуй таки зацепить аллокатор из буста - хоть посмотришь к чему надо стремиться. :)

Да, можно ещё такой финт провернуть:
При разборе блока параметры загоняешь в список - std::list с быстрым аллокатором.
Когда блок разобран, создаёшь массив std::vector или обычный массив с уже известным размером и копируешь туда данные.
Если все блоки не очень большого размера, то можно выделить для аллокатора списка сразу память под самый большой блок и переразмещений в нём не будет.
И массивы будут размещаться всего один раз.
Стало быть получим количество выделений памяти в идеале: кол-во блоков + 1. :)
А переразмещений не будет вовсе - что сильно снизает нагрузку на всю подсистему памяти. :)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 1.7.2009, 9:05
Сообщение #33


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Цитата(Tonal @ 1.7.2009, 9:47) *
Ты выделяешь столько памяти, сколько просит клиент (std::vector). Ровно это же и делает стандартный аллокатор. Т.е. ты ничего не выигрываешь.
Для того, чтобы получить эффект, нужно изменить стратегии выделения - например выделять память сразу большими блоками, а потом раздавать на них место. :)
Попробуй таки зацепить аллокатор из буста - хоть посмотришь к чему надо стремиться. :)

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

Цитата(Tonal @ 1.7.2009, 9:47) *
Да, можно ещё такой финт провернуть:
При разборе блока параметры загоняешь в список - std::list с быстрым аллокатором.
Когда блок разобран, создаёшь массив std::vector или обычный массив с уже известным размером и копируешь туда данные.
Если все блоки не очень большого размера, то можно выделить для аллокатора списка сразу память под самый большой блок и переразмещений в нём не будет.
И массивы будут размещаться всего один раз.
Стало быть получим количество выделений памяти в идеале: кол-во блоков + 1. :)
А переразмещений не будет вовсе - что сильно снизает нагрузку на всю подсистему памяти. :)

Спасибо большое. Мне бы хоть пример небольшой, тогда смогу сделать, а так сложно представить, как это реализовать!
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 1.7.2009, 9:59
Сообщение #34


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


В boost в файле allocator.hpp нашел следующий код:
typedef std::alloc alloc_type;



template <typename T>
class allocator
{
   pointer allocate(size_type n, const void* = 0)
   {
      #ifdef BOOST_HAVE_SGI_ALLOCATOR
      return n != 0 ?
         reinterpret_cast<pointer>(alloc_type::allocate(n * sizeof(value_type)))
         : 0;
      #else
      return n != 0 ?
         reinterpret_cast<pointer>(::operator new(n * sizeof(value_type)))
         : 0;
      #endif
   }

   void deallocate(pointer p, size_type n)
   {
      #ifdef BOOST_HAVE_SGI_ALLOCATOR
      assert( (p == 0) == (n == 0) );
      if (p != 0)
         alloc_type::deallocate((void*)p, n);
      #else
      assert( (p == 0) == (n == 0) );
      if (p != 0)
         ::operator delete((void*)p);
      #endif
   }
}

Беда в том, что я не нашел в std данного типа: std::alloc! И что это за alloc_type::allocate(), alloc_type::deallocate() не смог узнать и найти код реализации этих функций. Буду благодарен за помощь в реализации корректной стратегии выделения памяти.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 1.7.2009, 10:37
Сообщение #35


Профессионал
*****

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

Спасибо сказали: 264 раз(а)




Репутация:   44  


Почитай вот эту тему. В конце есть готовый алокатор, с примером.
Стратегия там такая, выделяется один кусок памяти под 1K объектов (chunk), когда память в нем заканчивается, выделяется следующий chunk и т.д.

Блин, ссылку забыл приложить. :)
http://forum.sources.ru/index.php?showtopic=249933

Сообщение отредактировал BRE - 1.7.2009, 10:38
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Tonal
  опции профиля:
сообщение 1.7.2009, 10:44
Сообщение #36


Активный участник
***

Группа: Участник
Сообщений: 452
Регистрация: 6.12.2007
Из: Новосибирск
Пользователь №: 34

Спасибо сказали: 69 раз(а)




Репутация:   17  


Цитата(AD @ 1.7.2009, 13:05) *
Цитата(Tonal @ 1.7.2009, 9:47) *
Попробуй таки зацепить аллокатор из буста - хоть посмотришь к чему надо стремиться. :)

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

Вот и смотри как там работают с памятью.
А подключить действительно просто - бостовский пул не требует подключения библиотек - только хедеров и пути к ним. :)

Кстати, в том коде, который ты приводил в сообщении 13
Попробуй сделать для LOGRECORD конструктор с размером параметров:
explicit LOGRECORD::LOGRECORD(size_t size) : params(size) ...

Конструирование вектора сразу нужного размера выгоднее, чем конструирование пустого, с последующим его увеличением.

П.С.
Цитата(AD @ 1.7.2009, 13:05) *
Цитата(Tonal @ 1.7.2009, 9:47) *
Да, можно ещё такой финт провернуть...

Спасибо большое. Мне бы хоть пример небольшой, тогда смогу сделать, а так сложно представить, как это реализовать!

Рассмотрел ещё раз твой код и подумал, что я похоже фигню написал.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 1.7.2009, 10:50
Сообщение #37


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Цитата(Tonal @ 1.7.2009, 11:44) *
Вот и смотри как там работают с памятью.
А подключить действительно просто - бостовский пул не требует подключения библиотек - только хедеров и пути к ним. :)

Подключение буста - не решение. Довольно много причин, по которым я не хочу его подключать! Вот я и задаю вопросы, рассмотрев код буста, вообще-то!

Цитата(Tonal @ 1.7.2009, 11:44) *
Кстати, в том коде, который ты приводил в сообщении 13
Попробуй сделать для LOGRECORD конструктор с размером параметров:
explicit LOGRECORD::LOGRECORD(size_t size) : params(size) ...

Конструирование вектора сразу нужного размера выгоднее, чем конструирование пустого, с последующим его увеличением.

Это я уже сделал! :)


Цитата(Tonal @ 1.7.2009, 11:44) *
П.С. Рассмотрел ещё раз твой код и подумал, что я похоже фигню написал.

В чем именно? :blink:
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 1.7.2009, 14:55
Сообщение #38


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Вот блин. Сделал следующий распределитель:
allocator
#ifndef SPECIFIC_ALLOCATOR_INL
#define SPECIFIC_ALLOCATOR_INL

#include <memory>
#include <cassert>

#define CHUNK_SIZE 4096

/// Собственный распределитель памяти
template <typename T> class pool_alloc: public std::allocator<T>
{
private:
    static const difference_type chunk_size = CHUNK_SIZE;
    struct Link { Link* next; };
    struct Chunk
    {
        Chunk* next;
        char memory[chunk_size];
    };
    Link* head;
    Chunk* chunks;
    static const size_type elem_size = (sizeof(T) < sizeof(Link*)) ? sizeof(Link*) : sizeof(T);
    static const size_type num_elem = chunk_size / elem_size;

private:
    void grow(bool special = false)            ///< увеличиваем пулл
    {
        Chunk* n = new Chunk;
        n -> next = chunks;
        chunks = n;

        char* start = n -> memory;
        char* last = &n -> memory[(num_elem - 1) * elem_size];
        for(char* p=start; p<last; p+=elem_size)
            reinterpret_cast<Link*> (p) -> next = reinterpret_cast<Link*> (p + elem_size);
        reinterpret_cast<Link*> (last) -> next = (special) ? head : 0;
        head = reinterpret_cast<Link*> (start);
    }

public:
    pool_alloc() throw(): head(0), chunks(0) {}
    pointer allocate(size_type n)            ///< выделяем память под n элементов типа T
    {
        if(n * elem_size > chunk_size) throw "Unsuccessfully memory allotment";
        if(!head) grow();
        else if(n != 1) grow(true);
        Link* p = head;
        while(n--) head = head -> next;
        return reinterpret_cast<pointer> (p);
    }
    void deallocate(pointer p, size_type n) ///< возвращаем память в пулл
    {
        while(n--)
        {
            reinterpret_cast<Link*> (p) -> next = head;
            head = reinterpret_cast<Link*> (p);
        }
    }
    ~pool_alloc() throw()
    {
        Chunk* n = chunks;
        while(n)
        {
            Chunk* p = n;
            n = n -> next;
            delete p;
        }
    }
    template <typename Other> struct rebind
    { typedef pool_alloc<Other> other; };
    template <typename Other> pool_alloc(const pool_alloc<Other>& p) throw() { head = 0, chunks = 0; }
    template <typename Other> pool_alloc<T>& operator=(const pool_alloc<Other>&)
    { head = 0; chunks = 0; return *this; }
    pool_alloc(const pool_alloc<T>& p) throw() { head = 0, chunks = 0; }
};

#endif // SPECIFIC_ALLOCATOR_INL


Загрузка 5 логов, объемом записей в 7038 грузилось 8-9 секунд. Нехорошо! Что-то опять-таки не так реализовал? Или взял не тот распределитель? в чем теперь проблемы?

Сообщение отредактировал AD - 1.7.2009, 15:16
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 1.7.2009, 15:24
Сообщение #39


Профессионал
*****

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

Спасибо сказали: 264 раз(а)




Репутация:   44  


А ты в профилировщике результаты смотрел, точно именно на выделении памяти такие тормоза?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 1.7.2009, 15:57
Сообщение #40


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Цитата(BRE @ 1.7.2009, 16:24) *
А ты в профилировщике результаты смотрел, точно именно на выделении памяти такие тормоза?

Придется его еще раз подключать. Видимо, все-таки не только в выделении. Сейчас немного другую картинку наблюдаю!

Надо будет еще раз профайлером пройтись. Что-то не то. Как-то по-другому теперь программа себя ведет! В смысле тормозит теперь в другом месте. Операция выделения теперь шустренькая.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

6 страниц V  « < 2 3 4 5 6 >
Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 29.3.2024, 16:12