Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.80/15: Рейтинг темы: голосов - 15, средняя оценка - 4.80
77 / 50 / 16
Регистрация: 17.05.2015
Сообщений: 262

Оптимизация, сжатие переменных

10.02.2016, 05:19. Показов 3175. Ответов 35
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Есть у меня програмка, абстракный эмулятор псевдо эволюции так сказать.
Есть в нем класс, который имеет много перемен типа double и int. Порядка 20-25 (в будущем будет 35+).
Класс сам себя регулярно копирует и помещает в список. Когда делаю тестовый прогон - то миллион созданных обьектов сжирают у меня 1-1.2ГБ оперативной памяти (а я замахиваюсь на 10 миллионов).
Большая часть этих перемен почти никогда не достигнит значения 10 000, от сюда мне пришла идея, что если хранить эти параметры в одной unsigned long (или нескольких).
Вот например, создаем переменную 's = 1' (первая цифра в ней условная), умножаем ее на 10 000 и прибавляем наш первый блок данных, потом умножаем опять на 10 000 и прибавляем второй блок данных, опять на 10 000 и опять прибавляем блок данных и т.д.
Например:
1*10000 + 455
10455 * 10000 + 2865
104552865 * 10000 + 54
1045528650054...

С плавающей точкой нужно определить, сколько знаков после запятой нам надо (мне лично нужен только один знак), тут все тоже самое, только блок данных будут на один символ больше занимать.

Но перед тем как городить огород. Есть же наверняка готовые велосипеды, что бы хранить много данных в одной переменной или оптимизированном под это контейнере, что бы не выделять под каждый блок данных по 4-8 байт?

Хотя есть у меня сомнения, что QObject сам по сибе жрет больше, чем все эти переменные.
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
10.02.2016, 05:19
Ответы с готовыми решениями:

Оптимизация в пределах линейных участков - исключение лишних переменных
Необходимо произвести оптимизацию в пределах линейных участков (исключить лишние переменные). На входе имеем синтаксическое дерево. (На...

Сжатие и оптимизация БД
Здравствуйте имеется БД весом в 3терабайта( бд раньше хранила в себе очень много файлов. После того как поняли что так бесконечно расширять...

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

35
 Аватар для Nosey
1379 / 406 / 144
Регистрация: 22.10.2014
Сообщений: 872
12.02.2016, 12:30
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от SergioO Посмотреть сообщение
вот такого точно не надо советовать
все вещественные числа только в double (минимум)
Вам для игры жизнь не хватит 7-ми значащих чисел во float'e?
0
1394 / 1023 / 325
Регистрация: 28.07.2012
Сообщений: 2,813
12.02.2016, 23:24
Цитата Сообщение от SergioO Посмотреть сообщение
все вещественные числа только в double (минимум)
Цитата Сообщение от Nosey Посмотреть сообщение
Вам для игры жизнь не хватит 7-ми значащих чисел во float'e?
В одном проекте, над которым я работаю в команде, для повышения производительности и уменьшения потребления памяти вообще пришлось отказаться от вещественной арифметики в пользу целочисленной на int8.
0
77 / 50 / 16
Регистрация: 17.05.2015
Сообщений: 262
13.02.2016, 12:23  [ТС]
И так. Переписал пол кода.
Использовал стандартные классы, не QObject.
Использовал стандартные контейнеры. (хотя QLinkedList мне кажется шустрее работает, чем std::list).
Там где возможно, double заменил на флоат. На short|uint16_t думал менять, но пока на float остановился.
Запили новый класс, общая карта координат всех обьектов, банально это лист указателей, не более.

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

В функции life_cicle() у меня на каждом втором шаге вызывался rand() для создания случайности в разных просчета. Но эта rand жрала у меня 22% процессорного времени. Тут я просто создал переменную r = rand() и поставил ее везде за место rand. Так же передаю ее в функцию mutations, что бы там не вызывать rand().
В итоге и рандоминизация осталась в принципе и с экономил около двадцати процентов процессорного времени.

Самое прожорливое теперь у меня, это конструктор самого обьекта, а именно оператор new и map.push. =)

main.cpp
Кликните здесь для просмотра всего текста
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <QCoreApplication>
#include <QProcess>
#include "simpleorganism.h"
#include <iostream>
#include <time.h>
#include <QDebug>
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    srand(time(NULL));
    SimpleOrganism::pull_organism.clear();
    for (int i = 0; i < 100; ++i)
        SimpleOrganism::pull_organism.push_back(new SimpleOrganism());
 
    for (int i = 0; i < 10000; ++i) {
        SimpleOrganism::global_life_cicle();
      //  if (i % 10 == 0) {
            SimpleOrganism::show_stat();
      //  }
 
 
    }
 
 
    return a.exec();
}


