Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Помогите оптимизировать код. потребляет очень много оперативн. памяти 
:(
    Опции темы
Proger10
Дата 22.5.2011, 21:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 312
Регистрация: 16.12.2008

Репутация: нет
Всего: нет



Есть код на c++ (компилируется под GCC) - подсчёт коэффициентов осцилляторной системы методом Рунге-Кутта (метод в простейшем случае). Проблема в том, что секунд за 10, он успевает занять метров 600 оперативки, что она и заканчивается. Я к сожалению, на "вы" с С++, не очень часто приходится с ним сталкиваться, вот и не получается оптимизировать его, чтобы как-то высвобождать выделяемую память.

Код полностью рабочий и компилируемый (скопилировать и запустить можно так: `g++ rk.cpp && ./a.out`).

Может вы подскажите в какую сторону смотреть здесь нужно в первую очередь? Я там указал восклицательными знаками, что на объекте function съедается очень много памяти, покуда циклов этих много, а объекты не удаляются видимо, вот и происходит так, а как удалить - не знаю :( Подскажите чего-нибудь?

Код

#include <stdio.h>
#include <iostream>

using namespace std;

struct vectorvalue{
    
    unsigned int ElementsCount;
    double *x;
    
    vectorvalue(){        
    }
    
    void initializeArrElements( unsigned int ElementsCount ){
        
        this->ElementsCount = ElementsCount;
        
        for( unsigned int i = 0; i < ElementsCount; i++ ){
            
            x[ i ] = 0;
            
        }
        
    }
    
    vectorvalue( unsigned int kCount, double *myParams ){
        
        ElementsCount = kCount * 2;
        
        x = new double[ ElementsCount ];
        
        for( unsigned int i = 0; i < ElementsCount; i++ ){
            
            x[ i ] = myParams[ i ];
            
        }
        
    }
    
    vectorvalue operator +(vectorvalue a){
        
        for( unsigned int i = 0; i < ElementsCount; i++ ){
            
            a.x[ i ]+=this->x[ i ];
            
        }
        
        return a;
        
    }
    
    vectorvalue operator -(vectorvalue a){
        
        for( unsigned int i = 0; i < ElementsCount; i++ ){
            
            a.x[ i ]=this->x[ i ]-a.x[ i ];
            
        }
        
        return a;
        
    }
    
    void operator =(vectorvalue a){
        
        for( unsigned int i = 0; i < ElementsCount; i++ ){
            
            this->x[ i ]=a.x[ i ];
            
        }        
        
    }
    
    vectorvalue operator *(double a){
        
        vectorvalue res;
        res.x = new double[ ElementsCount ];
        res.ElementsCount = ElementsCount;
        
        for( unsigned int i = 0; i < ElementsCount; i++ ){
            
            res.x[ i ]=a*this->x[ i ];
            
        }        
        
        return res;
        
    }
    
};


vectorvalue function( vectorvalue Y, double forceValue, unsigned int kCount, double *m, double *k ){
    
    double vvArgs1[ kCount * 2+1 ];
    
    for( unsigned int i = 0; i < kCount; i++ ) {
        
        vvArgs1[ i ] = Y.x[ kCount + i ];
        
    }
    
    vvArgs1[ kCount ] = ( -k[ 0 ] * Y.x[ 0 ] + k[ 1 ] * ( Y.x[ 1 ] - Y.x[ 0 ] ) ) / m[ 0 ]; // first equation
    
    for( unsigned int i = 0; i < kCount - 2; i++ ) { // equations between the first eq and the last

        vvArgs1[ kCount + i + 1 ] = ( -k[ i + 1 ] * ( Y.x[ i + 1 ] - Y.x[ i ] ) + k[ i + 2 ] * ( Y.x[ i + 2 ] - Y.x[ i + 1 ] ) ) / m[ i + 1 ];
        
    }
    
    vvArgs1[ kCount * 2 - 1 ] = ( -k[ kCount - 1 ] * ( Y.x[ kCount - 1 ] - Y.x[ kCount - 2 ] ) + forceValue ) / m[ kCount - 1 ]; // last equation
    
    vectorvalue vv;
    vv.x = new double[ kCount * 2 ];
    vv.initializeArrElements( kCount * 2 );
    
    vv = vectorvalue( kCount, vvArgs1 );
    
    return vv;
    
}

void calculateHarmonicsModel( unsigned int kCount, double *k, double *m ){
    
    double harmStep = 0.001;

    vectorvalue func, k1, k2, k3, k4;
    
    func.x = new double[ kCount * 2 ];
    func.initializeArrElements( kCount * 2 );
    
    k1.x = new double[ kCount * 2 ];
    k1.initializeArrElements( kCount * 2 );    
    k2.x = new double[ kCount * 2 ];
    k2.initializeArrElements( kCount * 2 );
    k3.x = new double[ kCount * 2 ];
    k3.initializeArrElements( kCount * 2 );
    k4.x = new double[ kCount * 2 ];
    k4.initializeArrElements( kCount * 2 );
    
    func.x[ 0 ] = -1;
    func.x[ 1 ] = 1;
    func.x[ 2 ] = 2;
    func.x[ 3 ] = -1;
    
    double t = 0;
    double forceValue = 0.0;
    
    for( unsigned int i = 0; i < 100000000; i++ ) {
        
        vectorvalue vv1, vv2, vv3;
        
        vv1.x = new double[ kCount * 2 ];
        vv1.initializeArrElements( kCount * 2 );
        
        vv2.x = new double[ kCount * 2 ];
        vv2.initializeArrElements( kCount * 2 );
        
        vv3.x = new double[ kCount * 2 ];
        vv3.initializeArrElements( kCount * 2 );
        
        // !!!! ЗДЕСЬ ПРОБЛЕМА:
        k1 = function( func, forceValue, kCount, m, k );
        
        vv1 = func + k1 * ( harmStep / 2 );
        k2 = function( vv1, forceValue, kCount, m, k );
        
        vv2 = func + k2 * ( harmStep / 2 ); 
        k3 = function( vv2, forceValue, kCount, m, k );
        
        vv3 = func + k3 * harmStep;
        k4 = function( vv3, forceValue, kCount, m, k );
        
        free( vv1.x );
        free( vv2.x );
        free( vv3.x );
        
        func=func+(k1+k2*2+k3*2+k4)*(harmStep/6);
        
        printf( "%f %f\n", func.x[ 0 ], func.x[ 1 ] );
        
        t += harmStep;

    }
    
}

int main(){
    
    unsigned int kCount = 2;
    
    double m[ kCount ];
    double k[ kCount ];
    
    for( unsigned int i2 = 0; i2 < kCount; i2++ ) {
        
        m[ i2 ] = 2;
        k[ i2 ] = 10;
        
    }
    
    calculateHarmonicsModel( kCount, k, m );        
    
    printf( "Completed!\n" );
    
    cin.get();
    
    return 0;
    
}

PM MAIL   Вверх
boostcoder
Дата 22.5.2011, 21:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



банальная утечка на vectorvalue::x - память на освобождается. ни разу smile

PM WWW   Вверх
Proger10
Дата 22.5.2011, 21:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 312
Регистрация: 16.12.2008

Репутация: нет
Всего: нет



А в том-то и проблема, что я не знаю как освободить там её smile Вы про ту, что перед "return vv" можно высвободить переменную-указатель x в vectorvalue function(...)? smile Если её высвободишь, то return'а не получится... smile вот и не знаю как тут организовать это)
PM MAIL   Вверх
VictorTsaregorodtsev
Дата 22.5.2011, 22:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 274
Регистрация: 28.7.2006

Репутация: 1
Всего: 8



Не, беда в том, что на каждой итерации цикла аж 3 раза делается 
vvZ.x = new double[ kCount * 2 ];
а потом перед концом цикла delete[] для этих указателей не делается. Надо делать. Или деструктор для класса-структуры напишите, раз конструктор написали. Но тогда надо в "пустом" конструкторе присваивать НУЛЛ указателю, а в деструкторе проверять ненулевость указателя перед удалением памяти.

Это сообщение отредактировал(а) VictorTsaregorodtsev - 22.5.2011, 22:07
PM MAIL WWW   Вверх
bsa
Дата 22.5.2011, 22:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



Proger10, добавь #include <vector> в начало исходника. Затем в структуре замени double *x; на std::vector<double> x; Ну и наконец все строчки вида XXX.x = new double[asd]; замени на XXX.x.resize(asd);
Утечка памяти пропадет.
По хорошему, все содержимое твоей структуры может быть заменено этим вектором, так как у него есть метод size(), который возвращает количество элементов.
На будущее. Если выделил память, то ее надо освободить. Освобождать нужно, когда она больше не нужна.

P.S.: можно еще проще:
строку 11 заменить на "vectorvalue() : x(0) {"
добавить строку после 12: ~vectorvalue() { delete []x; }

Это сообщение отредактировал(а) bsa - 22.5.2011, 22:22
PM   Вверх
Proger10
Дата 22.5.2011, 23:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 312
Регистрация: 16.12.2008

Репутация: нет
Всего: нет



Цитата(bsa @ 22.5.2011,  22:20)

P.S.: можно еще проще:
строку 11 заменить на "vectorvalue() : x(0) {"
добавить строку после 12: ~vectorvalue() { delete []x; }

Вот это у меня не срабатывает, на моменте запуска проги пишет:

Код

$ g++ rk.cpp && ./a.out 
a.out(1421) malloc: *** error for object 0x100100080: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap


Код там получился такой:
Код

//vectorvalue(){    
vectorvalue() : x(0) {
}
~vectorvalue() {
    delete []x;
}    

PM MAIL   Вверх
borisbn
Дата 23.5.2011, 00:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Proger10, вот самый дельный совет
Цитата(bsa @  22.5.2011,  22:20 Найти цитируемый пост)
По хорошему, все содержимое твоей структуры может быть заменено этим вектором

добавь к этому вектору операции
Код

typedef std::vector< double > vectorvalue;

vectorvalue operator+( const vectorvalue & left, const vectorvalue & right ) {
    int count = left.size();
    assert( count == right.size() );
    vectorvalue res;
    res.resize( count ); 
    for ( int i = 0; i < count; i++ ) {
       res[ i ] = left[ i ] + right[ i ];
    }
    return res;
}

vectorvalue operator-( const vectorvalue & left, const vectorvalue & right ) {
    int count = left.size();
    assert( count == right.size() );
    vectorvalue res;
    res.resize( count ); 
    for ( int i = 0; i < count; i++ ) {
       res[ i ] = left[ i ] - right[ i ];
    }
    return res;
}

vectorvalue operator*( const vectorvalue & v, double val ) {
    int count = v.size();
    vectorvalue res;
    res.resize( count ); 
    for ( int i = 0; i < count; i++ ) {
        res[ i ] = v[ i ] * val;
    } 
    return res;
}

и замени 
Код

vectorvalue v;
v.x = new double[ kCount * 2 ];
v.initializeArrElements( kCount * 2 );

на
Код

vectorvalue func( kCount * 2,  0 );


Это сообщение отредактировал(а) borisbn - 23.5.2011, 00:27


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
borisbn
Дата 23.5.2011, 01:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



в общем получается как-то так
http://liveworkspace.org/code/8cab44a718cc...ef262c73620be2a
Правильный результат или нет - не знаю. Проверяй.


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
Proger10
Дата 23.5.2011, 01:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 312
Регистрация: 16.12.2008

Репутация: нет
Всего: нет



Цитата(bsa @ 22.5.2011,  22:20)
Proger10, добавь #include <vector> в начало исходника. Затем в структуре замени double *x; на std::vector<double> x; Ну и наконец все строчки вида XXX.x = new double[asd]; замени на XXX.x.resize(asd);
Утечка памяти пропадет.
По хорошему, все содержимое твоей структуры может быть заменено этим вектором, так как у него есть метод size(), который возвращает количество элементов.
На будущее. Если выделил память, то ее надо освободить. Освобождать нужно, когда она больше не нужна.

Спасибо большое! Вот это сделал и теперь программа занимает в оперативке всего лишь 380кб! smile
Буду теперь следить за расходами памяти в программах smile

Всем спасибо за участие в теме!

Добавлено через 1 минуту и 37 секунд
Цитата(borisbn @ 23.5.2011,  01:06)
в общем получается как-то так
http://liveworkspace.org/code/8cab44a718cc...ef262c73620be2a
Правильный результат или нет - не знаю. Проверяй.

Спасибо! Очень интересный код получился.. сейчас разберусь в нём.. smile
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0552 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.