crossplatform.ru

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

> Создание быстродействующего распределителя памяти, для std::vector или замена глобальных операций выделения памяти
AD
  опции профиля:
сообщение 29.6.2009, 10:38
Сообщение #1


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

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

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




Репутация:   17  


Раньше был обычный массив (динамический), который содержал значения определенных параметров, прочитанных из лог-файла (широта, долгота, скорость и пр.). Сейчас сделал в виде вектора. Вместо оператора new теперь использую resize. Но так как эти операции чересчур затратные (а цикл может содержать и 100000 итераций (где каждый раз происходит выделение)), то стало необходимо сделать алгоритм немного по-другому.
Выделять память блоками. Т.е. вместо след. операций:
code1
t.params = new PARAMVALUE[rec_descr.size()];
t.words = new uint[rec_descr.size()];
memset(t.params, 0, sizeof(PARAMVALUE) * rec_descr.size());
memset(t.words, 0, sizeof(uint) * rec_descr.size());

Делать следующее:
code2
/// 0 <= num_block <= 1000
char *buff, *buff1;
if(num_block > 1000)
{
buff = new char[rec_descr.size() * BLOCKSIZE];
buff1 = new char[rec_descr.size() * BLOCKSIZE];
flag = false;
num_block = 0;
}
++num_block;
t.params = buff + rec_descr.size() * num_block;
t.words = buff1 + rec_descr.size() * num_block;


При замене на QVector code1 перешел в следующий:
code3
t.params.resize(rec_descr.size());
t.words.resize(rec_descr.size());


Как переписать code2 для использования в векторе QVector? Заранее благодарен за помощь....

Сообщение отредактировал AD - 30.6.2009, 15:08
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
 
Начать новую тему
Ответов
Влад
  опции профиля:
сообщение 13.7.2009, 11:59
Сообщение #2


Участник
**

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

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




Репутация:   8  


Цитата
bcp
Usage:
bcp --list [options] module-list
bcp --list-short [options] module-list
bcp --report [options] module-list html-file
bcp [options] module-list output-path

Options:
--boost=path sets the location of the boost tree to path
--scan treat the module list as a list of (possibly non-boost)
files to scan for boost dependencies
--cvs only copy files under cvs version control
--unix-lines make sure that all copied files use Unix style line endings

module-list: a list of boost files or library names to copy
html-file: the name of a html file to which the report will be written
output-path: the path to which files will be copied
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 13.7.2009, 17:30
Сообщение #3


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

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

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




Репутация:   17  


Итак, сделал вырезку некоторых файлов из boost и добавил в свой проект.
Распределителем памяти сделал fast_pool_allocator. Скорость значительно улучшилась. Есть еще тормоза при загрузке 50 и более файлов, но это уже несмертельно и не так долго.
Вот версия, с которой буду "жить" некоторое время. Потом оптимизирую отрисовку - должно улучшить результаты! :)
Reading Logs
#include "boost/pool/pool_alloc.hpp"

/// Структура для хранения всех значений параметров в логе
struct LOGRECORD
{
public:
    QString name_file;                        ///< имя лог-файла для данной записи
    QMap<bool, QString> phase;                ///< название этапа полета
    std::vector<PARAMVALUE, boost::fast_pool_allocator<PARAMVALUE> > params;    ///< вектор параметров

public:
    LOGRECORD(const boost::fast_pool_allocator<PARAMVALUE>& only_once_allocator =
                boost::fast_pool_allocator<PARAMVALUE>(), size_t size = 0): name_file(""),
                params(size, PARAMVALUE(), only_once_allocator) {}
    LOGRECORD(const LOGRECORD& l): name_file(l.name_file), phase(l.phase),
                                   params(l.params.size(), PARAMVALUE(), l.params.get_allocator())
    { std::copy(l.params.begin(), l.params.end(), params.begin()); }
    LOGRECORD& operator=(const LOGRECORD& l);
    PARAMVALUE GetLat(QVector<ParamDescr*>* descr) const;
    PARAMVALUE GetLon(QVector<ParamDescr*>* descr) const;
    PARAMVALUE GetDateTime(QVector<ParamDescr*>* descr) const;
    PARAMVALUE GetParamValue(QVector<ParamDescr*>* descr, const std::string& name, const Suint& addr) const;
    PARAMVALUE GetParamValue(QVector<ParamDescr*>* descr, const std::string& name) const;
    PARAMVALUE GetParamValue(QVector<ParamDescr*>* descr, const Suint& addr, std::string& instance);
};