dna.h, dna.cpp
Кликните здесь для просмотра всего текста
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#ifndef DNA_H
#define DNA_H
 
#include <list>
 
#define G_DNA_SIZE 20
 
class DNA
{
 
public:
    explicit DNA();
    explicit DNA(DNA * parent_dna);
    ~DNA();
 
    //QList<short>  get_dna();
    //short get_dna();
    short get_dna_block(int i);
    bool set_dna_block(int i, short param);
    bool copy_dna(DNA * parent_dna);
    bool mutations(int i, unsigned int random);
    bool mutations(unsigned int random);
private:
    //QList<short> dna;
    short dna[G_DNA_SIZE];
 
};
 
#endif // DNA_H

Кликните здесь для просмотра всего текста
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include "dna.h"
#include <QDebug>
 
 
DNA::DNA()
{
    for (int i = 0; i < G_DNA_SIZE; ++i) {
        dna[i] = rand() % 20 + 2;
    }
}
 
DNA::DNA(DNA *parent_dna)
{
    copy_dna(parent_dna);
}
 
DNA::~DNA() {
 
}
 
 
short DNA::get_dna_block(int i) {
    return dna[i];
}
 
bool DNA::set_dna_block(int i, short param) {
    if (i < 1)
        return false;
    dna[i] = param;
    return true;
}
 
bool DNA::copy_dna(DNA *parent_dna) {
    for (int i = 0; i < G_DNA_SIZE; i++)
        dna[i] = parent_dna->get_dna_block(i);
    return true;
}
 
bool DNA::mutations(int i, unsigned int random) {
    //int random = rand() % 100;
    if (random % 100 <= 49)
        dna[i]++;
    else
        if (dna[i] > 1)
            dna[i]--;
 
    return true;
}
 
bool DNA::mutations(unsigned int random) {
    for (unsigned int i = 0; i < random % (G_DNA_SIZE / 2) + 1; ++i)
      mutations(random % (G_DNA_SIZE - 1) + 1, random);
//    mutations(random % (G_DNA_SIZE - 1) + 1, random);
 
    return true;
}


simpleOrganism.h, .cpp
Кликните здесь для просмотра всего текста
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#ifndef SIMPLEORGANISM_H
#define SIMPLEORGANISM_H
 
#include <QList>
#include <QListIterator>
#include <QLinkedList>
#include <QLinkedListIterator>
#include <QMutableListIterator>
#include <QDebug>
#include <QtMath>
 
 
#include <cmath>
#include <time.h>
#include <list>
#include <forward_list>
#include <iterator>
#include "dna.h"
 
 
#define LIFE_INTERVAL 0.1
 
struct statistic {
    int mutations;
    int alives;
    int deads;
    int creates;
    int delete_objects;
    int size_pull;
    int del_test;
 
};
 
class SimpleOrganism
{
 
public:
    static class Map map;
    static uint64_t GLOBAL_ID_ORGANISM;
    static uint64_t GLOBAL_CLASS_ORGANISM;
    //static QLinkedList<SimpleOrganism *> pull_organism;
    //static QLinkedList<SimpleOrganism *>::iterator g_itr;
    static std::list<SimpleOrganism *> pull_organism;
    static std::list<SimpleOrganism *>::iterator g_itr;
    static bool global_life_cicle();
    static void show_stat();
 
    explicit SimpleOrganism();
    explicit SimpleOrganism(SimpleOrganism *parent_organism);
    ~SimpleOrganism();
    DNA * dna;
    uint64_t get_id();
    uint64_t get_class();
 
    bool lifecicle();
    bool get_life();
    void clone();
    void death();
    void show();
    void delete_this();
 
    uint64_t * get_ID_point();
    double * get_posX_point();
    double * get_posY_point();
    SimpleOrganism * get_this_point();
private:
    uint64_t * ID_Organism;
    uint64_t * Class_organism;
    static statistic stat;
 
    struct parametrs {
        float outer_shell; //внешняя оболочка толщина   [1]
        float inner_shell; //внутреняя оболочка толщина [2]
        float insides;     //внутренности толщина       [3]
        float force;       //массивность/сила/etc. [4]
        float density;     //плотность             [5]
        float life_cicle;      //жизненный цыкл.      [8]
    } max_param, current_param;
 
    struct movement {
        float speed;
        float direction; //направление 360градусов
        float acceleration = 0; //разгон, макс 100% 1.0.
        double * posX;
        double * posY;
        bool move = false;
    } move;
 
    float size;        //общая толщина. (радиус)
    float hungry;      //голод
    bool life;
 
    bool dna_calc();
    bool param_calc();
    bool push_pull();
 
 
};
 
