динамическое распределение памяти
От: alex74  
Дата: 06.09.04 13:21
Оценка:
Проблема быстродействия. У меня есть задача, которая активно использует динамическую память (память выделяется по мере необходимости небольшими кусками и затем освобождается), по логике программы может возникнуть необходимость выделить несколько кусков по несколько килобайт. После выделения этих самых килобайт скорость выполнения сильно падает (разница даже не в разы а на порядки).

Мне необходимо, чтобы скорость выполнения задачи не зависила от дополнительного выделения памяти (во всяком случае отличалась не в разы). Может что посоветуете ?

18.10.04 21:38: Перенесено модератором из 'C/C++' — Павел Кузнецов
Re: динамическое распределение памяти
От: Bell Россия  
Дата: 06.09.04 13:36
Оценка:
Здравствуйте, alex74, Вы писали:

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


A>Мне необходимо, чтобы скорость выполнения задачи не зависила от дополнительного выделения памяти (во всяком случае отличалась не в разы). Может что посоветуете ?


Для начала посмотреть профайлером, действительно ли замедление связано с распределением памяти.
Любите книгу — источник знаний (с) М.Горький
Re: динамическое распределение памяти
От: maq Россия http://www.maqdev.com
Дата: 06.09.04 13:47
Оценка:
Значительное снижение может быть если несколько потоков все время
выделяют/удаляют память, или если она сильно фрагментируется в процессе работы.

Если дело действительно в памяти (можно проверить профайлером), то можно
попробовать написать свои аллокаторы, а м/б подойдет и boost::pool

Опиши конкретную задачу, каким образом у тебя выделяется память?
... << RSDN@Home 1.1.4 beta 2 >>
Re: динамическое распределение памяти
От: Kluev  
Дата: 06.09.04 13:50
Оценка:
Здравствуйте, alex74, Вы писали:

A>Мне необходимо, чтобы скорость выполнения задачи не зависила от дополнительного выделения памяти (во всяком случае отличалась не в разы). Может что посоветуете ?


Заюзай вот это счастье. Eсли сможешь разобратся все будет летать:

Компактный и быстрый распределитель:
http://rsdn.ru/File/16157/mem_mgr.h

Настройки и пример использования:
http://rsdn.ru/File/16157/memory.cpp

При запуске программы надо вызвать mem_init. В mem_init надо передать диапазон адрессов зарезервированных VirtuallAlloc(MEM_RESERVE)

при выходе mem_finalize

периодически надо вызывать mem_compact к примеру когда произошло большое перераспределения памяти.

статистика: mem_stat
Re[2]: динамическое распределение памяти
От: alex74  
Дата: 07.09.04 05:17
Оценка:
B>Для начала посмотреть профайлером, действительно ли замедление связано с распределением памяти.

Именно с распределением. Тормозит оператор new.
Re[2]: динамическое распределение памяти
От: alex74  
Дата: 07.09.04 05:34
Оценка:
maq>Значительное снижение может быть если несколько потоков все время
maq>выделяют/удаляют память, или если она сильно фрагментируется в процессе работы.

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

maq>Если дело действительно в памяти (можно проверить профайлером), то можно

maq>попробовать написать свои аллокаторы, а м/б подойдет и boost::pool

Что за boost::pool ?

maq>Опиши конкретную задачу, каким образом у тебя выделяется память?


Память выделяется оператором new. Если в терминах БД то задача следующая:

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

кроме того может передаваться информация о порядке записей, соответственно нужно выделять для нее память
Re[2]: динамическое распределение памяти
От: alex74  
Дата: 07.09.04 05:39
Оценка:
Здравствуйте, Kluev, Вы писали:

K>Заюзай вот это счастье. Eсли сможешь разобратся все будет летать:


K>Компактный и быстрый распределитель:

K>http://rsdn.ru/File/16157/mem_mgr.h

Чем он лучше ? Хотелось заранее определится насколько он мне подойдет.
Re[3]: динамическое распределение памяти
От: maq Россия http://www.maqdev.com
Дата: 07.09.04 07:04
Оценка:
A>Что за boost::pool ?
http://www.boost.org/libs/pool/doc/index.html
Это вроде пула блоков/объектов одинакового размера, оптимально использовать
когда идет частое выделение, а потом частое удаление их же.