class LogReader: public QObject
    {
        Q_OBJECT

    private:
        QVector<uint> m_vBlock;                    ///< вектор прочитанных слов
        QFile* _file;                            ///< указатель на файл загрузки (лог-файл)
        char* files_buff;                        ///< буфер, в который будут считываться все данные из файлов
        qint64 bytes_read;                        ///< реальное количество прочитанных данных
        int records_count;                        ///< количество записей в лог-файле
        boost::fast_pool_allocator<PARAMVALUE> alloc;///< распределитель памяти

    public:
        QVector<ParamDescr*> rec_descr;            ///< вектор параметров из файла описания (файла загрузки)
        TLV* mainWindow;                        ///< указатель на объект главного окна

    private:
        bool parseBlock(LOGRECORD& t);
        void ChangeDateTime(LOGRECORD& t);
        void FillCompParams(LOGRECORD& t);
        void selectPhase(ParamDescr* descrParam, int index, LOGRECORD& t);
        void selectPhase(LOGRECORD& t);
        void fillHlpLog(const LOGRECORD& t, uint index);
        void compareTimeMark(QVector<LOGRECORD>& log, time_t& before_read);
        void lastCompare(QVector<LOGRECORD>& log, const time_t& before_read);

    public:
        LogReader(std::string FileName, TLV* main): mainWindow(main), records_count(0), _file(new QFile()),
                                        files_buff(0), bytes_read(0) { _file -> setName(FileName.c_str()); }
        LogReader(const char* FileName, TLV* main): mainWindow(main), records_count(0), _file(new QFile()),
                                        files_buff(0), bytes_read(0) { _file -> setName(FileName); }
        ~LogReader() { shutdown(); }
    ///// ................................................... ////////
        void setBytesRead(qint64 n) { bytes_read = n; }
        qint64 bytesRead() const { return bytes_read; }
        bool tRead();
        bool parseBuffer();
    };