#endif // SIMPLEORGANISM_H

Кликните здесь для просмотра всего текста
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
#include "simpleorganism.h"
#include "map.h"
#include <random>
 
#define MAX_SPEED current_param.force - ((size * (current_param.density / 10)) / 20)
 
uint64_t SimpleOrganism::GLOBAL_ID_ORGANISM = 0;
uint64_t SimpleOrganism::GLOBAL_CLASS_ORGANISM = 0;
statistic SimpleOrganism::stat;
Map SimpleOrganism::map;
 
 
 
//QList<SimpleOrganism *> SimpleOrganism::pull_organusm;
//QVector<SimpleOrganism *> SimpleOrganism::pull_organism;
//std::vector<SimpleOrganism *> SimpleOrganism::pull_organism;
//std::deque<SimpleOrganism *> SimpleOrganism::pull_organism;
//std::deque<SimpleOrganism *>::iterator SimpleOrganism::g_itr;
//QLinkedList<SimpleOrganism *> SimpleOrganism::pull_organism;
//QLinkedList<SimpleOrganism *>::iterator SimpleOrganism::g_itr;
 
std::list<SimpleOrganism *> SimpleOrganism::pull_organism;
std::list<SimpleOrganism *>::iterator SimpleOrganism::g_itr;
 
SimpleOrganism::SimpleOrganism()
{
    ID_Organism = new uint64_t;
    *ID_Organism = GLOBAL_ID_ORGANISM;
    GLOBAL_ID_ORGANISM++;
 
 
    Class_organism = new uint64_t;
    *Class_organism = GLOBAL_CLASS_ORGANISM;
    GLOBAL_CLASS_ORGANISM++;
 
    move.posX = new double;
    *move.posX = 0;
    move.posY = new double;
    *move.posY = 0;
 
   // this->setObjectName("Organism CLASS: " + QString().number(Class_organism) + "; ID: " + QString().number(GLOBAL_ID_ORGANISM));
 
    dna = new DNA();
    dna_calc();
 
}
 
SimpleOrganism::SimpleOrganism(SimpleOrganism *parent_organism)
{
    ID_Organism = new uint64_t;
    *ID_Organism = GLOBAL_ID_ORGANISM;
    GLOBAL_ID_ORGANISM++;
 
    Class_organism = new uint64_t;
    *Class_organism = parent_organism->get_class();
 
    move.posX = new double;
    *move.posX = 0;
    move.posY = new double;
    *move.posY = 0;
 
    dna = new DNA(parent_organism->dna);
    dna_calc();
}
 
SimpleOrganism::~SimpleOrganism() {
    delete ID_Organism;
    delete Class_organism;
    delete move.posX;
    delete move.posY;
    delete dna;
    stat.delete_objects++;
}
 
bool SimpleOrganism::dna_calc() {
    map.push(this);
    stat.alives++;
    stat.creates++;
 
    max_param.insides = log(dna->get_dna_block(3)) / log(1.01); //внутренности от ДНК
    max_param.outer_shell = max_param.insides / 20 + (log(dna->get_dna_block(1)) / log(1.1) / 2); //внешняя оболочка, зависит от размеров внутренностей и ДНК
    max_param.inner_shell = max_param.insides / 20 + (log(dna->get_dna_block(2)) / log(1.1) / 2); //внутренняя оболочка, зависит от размера внутренностей и ДНК
    max_param.force = log(dna->get_dna_block(4)) / log(1.01); //мощность.
    max_param.density = log(dna->get_dna_block(5)) / log(1.1); // чем выше плотность - тем прочнее и медленнее создание.
    max_param.life_cicle = log(dna->get_dna_block(8)) / log(1.1);
 
    current_param.life_cicle = LIFE_INTERVAL;
 
    life = true;
    hungry = 1;
    return true;
}
 
bool SimpleOrganism::param_calc() {
 
    float procent_life = current_param.life_cicle / max_param.life_cicle;
    current_param.insides = max_param.insides * procent_life;
    current_param.outer_shell = max_param.outer_shell  * procent_life;
    current_param.inner_shell = max_param.inner_shell * procent_life;
    current_param.force = max_param.force * procent_life;
    current_param.density = max_param.density * procent_life;
 
    size = current_param.insides + current_param.inner_shell + current_param.outer_shell;
    float temp_speed = current_param.force - ((size * (current_param.density / 10)) / 20);
    if (move.move) {
        if (move.acceleration < 1)
            move.acceleration += 0.1;
    }
    else {
        if (move.acceleration > 0)
            move.acceleration -= 0.1;
    }
    move.speed = temp_speed * move.acceleration;
 
    return true;
}
 