maq>>Опиши конкретную задачу, каким образом у тебя выделяется память?


A>Память выделяется оператором new. Если в терминах БД то задача следующая:


A>получаю запись (это в цикле)

A>при необходимости преобразовываю поля к нужному формату (например строковому, соответственно выделяю для этого память)
A>делаю необходимые вычисления
A>передаю полученный результат обратно

Т.е. память в цикле выделяется/удаляется или остается выделенной?
Еще могу посоветовать выделять память не для отдельных записей, а блоками.
Можно для этой цели воспользоваться std::vector

A>кроме того может передаваться информация о порядке записей, соответственно нужно выделять для нее память
... << RSDN@Home 1.1.4 beta 2 >>
Re[3]: динамическое распределение памяти
От: Kluev  
Дата: 07.09.04 07:09
Оценка:
Здравствуйте, alex74, Вы писали:

A>Здравствуйте, Kluev, Вы писали:


K>>Заюзай вот это счастье. Eсли сможешь разобратся все будет летать:


K>>Компактный и быстрый распределитель:

K>>http://rsdn.ru/File/16157/mem_mgr.h

A>Чем он лучше ? Хотелось заранее определится насколько он мне подойдет.


Этот менеджер написан специально чтобы решить проблему фрагментации памяти. У нас программа может работать считать непрерывно несколько дней подряд создавая и уничтожая большое число обьектов. В таких условиях стандартная куча начинает серьезно тормозить.
Re: динамическое распределение памяти
От: white_znake  
Дата: 07.09.04 10:05
Оценка:
Здравствуйте, alex74, Вы писали:

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


A>Мне необходимо, чтобы скорость выполнения задачи не зависила от дополнительного выделения памяти (во всяком случае отличалась не в разы). Может что посоветуете ?


Использовать оператор new для выделения памяти в критических по времени приложениях — это плохо (работай с виртуальной памятью — т.к. Windows сама оптимизирует этот процесс).

Почитай про VirtualAlloc() и другие WIN API ф-ции позволяющие работать с virtual страницами памяти.
(так же просвятись по тому как Windows NT работает с памятью — Heap, виртуальный набор страниц и тд.)
Re[2]: динамическое распределение памяти
От: Sir Wiz Россия  
Дата: 07.09.04 10:12
Оценка:
Здравствуйте, white_znake, Вы писали:

A>>Мне необходимо, чтобы скорость выполнения задачи не зависила от дополнительного выделения памяти (во всяком случае отличалась не в разы). Может что посоветуете ?


_>Использовать оператор new для выделения памяти в критических по времени приложениях — это плохо (работай с виртуальной памятью — т.к. Windows сама оптимизирует этот процесс).


Где про это можно почитать?
... << RSDN@Home 1.1.4 @@subversion >>
Re[4]: динамическое распределение памяти
От: alex74  
Дата: 07.09.04 10:19
Оценка:
maq>Т.е. память в цикле выделяется/удаляется или остается выделенной?
maq>Еще могу посоветовать выделять память не для отдельных записей, а блоками.
maq>Можно для этой цели воспользоваться std::vector

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

Для записей дополнительно ничего не выделяется, память выделяется только при обработке полей (выделение блоками тут не поможет).

Первоначально у меня вся память выделялась только по мере необходимости, тогда обработка порядка 600 тыс записей занимала более получаса. Потом я это все "оптимизировал" и выделеная память не освобождалась до конца цикла, а повторно использовалась. Выполнение сократилось до полутора минут. Но по всему коду были раставлены проверки типа выделина память или нет (проверялся указатель). Потом я решил еще больше "оптимизировать" и убрать проверки, перенеся выделение памяти для индекса в процедуру инициализации (момент определения параметров передаваемых данных). Скорость ваполнения составила примерно те же пол часа .

Дело в том что у меня в циксе может обрабатыватся несколько записей из разных источников и при этом производительность не должна так сильно падать.
Re[5]: динамическое распределение памяти
От: maq Россия http://www.maqdev.com
Дата: 07.09.04 10:29
Оценка:
A>Первоначально у меня вся память выделялась только по мере необходимости, тогда обработка порядка 600 тыс записей занимала более получаса. Потом я это все "оптимизировал" и выделеная память не освобождалась до конца цикла, а повторно использовалась. Выполнение сократилось до полутора минут. Но по всему коду были раставлены проверки типа выделина память или нет (проверялся указатель). Потом я решил еще больше "оптимизировать" и убрать проверки, перенеся выделение памяти для индекса в процедуру инициализации (момент определения параметров передаваемых данных). Скорость ваполнения составила примерно те же пол часа .

