From b6da8482e184e98f506343325d045bd362778cc0 Mon Sep 17 00:00:00 2001 From: Jonathan Rouzaud-Cornabas <jonathan.rouzaud-cornabas@inria.fr> Date: Tue, 10 Jul 2018 08:39:42 +0200 Subject: [PATCH] Fix memory leak + add configure switch for different level of parallelism (and intel hack) --- configure.ac | 44 +++++++ src/aevol_run.cpp | 9 +- src/libaevol/Dna_SIMD.cpp | 11 +- src/libaevol/ExpManager.cpp | 54 ++++---- src/libaevol/ExpManager.h | 1 + src/libaevol/SIMD_Individual.cpp | 212 +++++++++++++++++++++++++------ src/libaevol/SIMD_Individual.h | 8 +- src/libaevol/Stats_SIMD.cpp | 4 +- 8 files changed, 272 insertions(+), 71 deletions(-) diff --git a/configure.ac b/configure.ac index 1f938b55f..2d23fc175 100644 --- a/configure.ac +++ b/configure.ac @@ -556,6 +556,34 @@ if test "x$bitset" = "xyes" ; then AC_DEFINE(_DYNAMIC_CUSTOM_BITSET) fi +# ************************* --with-l1task option ******************************* +# +# With this option, pow basal support is enabled and the __POW_BASAL flag is defined +# + + +AC_MSG_CHECKING([whether to use Task or TaskLoop for first level parallelism]) +AC_ARG_WITH(l1task, [--with-l1task to enable Task as first level parallelism], l1task=$withval, l1task=no) +AC_MSG_RESULT($l1task) +AM_CONDITIONAL(WITH_L1TASK, test x"$l1task" != xno) +if test "x$l1task" = "xyes" ; then + AC_DEFINE(WITH_L1TASK) +fi + +# ************************* --with-finetaskloop option ******************************* +# +# With this option, pow basal support is enabled and the __POW_BASAL flag is defined +# + + +AC_MSG_CHECKING([whether to use TaskLoop for second level parallelism]) +AC_ARG_WITH(finetaskloop, [--with-finetaskloop to enable TaskLoop as second level parallelism], finetaskloop=$withval, finetaskloop=no) +AC_MSG_RESULT($finetaskloop) +AM_CONDITIONAL(WITH_FINETASKLOOP, test x"$finetaskloop" != xno) +if test "x$finetaskloop" = "xyes" ; then + AC_DEFINE(WITH_FINETASKLOOP) +fi + # ************************** --without-cuda option ********************************** # @@ -578,6 +606,22 @@ else AC_MSG_NOTICE([Disable CUDA Library]) AM_CONDITIONAL([ENABLE_CUDA], [test x"$with_cuda" == xno]) fi + + + +# ************************ --without-standalonesimd option ********************* +# + +AC_MSG_CHECKING([whether to enable SIMD Standalone]) +AC_ARG_WITH(x, [ --without-standalonesimd to disable SIMD standalone], , with_standalonesimd=yes) +AC_MSG_RESULT($with_standalonesimd) +AM_CONDITIONAL(WITH_STANDALONESIMD, test x"$with_standalonesimd" != xno) +if test "x$with_standalonesimd" != xno ; then + AC_DEFINE(WITH_STANDALONE_SIMD) +else + AC_DEFINE(__NO_VANILLA) +fi + # ************************* back to GENERAL stuff ******************************* AC_CONFIG_FILES([Makefile diff --git a/src/aevol_run.cpp b/src/aevol_run.cpp index 7edafe167..05e9cb24d 100644 --- a/src/aevol_run.cpp +++ b/src/aevol_run.cpp @@ -99,6 +99,7 @@ int main(int argc, char* argv[]) int64_t t0 = -1; int64_t t_end = -1; int64_t nb_steps = -1; + int grain_size = 1; #ifndef __NO_X bool show_display_on_startup = true; @@ -110,7 +111,7 @@ int main(int argc, char* argv[]) // ------------------------------------------------------------------------- // 2) Define allowed options // ------------------------------------------------------------------------- - const char * options_list = "he:n:r:vVwxp:"; + const char * options_list = "he:n:r:vVwxp:g:"; static struct option long_options_list[] = { // Print help { "help", no_argument, NULL, 'h' }, @@ -130,6 +131,7 @@ int main(int argc, char* argv[]) { "noX", no_argument, NULL, 'x' }, // Run in parallel on x threads (0 or negative value yields system default) { "parallel", required_argument, NULL, 'p' }, + { "grainsize", required_argument, NULL, 'g' }, { 0, 0, 0, 0 } }; @@ -197,6 +199,10 @@ int main(int argc, char* argv[]) #endif break; } + case 'g' : { + grain_size = atoi(optarg); + break; + } default : { // An error message is printed in getopt_long, we just need to exit exit(EXIT_FAILURE); @@ -234,6 +240,7 @@ int main(int argc, char* argv[]) exp_manager = new ExpManager(); #endif + exp_manager->grain_size = grain_size; exp_manager->load(t0, verbose, true); exp_manager->set_t_end(t_end); diff --git a/src/libaevol/Dna_SIMD.cpp b/src/libaevol/Dna_SIMD.cpp index 2b06bdd2a..78ee2d9ae 100644 --- a/src/libaevol/Dna_SIMD.cpp +++ b/src/libaevol/Dna_SIMD.cpp @@ -71,13 +71,16 @@ Dna_SIMD::~Dna_SIMD() { #ifdef WITH_BITSET delete bitset_; #else - free(data_); + if (data_ != nullptr) { free(data_); data_=nullptr;} #endif - for (auto repl : mutation_list) - delete repl; +if (mutation_list.size() > 0) { + for (auto repl : mutation_list) + delete repl; + mutation_list.clear(); +} + - mutation_list.clear(); } #ifndef WITH_BITSET diff --git a/src/libaevol/ExpManager.cpp b/src/libaevol/ExpManager.cpp index 500d05961..baeb62eac 100644 --- a/src/libaevol/ExpManager.cpp +++ b/src/libaevol/ExpManager.cpp @@ -380,6 +380,19 @@ auto t1 = high_resolution_clock::now(); + + + if (!simd_individual->standalone()) { + t1 = high_resolution_clock::now(); + // Write statistical data and store phylogenetic data (tree) +#pragma omp single + { + output_m_->write_current_generation_outputs(); + } + t2 = high_resolution_clock::now(); + duration_2 += std::chrono::duration_cast<std::chrono::microseconds>( t2 - t1 ).count(); + } + #ifdef __CUDACC__ std::cout<<"PERFLOG,"<<AeTime::time()<<","<<duration_2<<","<<duration<<","<<duration_A<<","<<duration_B<<","<<duration_C<<std::endl; @@ -390,14 +403,6 @@ auto t1 = high_resolution_clock::now(); #else std::cout<<"PERFLOG,"<<AeTime::time()<<","<<duration_2<<","<<duration_simd<<std::endl; #endif - - if (!simd_individual->standalone()) { - // Write statistical data and store phylogenetic data (tree) -#pragma omp single - { - output_m_->write_current_generation_outputs(); - } - } } /*! @@ -594,31 +599,36 @@ void ExpManager::run_evolution() { } simd_individual = new SIMD_Individual(this); + simd_individual->protein_grain_size = grain_size; + simd_individual->rna_grain_size = grain_size; + simd_individual->run_a_step(best_indiv()->w_max(),selection_pressure(),false); // For each generation while (true) { // termination condition is into the loop - printf( - "============================== %" PRId64 " ==============================\n", - AeTime::time()); - if (!first_run) { - if (SIMD_Individual::standalone_simd) { - printf( - " Best individual's (%d) distance to target (metabolic) : %f (clones %d)\n", - simd_individual->best_indiv->indiv_id, - simd_individual->best_indiv->metaerror, - simd_individual->nb_clones_); + if (AeTime::time() % 100 == 0) { + printf( + "============================== %" PRId64 " ==============================\n", + AeTime::time()); + if (!first_run) { + if (SIMD_Individual::standalone_simd) { + printf( + " Best individual's (%d) distance to target (metabolic) : %f (clones %d)\n", + simd_individual->best_indiv->indiv_id, + simd_individual->best_indiv->metaerror, + simd_individual->nb_clones_); + } else { + printf(" Best individual's (%d) distance to target (metabolic) : %f\n", + best_indiv()->id(), + best_indiv()->dist_to_target_by_feature(METABOLISM)); + } } else { printf(" Best individual's (%d) distance to target (metabolic) : %f\n", best_indiv()->id(), best_indiv()->dist_to_target_by_feature(METABOLISM)); } - } else { - printf(" Best individual's (%d) distance to target (metabolic) : %f\n", - best_indiv()->id(), - best_indiv()->dist_to_target_by_feature(METABOLISM)); } first_run = false; diff --git a/src/libaevol/ExpManager.h b/src/libaevol/ExpManager.h index 485bad0db..f8545a93e 100644 --- a/src/libaevol/ExpManager.h +++ b/src/libaevol/ExpManager.h @@ -167,6 +167,7 @@ class ExpManager : public Observer { // SIMD Stuff SIMD_Individual* simd_individual = nullptr; + int grain_size = 1; protected: // ======================================================================= // Protected Methods diff --git a/src/libaevol/SIMD_Individual.cpp b/src/libaevol/SIMD_Individual.cpp index afc2cce60..39e228e70 100644 --- a/src/libaevol/SIMD_Individual.cpp +++ b/src/libaevol/SIMD_Individual.cpp @@ -12,7 +12,11 @@ namespace aevol { +#ifndef WITH_STANDALONE_SIMD + bool SIMD_Individual::standalone_simd = false; +#else bool SIMD_Individual::standalone_simd = true; +#endif SIMD_Individual::SIMD_Individual(ExpManager* exp_m) { @@ -38,6 +42,7 @@ SIMD_Individual::SIMD_Individual(ExpManager* exp_m) { internal_simd_struct[indiv_id]->parent_id = indiv_id; //printf("Set Prev Indiv\n"); prev_internal_simd_struct[indiv_id] = internal_simd_struct[indiv_id]; + internal_simd_struct[indiv_id]->global_id = AeTime::time()*1024+indiv_id; } dna_size = new int[exp_m_->nb_indivs()]; @@ -532,14 +537,18 @@ void SIMD_Individual::selection() { // printf("DNA BEFORE SIZE of %d is %d (%d)\n",indiv_id,dna_size[indiv_id],internal_simd_struct[indiv_id]->dna_->length()); if (exp_m_->dna_mutator_array_[indiv_id]->hasMutate()) { +/* if (internal_simd_struct[indiv_id] != nullptr) { + printf("Warning will replace something that is not null !!!\n"); + }*/ - exp_m_->simd_individual->internal_simd_struct[indiv_id] = + internal_simd_struct[indiv_id] = new Internal_SIMD_Struct(exp_m_,prev_internal_simd_struct [next_generation_reproducer_[indiv_id]],false); - exp_m_->simd_individual->internal_simd_struct[indiv_id]->indiv_id = indiv_id; - exp_m_->simd_individual->internal_simd_struct[indiv_id]->parent_id = + internal_simd_struct[indiv_id]->global_id = AeTime::time()*1024+indiv_id; + internal_simd_struct[indiv_id]->indiv_id = indiv_id; + internal_simd_struct[indiv_id]->parent_id = next_generation_reproducer_[indiv_id]; #ifdef WITH_BITSET @@ -678,36 +687,110 @@ SIMD_Individual::~SIMD_Individual() { printf("Destroy SIMD Controller\n"); for (int indiv_id = 0; indiv_id < (int) exp_m_->nb_indivs(); indiv_id++) { - if (internal_simd_struct[indiv_id] != nullptr) { - for (auto rn : internal_simd_struct[indiv_id]->rnas) { - delete rn; - } - internal_simd_struct[indiv_id]->rnas.clear(); - for (auto prot : internal_simd_struct[indiv_id]->proteins) { - delete prot; + +/* + if (internal_simd_struct[indiv_id] != nullptr) { + printf("Internal %d : %d \n", indiv_id, internal_simd_struct[indiv_id]->usage_count_); } - internal_simd_struct[indiv_id]->proteins.clear(); +*/ - if (internal_simd_struct[indiv_id]->usage_count_ > 1) - internal_simd_struct[indiv_id]->usage_count_--; - else { - delete internal_simd_struct[indiv_id]; - internal_simd_struct[indiv_id] = nullptr; + if (internal_simd_struct[indiv_id] != nullptr) { + + + if (internal_simd_struct[indiv_id]->usage_count_ > 0) + internal_simd_struct[indiv_id]->usage_count_--; + else { + if (internal_simd_struct[indiv_id]->usage_count_ != -1) { + internal_simd_struct[indiv_id]->usage_count_ = -1; + + for (auto rn : internal_simd_struct[indiv_id]->rnas) { + delete rn; + } + internal_simd_struct[indiv_id]->rnas.clear(); + for (auto prot : internal_simd_struct[indiv_id]->proteins) { + delete prot; + } + internal_simd_struct[indiv_id]->proteins.clear(); + + delete internal_simd_struct[indiv_id]; + internal_simd_struct[indiv_id] = nullptr; + } + } } - } + } + for (int indiv_id = 0; indiv_id < (int) exp_m_->nb_indivs(); indiv_id++) { if (prev_internal_simd_struct[indiv_id] != nullptr) { - if (prev_internal_simd_struct[indiv_id]->usage_count_ > 1) + if (prev_internal_simd_struct[indiv_id]->usage_count_ > 0) prev_internal_simd_struct[indiv_id]->usage_count_--; else { - delete prev_internal_simd_struct[indiv_id]; - prev_internal_simd_struct[indiv_id] = nullptr; + if (prev_internal_simd_struct[indiv_id]->usage_count_ != -1) { + prev_internal_simd_struct[indiv_id]->usage_count_ = -1; + + /*printf("DELETE --- PREV %d (%d) : %d \n", indiv_id, prev_internal_simd_struct[indiv_id]->usage_count_, + prev_internal_simd_struct[indiv_id]->global_id);*/ + for (auto rn : prev_internal_simd_struct[indiv_id]->rnas) { + delete rn; + } + prev_internal_simd_struct[indiv_id]->rnas.clear(); + for (auto prot : prev_internal_simd_struct[indiv_id]->proteins) { + delete prot; + } + prev_internal_simd_struct[indiv_id]->proteins.clear(); + + delete prev_internal_simd_struct[indiv_id]; + prev_internal_simd_struct[indiv_id] = nullptr; + } } } delete exp_m_->dna_mutator_array_[indiv_id]; } + for (int indiv_id = 0; indiv_id < (int) exp_m_->nb_indivs(); indiv_id++) { + /* if (internal_simd_struct[indiv_id] != nullptr) { + printf("Still here %d : %d\n",internal_simd_struct[indiv_id]->global_id, + internal_simd_struct[indiv_id]->usage_count_); + //} + // delete internal_simd_struct[indiv_id]; + } +*/ + if (prev_internal_simd_struct[indiv_id] != nullptr) { + if (prev_internal_simd_struct[indiv_id]->usage_count_ != -1) { + prev_internal_simd_struct[indiv_id]->usage_count_ = -1; + /*printf("Still here %d -- %d : %d\n", indiv_id, prev_internal_simd_struct[indiv_id]->global_id, + prev_internal_simd_struct[indiv_id]->usage_count_);*/ + + for (auto rn : prev_internal_simd_struct[indiv_id]->rnas) { + delete rn; + } + + prev_internal_simd_struct[indiv_id]->rnas.clear(); + for (auto prot : prev_internal_simd_struct[indiv_id]->proteins) { + delete prot; + } + prev_internal_simd_struct[indiv_id]->proteins.clear(); + + delete prev_internal_simd_struct[indiv_id]; + prev_internal_simd_struct[indiv_id] = nullptr; + } + } + } + +/* for (int indiv_id = 0; indiv_id < (int) exp_m_->nb_indivs(); indiv_id++) { + *//* if (internal_simd_struct[indiv_id] != nullptr) { + printf("Still here %d : %d\n",internal_simd_struct[indiv_id]->global_id, + internal_simd_struct[indiv_id]->usage_count_); + //} + // delete internal_simd_struct[indiv_id]; + } + *//* + if (prev_internal_simd_struct[indiv_id] != nullptr) { + printf("WHAT Still here %d -- %d : %d\n",indiv_id,prev_internal_simd_struct[indiv_id]->global_id, + prev_internal_simd_struct[indiv_id]->usage_count_); + } + }*/ + delete[] prev_internal_simd_struct; delete[] internal_simd_struct; @@ -716,6 +799,15 @@ SIMD_Individual::~SIMD_Individual() { delete stats_best; delete stats_mean; + + for (int indiv_id = 0; indiv_id < (int) exp_m_->nb_indivs(); indiv_id++) { + int x = indiv_id / exp_m_->world()->height(); + int y = indiv_id % exp_m_->world()->height(); + + exp_m_->world()->grid(x, y)->individual()->clear_everything_except_dna_and_promoters(); + exp_m_->world()->grid(x, y)->individual()->genetic_unit_list_nonconst().clear(); + delete exp_m_->world()->grid(x, y)->individual(); + } } @@ -1520,7 +1612,9 @@ void SIMD_Individual::opt_prom_compute_RNA() { //#pragma omp task firstprivate(indiv_id) // { +#ifdef WITH_FINETASKLOOP #pragma omp taskloop grainsize(rna_grain_size) +#endif for (int prom_idx = 0; prom_idx< internal_simd_struct[indiv_id]->promoters.size(); prom_idx++) { if (internal_simd_struct[indiv_id]->promoters.find(prom_idx) != @@ -1984,7 +2078,9 @@ void SIMD_Individual::compute_RNA() { internal_simd_struct[indiv_id]->rnas.resize( internal_simd_struct[indiv_id]->promoters.size()); //#pragma omp parallel for firstprivate(indiv_id) schedule(dynamic) +#ifdef WITH_FINETASKLOOP #pragma omp taskloop grainsize(rna_grain_size) +#endif for (int rna_idx = 0; rna_idx < (int) internal_simd_struct[indiv_id]->promoters.size(); rna_idx++) { //#pragma omp task firstprivate(indiv_id, rna_idx) @@ -2169,7 +2265,9 @@ void SIMD_Individual::compute_RNA() { } void SIMD_Individual::start_protein(int indiv_id) { -#pragma omp taskloop grainsize(rna_grain_size) +#ifdef WITH_FINETASKLOOP + #pragma omp taskloop grainsize(rna_grain_size) +#endif for (int rna_idx = 0; rna_idx < (int) internal_simd_struct[indiv_id]->rna_count_; rna_idx++) { //#pragma omp task firstprivate(indiv_id, rna_idx) depend(out: internal_simd_struct[indiv_id]) @@ -2449,7 +2547,9 @@ void SIMD_Individual::compute_protein(int indiv_id) { proteins.resize(resize_to); } //#pragma omp parallel for firstprivate(indiv_id) schedule(dynamic) +#ifdef WITH_FINETASKLOOP #pragma omp taskloop grainsize(rna_grain_size) +#endif for (int rna_idx = 0; rna_idx < (int) internal_simd_struct[indiv_id]->rna_count_; rna_idx++) { if (internal_simd_struct[indiv_id]->rnas[rna_idx]->is_init_) { @@ -3388,7 +3488,9 @@ void SIMD_Individual::translate_protein(double w_max) { void SIMD_Individual::translate_protein(int indiv_id, double w_max) { -#pragma omp taskloop grainsize(protein_grain_size) +#ifdef WITH_FINETASKLOOP + #pragma omp taskloop grainsize(protein_grain_size) +#endif for (int protein_idx = 0; protein_idx < (int) internal_simd_struct[indiv_id]->protein_count_; protein_idx++) { //#pragma omp task firstprivate(indiv_id, protein_idx) depend(inout: internal_simd_struct[indiv_id]) @@ -4091,9 +4193,13 @@ void SIMD_Individual::run_a_step(double w_max, double selection_pressure,bool op #pragma omp single nowait { nb_clones_ = 0; -#pragma omp taskloop +#ifndef WITH_L1TASK + #pragma omp taskloop +#endif for (int indiv_id = 0; indiv_id < exp_m_->nb_indivs(); indiv_id++) { - //#pragma omp task firstprivate(indiv_id) +#ifdef WITH_L1TASK + #pragma omp task firstprivate(indiv_id) +#endif { // if (AeTime::time() > 0 && optim_prom) check_selection(indiv_id); if (standalone_ && optim_prom) { @@ -4157,8 +4263,8 @@ void SIMD_Individual::run_a_step(double w_max, double selection_pressure,bool op } -//#pragma omp task firstprivate(indiv_id) - // { +/*#pragma omp task firstprivate(indiv_id) + {*/ if (optim_prom) { //printf("Clear structures\n"); //clear_struct_before_next_step(); @@ -4297,28 +4403,52 @@ void SIMD_Individual::run_a_step(double w_max, double selection_pressure,bool op //#pragma omp single //#pragma omp taskloop for (int indiv_id = 0; indiv_id < (int) exp_m_->nb_indivs(); indiv_id++) { + //if (indiv_id == 0) + // printf("%d -- usage %d -- \n", indiv_id, internal_simd_struct[indiv_id]->usage_count_); int usage_cpt = 0; - //#pragma omp critical +#pragma omp critical { - usage_cpt = prev_internal_simd_struct[indiv_id]->usage_count_--; + if (prev_internal_simd_struct[indiv_id]->usage_count_ == 1) { + prev_internal_simd_struct[indiv_id]->usage_count_ = -1; - if (usage_cpt == 0) delete prev_internal_simd_struct[indiv_id]; + } else + prev_internal_simd_struct[indiv_id]->usage_count_--; + /*else { + printf("Still alive %d : %d\n",prev_internal_simd_struct[indiv_id]->global_id, + prev_internal_simd_struct[indiv_id]->usage_count_); + }*/ + } prev_internal_simd_struct[indiv_id] = internal_simd_struct[indiv_id]; internal_simd_struct[indiv_id] = nullptr; } - } else { + } else if (standalone_ && (!optim_prom)) { + + } else { // printf("Copy to old generation struct\n"); -#pragma omp parallel -#pragma omp single -#pragma omp taskloop +//#pragma omp parallel +//#pragma omp single +//#pragma omp taskloop for (int indiv_id = 0; indiv_id < (int) exp_m_->nb_indivs(); indiv_id++) { + int usage_cpt = 0; + + #pragma omp critical + { + if (prev_internal_simd_struct[indiv_id]->usage_count_ == 1) { + prev_internal_simd_struct[indiv_id]->usage_count_ = -1; - prev_internal_simd_struct[indiv_id] = internal_simd_struct[indiv_id]; - internal_simd_struct[indiv_id] = nullptr; + delete prev_internal_simd_struct[indiv_id]; + } else + prev_internal_simd_struct[indiv_id]->usage_count_--; + //usage_cpt = prev_internal_simd_struct[indiv_id]->usage_count_; + + } + + prev_internal_simd_struct[indiv_id] = internal_simd_struct[indiv_id]; + internal_simd_struct[indiv_id] = nullptr; } } @@ -4331,6 +4461,8 @@ void SIMD_Individual::run_a_step(double w_max, double selection_pressure,bool op best_fitness = prev_internal_simd_struct[indiv_id]->fitness; } } +/* + printf("IDX BEST %d\n",idx_best);*/ best_indiv = prev_internal_simd_struct[idx_best]; @@ -4687,10 +4819,12 @@ Internal_SIMD_Struct::Internal_SIMD_Struct(ExpManager* exp_m, Internal_SIMD_Stru } Internal_SIMD_Struct::~Internal_SIMD_Struct() { - for (auto element = promoters.begin(); - element != promoters.end(); ++element) { - delete element->second; - } + if (promoters.size() > 0) { + for (auto element = promoters.begin(); + element != promoters.end(); ++element) { + if (element->second != nullptr) delete element->second; + } + } promoters.clear(); diff --git a/src/libaevol/SIMD_Individual.h b/src/libaevol/SIMD_Individual.h index b12c7b24f..13c59dcdc 100644 --- a/src/libaevol/SIMD_Individual.h +++ b/src/libaevol/SIMD_Individual.h @@ -127,6 +127,8 @@ class Internal_SIMD_Struct { ExpManager* exp_m_; + int global_id = -1; + void rebuild_index(); void remove_promoters_around(int32_t pos_1); @@ -264,7 +266,8 @@ class SIMD_Individual { int32_t nb_clones_; static bool standalone_simd;//= true; - + int rna_grain_size = 32; + int protein_grain_size = 32; private: ExpManager* exp_m_; int* dna_size; @@ -280,8 +283,7 @@ class SIMD_Individual { void check_selection(int indiv_id); - int rna_grain_size = 32; - int protein_grain_size = 32; + }; } diff --git a/src/libaevol/Stats_SIMD.cpp b/src/libaevol/Stats_SIMD.cpp index 409c645ae..90877773a 100644 --- a/src/libaevol/Stats_SIMD.cpp +++ b/src/libaevol/Stats_SIMD.cpp @@ -187,7 +187,7 @@ void Stats_SIMD::compute_average() { amount_of_dna_ += simd_individual_->prev_internal_simd_struct[indiv_id]->dna_->length(); for (int i = 0; i < simd_individual_->prev_internal_simd_struct[indiv_id]->rna_count_; i++) { - if (simd_individual_->best_indiv->rnas[i] != nullptr) { + if (simd_individual_->prev_internal_simd_struct[indiv_id]->rnas[i] != nullptr) { if (simd_individual_->prev_internal_simd_struct[indiv_id]->rnas[i]->is_coding_) nb_coding_rnas_++; else @@ -196,7 +196,7 @@ void Stats_SIMD::compute_average() { } for (int i = 0; i < simd_individual_->prev_internal_simd_struct[indiv_id]->protein_count_; i++) { - if (simd_individual_->best_indiv->rnas[i] != nullptr) { + if (simd_individual_->prev_internal_simd_struct[indiv_id]->rnas[i] != nullptr) { if (simd_individual_->prev_internal_simd_struct[indiv_id]->proteins[i]->is_functional) { nb_functional_genes_++; } else { -- GitLab