/// Выбор этапа полета
    void LogReader::selectPhase(ParamDescr* descrParam, int index, LOGRECORD& t)
    {
        if(descrParam -> Name() != "phaseoperation") return;
        int n = t.params[index].value;
        if(n < phaseList.size() && !phaseList.isEmpty())
        {
            t.phase[true] = phaseList[n][(mainWindow) ? mainWindow -> Language() : true];
            t.phase[false] = phaseList[n][(mainWindow) ? !mainWindow -> Language() : false];
        }
    }

    /// Выбор этапа полета - если нет совпадений имен
    void LogReader::selectPhase(LOGRECORD& t)
    {
        if(t.phase.isEmpty() && !phaseList.isEmpty())
        {
            bool f = (mainWindow) ? mainWindow -> Language() : true;
            t.phase[f] = phaseList[0][f];
            t.phase[!f] = phaseList[0][!f];
        }
    }

    /// Разбор одной записи
    bool LogReader::parseBlock(LOGRECORD& t)
    {
        struct VARS {
            bool flag;
            uint var;
            VARS(): flag(false), var(0) {}
        } vars[ADDR_LIMIT];

        t.name_file = strippedName(_file -> fileName());

        int i = 0, block_size = m_vBlock.size();
        for(int j=0; j<block_size; ++j)
        {
            uint index = m_vBlock[j] % ADDR_LIMIT;
            vars[index].flag = true;
            vars[index].var = m_vBlock[j];
        }

        paramI end(rec_descr.end());
        for(paramI iter=rec_descr.begin(); iter!=end; ++iter, ++i)
        {
            uint addr_index = (*iter) -> Address();
            if(addr_index < ADDR_LIMIT)
                if(vars[addr_index].flag)
                    t.params[i] = (*iter) -> GetValue(vars[addr_index].var);
            selectPhase((*iter), i, t);
        }
        selectPhase(t);

        return true;
    }

    /// Заполнение вычислимых параметров
    void LogReader::FillCompParams(LOGRECORD& t)
    {
        if(mainWindow -> iniReader() -> indexComputeParam() < 0) return;
        for(int i=mainWindow -> iniReader() -> indexComputeParam(); i<rec_descr.size(); ++i)
        {
            CompParamDescr* p = dynamic_cast<CompParamDescr*> (rec_descr[i]);
            ElemFormul formul(p -> formulList());
            COMPUTE* element = formul.calculateFormul(&t, &rec_descr);
            if(element != 0)
            {
                t.params[i].value = element -> GetValue();
                t.params[i].status = PS_OK;
                t.params[i].evn = 0;
            }
        }
    }

    /// Заполнение вектора-получателя частями прочитанных данных
    void LogReader::fillVec(QVector<LOGRECORD>& sender) { mainWindow -> addData(sender); }

    /// Запись значений времени и даты
    void LogReader::ChangeDateTime(LOGRECORD& t)
    {
        int time_index = mainWindow -> iniReader() -> indexTimeParam(),
            date_index = mainWindow -> iniReader() -> indexDateParam();
        TimeParamDescr* dt_time = dynamic_cast<TimeParamDescr*> (rec_descr[time_index]);
        DateParamDescr* dt_date = dynamic_cast<DateParamDescr*> (rec_descr[date_index]);
        tm c_time = dt_time -> TCTime(), c_date = dt_date -> TCDate();
        TimeDateParamDescr tmd(c_time, c_date);
        t.params[time_index] = tmd.GetValue(0);
        t.params[date_index] = tmd.GetValue(0);
    }

    /// Заполнение hlp_log
    void LogReader::fillHlpLog(const LOGRECORD& t, uint index)
    {
        if(index == 0)
            mainWindow -> hlp_log.append(VEC_PARTNER(index, t.name_file, t.phase));
        else if(index > 0 && mainWindow -> hlp_log.size() != 0)
        {
            if(mainWindow -> hlp_log.last().name != t.name_file ||
                mainWindow -> hlp_log.last().phase != t.phase)
                mainWindow -> hlp_log.append(VEC_PARTNER(index, t.name_file, t.phase));

        }
    }

    /// Сравнение временных меток
    void LogReader::compareTimeMark(QVector<LOGRECORD>& log, time_t& before_read)
    {
        time_t contin_read;
        time(&contin_read);
        time_t delta = contin_read - before_read;
        if(delta > 2)
        {
            before_read = contin_read;
            fillVec(log);
            log.clear();
        }
    }

    /// Сравнение временных меток, если чтение файла завершилось раньше, чем через 3 секунды
    void LogReader::lastCompare(QVector<LOGRECORD>& log, const time_t& before_read)
    {
        if(!log.size()) return;
        fillVec(log);
        log.clear();
    }