bool SimpleOrganism::lifecicle() {
    if (!life)
        return false;
 
    unsigned int r = rand();
    //смерть от голода.
    if (hungry >= 100) {
        death();
        return false;
    }
 
    //Вероятность смерти от старости
    if (current_param.life_cicle > max_param.life_cicle) {
        if (r % 100+1 <= current_param.life_cicle / max_param.life_cicle * 100 - 100) {
            death();
            return false;
        }
    }
 
    current_param.life_cicle += LIFE_INTERVAL;
 
    //Голод
    //if (hungry < 100)
   //     hungry++;
 
    if (r % 10000 <= 5) {
        dna->mutations(r);
        stat.mutations++;
    }
 
    if (current_param.life_cicle / max_param.life_cicle * 100 + (r % 40) - hungry >= 100 ) {
        clone();
        return false;
    }
 
    param_calc();
    return true;
}
 
bool SimpleOrganism::global_life_cicle() {
    clock_t start_timer = clock();
    //clock_t stop_timer;
    for (g_itr = pull_organism.begin(); g_itr != pull_organism.cend(); g_itr++) {
        (*g_itr)->lifecicle();
    }
    //Ограничитель FPS
   // while (clock() - start_timer < 100000) {}
 
    if (stat.deads > 200000) {
        map.clear();
        for (g_itr = pull_organism.begin(); g_itr != pull_organism.cend(); ++g_itr) {
            if (stat.deads < 100000)
                break;
            if (!(*g_itr)->get_life()) {
                stat.deads--;
                (*g_itr)->delete_this();
                pull_organism.erase(g_itr);
                g_itr--;
            }
        }
        stat.del_test = map.get_count();
    }
 
    return true;
}
 
 
void SimpleOrganism::death() {
    life = false;
    stat.deads++;
    stat.alives--;
}
 
void SimpleOrganism::clone() {
    pull_organism.push_back(new SimpleOrganism(this));
    pull_organism.push_back(new SimpleOrganism(this));
    death();
}
 
uint64_t SimpleOrganism::get_class() {
    return *Class_organism;
}
 
uint64_t SimpleOrganism::get_id() {
    return *ID_Organism;
}
 
bool SimpleOrganism::get_life() {
    return life;
}
 
bool SimpleOrganism::push_pull() {
    pull_organism.push_back(this);
    return true;
}
 
 
void SimpleOrganism::show_stat() {
    qDebug() << "\n####STATS:####"
             << "\n creates - " << stat.creates
             << "\n lifes - " << stat.alives
             << "\n deads - " << stat.deads
             << "\n mutations - " << stat.mutations
             << "\n delete obj - " << stat.delete_objects
             << "\n size_pull - " << stat.size_pull
             << "\n del test - " << stat.del_test
             << "\n#############\n";
}
 
void SimpleOrganism::show() {
    qDebug() << "life " << life
             << "\n life cicle " << current_param.life_cicle;
 
}
 
void SimpleOrganism::delete_this() {
    delete this;
}
 
 
uint64_t * SimpleOrganism::get_ID_point() {
    return ID_Organism;
}
 
double * SimpleOrganism::get_posX_point() {
    return move.posX;
}
 
double * SimpleOrganism::get_posY_point() {
    return move.posY;
}
 
SimpleOrganism * SimpleOrganism::get_this_point() {
    return this;
}


map.h, .cpp
Кликните здесь для просмотра всего текста
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#ifndef MAP_H
#define MAP_H
#include <list>
#include <iterator>
 
struct coords {
    uint64_t * ID;
    double * posX;
    double * posY;
    class SimpleOrganism * object;
};
 
class Map
{
public:
    Map();
    ~Map();
 
    bool push(class SimpleOrganism * value);
    coords * get(uint64_t ID);
    coords * get(class SimpleOrganism *value);
    coords * get(double posX, double posY);
    int get_count();
    void clear();
 
private:
    std::list<coords *> map;
    std::list<coords *>::iterator itr;
};
 
#endif // MAP_H

Кликните здесь для просмотра всего текста
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include "map.h"
#include "simpleorganism.h"
 
Map::Map() {
 
}
 
Map::~Map() {
    while (!map.empty())
        delete *(map.begin());
}
 
coords * Map::get(uint64_t ID) {
    for (itr = map.begin(); itr != map.cend(); ++itr)
        if (*(*itr)->ID == ID)
            return (*itr);
    return NULL;
}
 
coords * Map::get(SimpleOrganism * value) {
    for (itr = map.begin(); itr != map.cend(); ++itr)
        if ((*itr)->object == value)
            return (*itr);
    return NULL;
}
 
