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