/// Чтение файла загрузки
    bool LogReader::tRead()
    {
        if(!open()) return false;        ///< открываем файл с логом

        if(_file -> size() > FBUFF_SIZE - bytes_read)
            return false;
        qint64 really_read = _file -> read(&files_buff[bytes_read], _file -> size());
        assert(really_read == _file -> size());
        bytes_read += really_read;

        shutdown();                        ///< закрываем файл с логом

        return true;
    }

    /// Разбор прочитанного буфера
    bool LogReader::parseBuffer()
    {
        uint var = 1e+6, index = 0;
        int i = 0;
        bool bBlock = false, buff_ready = false;
        LOGRECORD unit(alloc, rec_descr.size());
        QVector<LOGRECORD> log(0, unit);
        time_t before_read;        time(&before_read);

        for(uint* p=reinterpret_cast<uint*>(files_buff); i<(bytes_read / sizeof(var)); ++p, ++i)
        {
            var = *p;
            Suint adr = var % 256;
            /// Определение начала/конца одной записи и записывание ее в вектор
            switch(adr)
            {
            case 0000:
                m_vBlock.clear();
                bBlock = true;
            break;
            case 0001:
                if(bBlock)
                {
                    log.append(unit);
                    parseBlock(log.last());
                    ChangeDateTime(log.last());
                    if(mainWindow -> iniReader() -> indexComputeParam() > 0)
                        FillCompParams(log.last());
                    fillHlpLog(log.last(), index);
                    buff_ready = true;
                    compareTimeMark(log, before_read);
                    ++index;
                }
                bBlock = false;
            break;
            default:
                if(bBlock) m_vBlock.append((uint)var);
            }
        }
        lastCompare(log, before_read);

        return buff_ready;
    }

Если есть замечания, пишите, постараюсь учесть. Может быть, кому-то еще и пригодится то, что в этой теме было описано. :)

Да.... Огромное спасибо Tonal(у), Владу, BRE за помощь! Без вас я бы не смог так улучшить код! :)