coords * Map::get(double posX, double posY) {
    for (itr = map.begin(); itr != map.cend(); ++itr)
        if (*(*itr)->posX == posX && *(*itr)->posY == posY)
            return (*itr);
    return NULL;
}
 
bool Map::push(SimpleOrganism * value) {
    map.push_back(new coords);
    map.back()->ID = value->get_ID_point();
    map.back()->posX = value->get_posX_point();
    map.back()->posY = value->get_posY_point();
    map.back()->object = value->get_this_point();
    return true;
}
 
int Map::get_count() {
    return map.size();
}
 
void Map::clear() {
    for (itr = map.begin(); itr != map.cend(); ++itr) {
        if (!(*itr)->object->get_life()) {
            map.erase(itr);
            --itr;
        }
    }
}


После всех этих манипуляций в 1077Мб влезло 2.18 миллиона. обьектов.
0
 Аватар для Nosey
1379 / 406 / 144
Регистрация: 22.10.2014
Сообщений: 872
13.02.2016, 12:56
Valeryn,
C++
1
2
3
4
Map::~Map() {
    while (!map.empty())
        delete *(map.begin());
}
->

C++
1
2
3
4
5
6
7
Map::~Map()
{
    for (auto& value : map)
    {
        delete value;
    }
}
И после этого валгринд наверное начнёт работать нормально )
0
77 / 50 / 16
Регистрация: 17.05.2015
Сообщений: 262
13.02.2016, 13:08  [ТС]
Цитата Сообщение от Nosey Посмотреть сообщение
И после этого валгринд наверное начнёт работать нормально )
А до этого он нормально не работал?

Я если честно не могу не как понять принцип работы оператора auto.
Почему у тебя написано именно auto&, а не auto?
0
 Аватар для Nosey
1379 / 406 / 144
Регистрация: 22.10.2014
Сообщений: 872
13.02.2016, 14:48
Цитата Сообщение от Valeryn Посмотреть сообщение
Почему у тебя написано именно auto&, а не auto?
Хотел написать следующее, потом сообразил, что оно не нужно:
C++
1
2
3
4
5
6
7
8
9
    for (auto& value : map)
    {
        if (<нужно удалить>)
        {
            delete value;
            value = nullptr;
        }
    }
}
Суть не в auto, а в том что у вас там был бесконечный цикл, ваше приложение никогда нормальным способом не завершалось.
0
77 / 50 / 16
Регистрация: 17.05.2015
Сообщений: 262
13.02.2016, 14:51  [ТС]
Цитата Сообщение от Nosey Посмотреть сообщение
Суть не в auto, а в том что у вас там был бесконечный цикл, ваше приложение никогда нормальным способом не завершалось.
Я же сам указатель не удаляю получается...
0
 Аватар для Nosey
1379 / 406 / 144
Регистрация: 22.10.2014
Сообщений: 872
13.02.2016, 14:54
Цитата Сообщение от Valeryn Посмотреть сообщение
Я же сам указатель не удаляю получается...
Не понимаю о чём вы.

Просто поменяйте цикл в деструкторе мапы и дальше валгриндом посмотрите что да как получается.
0
77 / 50 / 16
Регистрация: 17.05.2015
Сообщений: 262
13.02.2016, 15:00  [ТС]
Еще такой момент сделал. Убрал цикл очистки, который удалял "трупы", теперь в том же цикле, где и просчитывается жизнь обьекта - проверяется, не мертв ли обьект и не пора ли его удалить, перед вызовом жизненного цикла.

Пошел костылями, теперь внутри каждого обьекта находится итератор, который указывает на них же в объекте map, что бы при удалении обьекта, он сам себя удалял из контейнера, не вызывая лишних циклов.
До этого был отдельный цикл, который удалял мертвые обьекты и еще один отдельный цикл, который удалял из карты все мертвые обьекты. (т.е. два лишьних цикла, но благодоря костылю - он теперь один, он же и слишком мертвых удаляет, он же и контейнер Map::map очищает, что бы не дай бог указатель не указал на удаленный обьект.)

SimpleOrganism::dna_calc()
Кликните здесь для просмотра всего текста
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
bool SimpleOrganism::dna_calc() {
    itr_map_this = map.push(this);
 
    stat.alives++;
    stat.creates++;
 
    max_param.insides = log(dna->get_dna_block(3)) / log(1.01); //внутренности от ДНК
    max_param.outer_shell = max_param.insides / 20 + (log(dna->get_dna_block(1)) / log(1.1) / 2); //внешняя оболочка, зависит от размеров внутренностей и ДНК
    max_param.inner_shell = max_param.insides / 20 + (log(dna->get_dna_block(2)) / log(1.1) / 2); //внутренняя оболочка, зависит от размера внутренностей и ДНК
    max_param.force = log(dna->get_dna_block(4)) / log(1.01); //мощность.
    max_param.density = log(dna->get_dna_block(5)) / log(1.1); // чем выше плотность - тем прочнее и медленнее создание.
    max_param.life_cicle = log(dna->get_dna_block(8)) / log(1.1);
 
    current_param.life_cicle = LIFE_INTERVAL;
 
    life = true;
    del = false;
    corpse = 0;
    hungry = 1;
    return true;
}