A>Дело в том что у меня в циксе может обрабатыватся несколько записей из разных источников и при этом производительность не должна так сильно падать.


Попробуй использовать вот этот код: http://gzip.rsdn.ru/Forum/Message.aspx?mid=556586&amp;only=1
Автор: maq
Дата: 02.03.04

Это простейший менеджер памяти вроде boost::pool

Я так понял для одного источника один размер блока — соответственно создаешь столько
менеджеров сколько у тебя источников и вызываешь allocate у соответствующего типу
источника менеджера. Храни их до конца обработки цикла.
... << RSDN@Home 1.1.4 beta 2 >>
Re[6]: динамическое распределение памяти
От: maq Россия http://www.maqdev.com
Дата: 07.09.04 10:33
Оценка:
Что то вроде:
    CBSimpleFixedAllocator* pManagers[nSrcCount];
    for (..) pManagers[i] = new CBSimpleFixedAllocator(size_of_block[i], 100); // выделять по 100 записей при расширении
    
    //... обработка
    for (int nSrc = 0; nSrc < nSrcCount; ++nSrc)
    {
      CBSimpleFixedAllocator& ca = *pManagers[nSrc];
        void* ptr = ca.allocate();
        void* ptr2 = ca.allocate();
        // ...
        ca.free(ptr);
        ca.free(ptr2);
    }

    delete[] pManagers;
... << RSDN@Home 1.1.4 beta 2 >>
Re[4]: динамическое распределение памяти
От: alex74  
Дата: 07.09.04 10:48
Оценка:
K>Этот менеджер написан специально чтобы решить проблему фрагментации памяти. У нас программа может работать считать непрерывно несколько дней подряд создавая и уничтожая большое число обьектов. В таких условиях стандартная куча начинает серьезно тормозить.

Как будет влиять выделеная память на дальнейшее выделение (я имею ввиду скорость работы) ? Кроме того, что решается проблема дефрагментации есть еще преимущества ?
Re[3]: динамическое распределение памяти
От: white_znake  
Дата: 08.09.04 05:50
Оценка:
Здравствуйте, Sir Wiz, Вы писали:

SW>Здравствуйте, white_znake, Вы писали:


A>>>Мне необходимо, чтобы скорость выполнения задачи не зависила от дополнительного выделения памяти (во всяком случае отличалась не в разы). Может что посоветуете ?


_>>Использовать оператор new для выделения памяти в критических по времени приложениях — это плохо (работай с виртуальной памятью — т.к. Windows сама оптимизирует этот процесс).


SW>Где про это можно почитать?


В MSDN прочитай про функции VirtualAlloc(), VirtualAllocEx(), VirtualFree(), VirtualProtectEx() и тд.
Эти ф-ции следует использовать в том, случае когда работаешь с большим объемом памяти и пишешь приложение критичное по времени.

(правда я читал о том, что производительность этих ф-ций зависит от размера стр. памяти — но сам не проверял).
Re: динамическое распределение памяти
От: prVovik Россия  
Дата: 18.10.04 20:51
Оценка:
Здравствуйте, alex74, Вы писали:

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


A>Мне необходимо, чтобы скорость выполнения задачи не зависила от дополнительного выделения памяти (во всяком случае отличалась не в разы). Может что посоветуете ?


Попробой проанализировать характер захватывания и освобождения памяти. Очень высокая производительность получится, если, например, удастся применить менеджер памяти, основанный на циклической очереди. Это когда выделяется память с головы очереди, а освобождается с хвоста. Но для эффективной работы такого менеджера надо, чтобы память освобождалась примерно в том же порядке, в котором она захватывалать (либо надо иметь запас свободной памяти). Причем точного соответствия отнюдь не требуется. Такой менеджер можно применить довольно часто. Это того стоит, ибо получим ОЧЕНЬ высокую производительность.
... << RSDN@Home 1.1.4 @@subversion >>
лэт ми спик фром май харт
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.