Сообщение отредактировал AD - 14.7.2009, 14:34
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Сообщений в этой теме
- AD   Создание быстродействующего распределителя памяти   29.6.2009, 10:38
- - Tonal   Интересно, в code2 при num_block <= 1000 t.para...   29.6.2009, 10:53
|- - AD   Цитата(Tonal)Интересно, в code2 при num_block ...   29.6.2009, 11:10
- - Litkevich Yuriy   Цитата(AD @ 29.6.2009, 14:38) Выделять па...   29.6.2009, 11:36
|- - AD   Цитата(Litkevich Yuriy @ 29.6.2009, 12:36...   29.6.2009, 11:59
|- - AD   Очень прошу помочь. Как реализовать код для QVecto...   29.6.2009, 13:25
- - SABROG   Кстати интересный класс есть QVarLengthArray, если...   29.6.2009, 11:43
- - Litkevich Yuriy   Цитата(AD @ 29.6.2009, 17:25) Делать выде...   29.6.2009, 13:34
|- - AD   Цитата(Litkevich Yuriy @ 29.6.2009, 14:34...   29.6.2009, 14:05
- - Litkevich Yuriy   по ссылке, что я привёл, дочитай до конца. Там ест...   29.6.2009, 15:19
|- - AD   Юра, мне непонятна одна конкретная вещь: вот я в...   29.6.2009, 16:14
- - Litkevich Yuriy   Цитата(AD @ 29.6.2009, 20:14) Как теперь ...   29.6.2009, 17:52
|- - AD   Цитата(Litkevich Yuriy @ 29.6.2009, 18:52...   29.6.2009, 18:02
|- - BRE   AD, прости, а можешь словами рассказать, что нужно...   29.6.2009, 19:18
|- - AD   code 1, code2 из первого примера - это рабочие ко...   29.6.2009, 22:01
- - Tonal   Т.е. у тебя много маленьких векторочков. В stl у ...   30.6.2009, 7:15
|- - AD   Цитата(Tonal)Т.е. у тебя много маленьких векторочк...   30.6.2009, 8:23
|- - Tonal   Цитата(AD @ 30.6.2009, 12:23) Цитата(Tona...   30.6.2009, 10:28
|- - AD   Цитата(Tonal @ 30.6.2009, 11:28) Ничего п...   30.6.2009, 10:41
- - BRE   Как я понял задачу. Есть несколько конфигурационны...   30.6.2009, 8:45
|- - AD   Цитата(BRE @ 30.6.2009, 9:45) Как я понял...   30.6.2009, 9:03
|- - BRE   Цитата(AD @ 30.6.2009, 10:03) Есть ини-фа...   30.6.2009, 9:28
|- - AD   Цитата(BRE @ 30.6.2009, 10:28) Так может ...   30.6.2009, 9:31
- - SABROG   Цитата(Tonal @ 30.6.2009, 8:15) и сделать...   30.6.2009, 8:53
- - Tonal   Можешь написать свой, проще зацепить из буста. Гд...   30.6.2009, 10:54
|- - AD   Цитата(Tonal @ 30.6.2009, 11:54) Можешь н...   30.6.2009, 11:11
|- - AD   да, кстати, а мне нужно наследоваться от стандартн...   30.6.2009, 12:09
|- - AD   Странно, как-то не очень помогло. Или я что-то заб...   30.6.2009, 14:09
|- - BRE   Цитата(AD @ 30.6.2009, 15:09) В чем еще м...   30.6.2009, 14:56
|- - Tonal   Цитата(AD @ 30.6.2009, 18:09) Странно, ка...   1.7.2009, 8:47
|- - AD   Цитата(Tonal @ 1.7.2009, 9:47) Ты выделяе...   1.7.2009, 9:05
|- - AD   В boost в файле allocator.hpp нашел следующий код:...   1.7.2009, 9:59
|- - Tonal   Цитата(AD @ 1.7.2009, 13:05) Цитата(Tonal...   1.7.2009, 10:44
|- - AD   Цитата(Tonal @ 1.7.2009, 11:44) Вот и смо...   1.7.2009, 10:50
||- - AD   Вот блин. Сделал следующий распределитель: allocat...   1.7.2009, 14:55
|- - AD   Цитата(Tonal @ 1.7.2009, 11:44) Вот и смо...   13.7.2009, 11:40
- - Влад   Хм, есть опасение, что если причиной разработки ал...   30.6.2009, 14:49
|- - AD   Влад, исходя из твоих слов, следует заменить глоба...   30.6.2009, 14:59
- - BRE   Почитай вот эту тему. В конце есть готовый алокато...   1.7.2009, 10:37
- - BRE   А ты в профилировщике результаты смотрел, точно им...   1.7.2009, 15:24
|- - AD   Цитата(BRE @ 1.7.2009, 16:24) А ты в проф...   1.7.2009, 15:57
- - Влад   Цитата(AD @ 30.6.2009, 15:59) Влад, исход...   1.7.2009, 16:07
|- - AD   Цитата(Влад @ 1.7.2009, 17:07) Нет. Тут ф...   1.7.2009, 16:10
|- - BRE   Цитата(AD @ 1.7.2009, 17:10) Да, видимо, ...   1.7.2009, 16:49
|- - AD   У меня видоизменилась несколько структура, потому ...   1.7.2009, 17:14
|- - AD   Заметил такую странную вещь: Указал CHUNK_SIZE = 2...   1.7.2009, 17:57
- - Tonal   Может всё же так: ... struct Chunk { Chunk* ne...   2.7.2009, 8:04
|- - AD   Цитата(Tonal @ 2.7.2009, 9:04) Да, ты вед...   2.7.2009, 9:11
|- - AD   Так.... совсем интересно. При загрузке большого ко...   2.7.2009, 10:51
- - Влад   Видел: http://rsdn.ru/forum/cpp.applied/930448.asp...   2.7.2009, 13:38
|- - AD   Так, получилось ускорение с помощью массивов (пока...   3.7.2009, 12:00
|- - AD   Сделал распределитель памяти следующий: allocator#...   6.7.2009, 17:36
|- - AD   Буду очень благодарен за любую помощь. Очень требу...   7.7.2009, 11:07
|- - AD   Так... Ну теперь я совсем не понимаю, почему при з...   8.7.2009, 12:12
|- - AD   Сделал так: вначале чтение всех файлов. Пихаем про...   9.7.2009, 17:10
- - Влад   Цитатаbcp Usage: bcp --list [options] module-li...   13.7.2009, 11:59
- - AD   Итак, сделал вырезку некоторых файлов из boost и д...   13.7.2009, 17:30


Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


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




RSS Текстовая версия Сейчас: 28.1.2025, 20:54