map:ush()
Кликните здесь для просмотра всего текста
C++ (Qt)
1
2
3
4
5
6
7
8
std::list<coords *>::iterator Map::push(SimpleOrganism * value) {
    map.push_back(new coords);
    map.back()->ID = value->ID_Organism;
    map.back()->posX = value->move.posX;
    map.back()->posY = value->move.posY;
    map.back()->object = value;
    return --map.end();
}


Добавлено через 3 минуты
Цитата Сообщение от Nosey Посмотреть сообщение
Не понимаю о чём вы.
Цитата Сообщение от Nosey Посмотреть сообщение
while (!map.empty())
* * * * delete *(map.begin());
т.е. идет проверка, что контейнер не пуст, а дальше вызов delete, удаление обьекта coords. При этом сам контейнер не очищается, из за чего map.empty никогда не станет true.

Вот я к чему
0
 Аватар для Nosey
1379 / 406 / 144
Регистрация: 22.10.2014
Сообщений: 872
13.02.2016, 15:02
Valeryn, У вас организмы в течении одного жизненного цикла осуществляют взаимодействие? а будут взаимодействовать?

Что-то я такого не нашел в коде )

Добавлено через 46 секунд
Цитата Сообщение от Valeryn Посмотреть сообщение
т.е. идет проверка, что контейнер не пуст, а дальше вызов delete, удаление обьекта coords. При этом сам контейнер не очищается, из за чего map.empty никогда не станет true.
Именно так, но в деструкторе вам на это наплевать, лист умрёт при смерти map'ы.
0
77 / 50 / 16
Регистрация: 17.05.2015
Сообщений: 262
13.02.2016, 15:37  [ТС]
Цитата Сообщение от Nosey Посмотреть сообщение
У вас организмы в течении одного жизненного цикла осуществляют взаимодействие? а будут взаимодействовать?
Сейчас они просто просчитывают вероятности своей смерти, свои параметры и вероятности деления.
В дальнейшем конечно будут взаимодействовать. Для этого им координаты прикрутил и сделал список, по которому они друг друга искать будут.
Хотя я думаю может лучше пусть друг друга ищут с помощью бродкастов/сообщений? Но тут все равно им придется от куда то извлекать координаты получателей.
0
 Аватар для Nosey
1379 / 406 / 144
Регистрация: 22.10.2014
Сообщений: 872
13.02.2016, 16:01
Valeryn, Тогда если размеры живности - не определены - то гуглите и пишите QuadTree, если определены, то vector<vector<живность*>> сойдёт.
И соответственно никаких листов. )
0
77 / 50 / 16
Регистрация: 17.05.2015
Сообщений: 262
13.02.2016, 16:27  [ТС]
Цитата Сообщение от Nosey Посмотреть сообщение
Valeryn, Тогда если размеры живности - не определены - то гуглите и пишите QuadTree, если определены, то vector<vector<живность*>> сойдёт.
И соответственно никаких листов. )
я если честно не догнал.
QuadTree - это некий двумерный массив, в нутри которого обсчитываются обьекты. Но когда их много - массив делиться на несколько массивов, а потом еще на несколько и т.д.?

А вот второе, зачем мне вектор векторов обьектов?) Ну будет этакий двумерный контейнер с обьектами, а что даст?
Я лист почему использую то, потому что последовательно обрабатываются все обьекты и из контейнера периодически удаляются и создаются обьекты, лист по сравнению с вектором существенно быстрее удаляет/добавляет обьекты из произвольной позиции.
0
 Аватар для Nosey
1379 / 406 / 144
Регистрация: 22.10.2014
Сообщений: 872
13.02.2016, 16:49
Цитата Сообщение от Valeryn Посмотреть сообщение
QuadTree - это некий двумерный массив, в нутри которого обсчитываются обьекты. Но когда их много - массив делиться на несколько массивов, а потом еще на несколько и т.д.?
Да, именно так.

Цитата Сообщение от Valeryn Посмотреть сообщение
А вот второе, зачем мне вектор векторов обьектов?) Ну будет этакий двумерный контейнер с обьектами, а что даст?
Быстрый поиск соседей, для расчёта "коллизий".

Цитата Сообщение от Valeryn Посмотреть сообщение
Я лист почему использую то, потому что последовательно обрабатываются все обьекты и из контейнера периодически удаляются и создаются обьекты, лист по сравнению с вектором существенно быстрее удаляет/добавляет обьекты из произвольной позиции.
Это будет самая меньшая из ваших бед.
0
77 / 50 / 16
Регистрация: 17.05.2015
Сообщений: 262
15.02.2016, 03:40  [ТС]
Цитата Сообщение от Nosey Посмотреть сообщение
Да, именно так.
С такой системой мне пришлось отказаться от общего пула и объекта, а держать пул в каждом блоке квадрата.
Но тут есть неоспоримый плюс - можно в отдельном потоке просчитывать каждый квадрат. Но тут же и минус, ибо надо обьекты перекидывать из потока в поток, при миграции между блоками, а тут блокировки/тормоза. Но пока сделал однопоточное решение.

map.h, cpp
Кликните здесь для просмотра всего текста
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#ifndef MAP_H
#define MAP_H
#include <list>
#include <iterator>
 
#define MAX_LEVEL 20
#define SIZE_MAP 1000000000
#define MAX_OBJ 20
 
 
class Map
{
public:
    Map(Map * parent_ = 0, int level = 0, double X, double Y, double size_ = SIZE_MAP);
    ~Map();
 
    bool push(class SimpleOrganism * object);
    bool cicle();
private:
    //размер карты = центральная точка  (+size ко всем краям)
    double size;
    //глубина
    int level;
    //раздроблена ли?
    bool drop;
    //центр карты
    struct {
        double X = 0;
        double Y = 0;
    } point;
 
 
 
    std::list<class SimpleOrganism *> pull;
    Map * parent;
    Map * NW;
    Map * NE;
    Map * SW;
    Map * SE;
 
    friend class SimpleOrganism;
};
 
#endif // MAP_H

Кликните здесь для просмотра всего текста
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#include "map.h"
#include "simpleorganism.h"
 
Map::Map(Map *parent_, int level, double X, double Y, double size_) {
    drop = false;
    point.X = X;
    point.Y = Y;
    const double s = size * 0.5f;
    parent = parent_;
    size = size_;
    if (level == MAX_LEVEL)
        return;
    NW = new Map(this, level+1, X - s, Y + s, s);
    NE = new Map(this, level+1, X + s, Y + s, s);
    SW = new Map(this, level+1, X - s, Y - s, s);
    SE = new Map(this, level+1, X + s, Y - s, s);
}
 
Map::~Map() {
    if (level == MAX_LEVEL)
        return;
 
    delete NW;
    delete NE;
    delete SW;
    delete SE;
}
 
bool Map::push(SimpleOrganism *object) {
    if (pull.size() < MAX_OBJ && drop == false) {
        //если обьект уходит за пределы текущего куба - то передать его родителю.
        //защиты от ухода за предел MAX_SIZE пока нету
        if (object->move.posX > X + size && object->move.posY > Y + size)
            parent->push(object);
        else if (object->move.posX < X - size && object->move.posY > Y + size)
            parent->push(object);
        else if (object->move.posX > X + size && object->move.posY < Y - size)
            parent->push(object);
        else if (object->move.posX < X - size && object->move.posY < Y - size)
            parent->push(object);
        else
            pull.push_back(object);
            return true;
    } //если текущий обьект раздроблен или переполнен - передаем следующему по глубине обьекту
    else if (object->move.posX > X && object->move.posY > Y)
        NW->push(object);
    else if (object->move.posX <= X && object->move.posY > Y)
        NE->push(object);
    else if (object->move.posX > X && object->move.posY <= Y)
        SW->push(object);
    else if (object->move.posX <= X && object->move.posY <= Y)
        SE->push(object);
    else
        return false;
    drop = true;
    return true;
}
 
bool Map::cicle() {
    if (!pull.empty()) {
        //пересортировка обьектов
        if (drop == true)
            for (auto it = pull.begin(); it != pull.cend();) {
                push((*it));
                it = pull.erase(it);
            }
        else {
            for (auto it = pull.begin(); it != pull.cend(); ) {
                if (!(*it)->get_del()) {
                    (*it)->lifecicle();
                    if ((*it)->move.posX > X+size && (*it)->move.posY > Y+size) {
                        parent->push((*it));
                        it = pull.erase(it);
                    }
                    else if ((*it)->move.posX < X-size && (*it)->move.posY > Y+size) {
                        parent->push((*it));
                        it = pull.erase(it);
                    }
                    else if ((*it)->move.posX > X+size && (*it)->move.posY < Y-size) {
                        parent->push((*it));
                        it = pull.erase(it);
                    }
                    else if ((*it)->move.posX < X-size && (*it)->move.posY < Y-size) {
                        parent->push((*it));
                        it = pull.erase(it);
                    }
                    ++it;
                }
                else {
                    delete (*it);
                    (*it)->stat.deads--;
                    (*it)->stat.delete_objects++;
                    it = pull.erase(it);
                } //else {
            } //for(auto it = pull.begin(); it != pull.cend(); ) {
        } //else {
    } // if(!pull.empty()) {
    else if (level != MAX_LEVEL) {
        NW->cicle();
        NE->cicle();
        SW->cicle();
        SE->cicle();
    }
}


VectorMove.h, cpp
Кликните здесь для просмотра всего текста
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#ifndef VECTORMOVE_H
#define VECTORMOVE_H
 
struct vec {
    double X;
    double Y;
};
 
class VectorMove
{
public:
    VectorMove(double * X_, double * Y_, double * speed_);
    double* X;
    double* Y;
    double* speed;
    double step;
 
    vec Way;
 
 
    void new_vector(double X_, double Y_, double newspeed);
    void move();
    void normalize();
private:
 
};
 
#endif // VECTORMOVE_H

Кликните здесь для просмотра всего текста
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include "vectormove.h"
#include <math.h>
 
VectorMove::VectorMove(double *X_, double *Y_, double *speed_)
{
    X = X_;
    Y = Y_;
    speed = speed_;
}
 
void VectorMove::move() {
    //делаем шаг
    X += vX * (1/step);
    Y += vY * (1/step);
 
}
 
void VectorMove::new_vector(double X_, double Y_) {
    vec.X = X_;
    vec.Y = Y_;
    //количество шагов до конечной точки
    step = abs((sqrt((vec.X*vec.X) + (vec.Y*vec.Y)) - sqrt((X*X) + (Y*Y))) / speed);
}


Написал вектор движения и просчет движения обьекта. Но пока мне кажется, что функция new_vector слишком тяжелая, из за вычесления длины вектора и деления его на скорость.
Последущее
0
77 / 50 / 16
Регистрация: 17.05.2015
Сообщений: 262
16.02.2016, 09:25  [ТС]
IT'S ALIVE!
Миниатюры
Оптимизация, сжатие переменных  
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
16.02.2016, 09:25
Помогаю со студенческими работами здесь

Оптимизация функции n переменных
Здравствуйте, помогите пожалуйста решить задачу. Необходимо отыскать максимум функции n переменных, но оптимизацию нужно проводить по одной...

Оптимизация двух переменных
Здравствуйте, оговорю сразу, математически я не подкован, а задача, как мне кажется, из ее поля. Перейду сразу к делу, у меня есть...

Безусловная оптимизация. Функция 2-х переменных.
кто может помочь решить задачу. x1x2+50/x1+20/x2 нахожу производные от x1и x2, объединяю это в систему и впадаю в ступор....

Многокритериальная оптимизация нелинейной функции 3х переменных
Добрый день. Пробовал найти решение, читал книги с алгоритмами и сайты но ничего понятного и рабочего не смог найти. Возможно не понял...

Оптимизация кода, универсальное имя переменных
Всем привет! В моем приложении в основном Activity есть несколько групп однотипных переменных и для каждой из них прописывается свой код....


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
36
Ответ Создать тему
Новые блоги и статьи
Переходник USB-CAN-GPIO
Eddy_Em 20.03.2026
Достаточно давно на работе возникла необходимость в переходнике CAN-USB с гальваноразвязкой, оный и был разработан. Однако, все меня терзала совесть, что аж 48-ногий МК используется так тупо: просто. . .
Оттенки серого
Argus19 18.03.2026
Оттенки серого Нашёл в интернете 3 прекрасных модуля: Модуль класса открытия диалога открытия/ сохранения файла на Win32 API; Модуль класса быстрого перекодирования цветного изображения в оттенки. . .
SDL3 для Desktop (MinGW): Рисуем цветные прямоугольники с помощью рисовальщика SDL3 на Си и C++
8Observer8 17.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-rectangles-sdl3-c. zip finish-rectangles-sdl3-cpp. zip
Символические и жёсткие ссылки в Linux.
algri14 15.03.2026
Существует два типа ссылок — символические и жёсткие. Ссылка в Linux — это запись в каталоге, которая может указывать либо на inode «файла-ИСТОЧНИКА», тогда это будет «жёсткая ссылка» (hard link),. . .
[Owen Logic] Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора
ФедосеевПавел 14.03.2026
Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора ВВЕДЕНИЕ Выполняя задание на управление насосной группой заполнения резервуара,. . .
делаю науч статью по влиянию грибов на сукцессию
anaschu 13.03.2026
прикрепляю статью
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru