From fbec5a3863135d0ac5b17257fff345cb3db39a27 Mon Sep 17 00:00:00 2001
From: Jonathan Rouzaud-Cornabas <jonathan.rouzaud-cornabas@inria.fr>
Date: Tue, 3 Jul 2018 14:46:31 +0200
Subject: [PATCH] Verified version with OpenMP Task without dependency

---
 src/libaevol/JumpingMT.cpp       |  3 +-
 src/libaevol/JumpingMT.h         |  2 +-
 src/libaevol/SIMD_Individual.cpp | 72 ++++++++++++++++++++------------
 src/libaevol/Selection.cpp       | 20 +++++++--
 4 files changed, 64 insertions(+), 33 deletions(-)

diff --git a/src/libaevol/JumpingMT.cpp b/src/libaevol/JumpingMT.cpp
index 97c4f0277..8d5b61e2b 100644
--- a/src/libaevol/JumpingMT.cpp
+++ b/src/libaevol/JumpingMT.cpp
@@ -236,13 +236,14 @@ double JumpingMT::gaussian_random()
   return x1 * r;
 }
 
-int32_t JumpingMT::roulette_random(double* probs, int32_t nb_elts)
+int32_t JumpingMT::roulette_random(double* probs, int32_t nb_elts, bool verbose )
 {
   double pick_one = 0.0;
 
   while (pick_one == 0.0)
   {
     pick_one = random();
+    //if (verbose) printf("pick one : %f\n",pick_one);
   }
 
   int32_t found_org = 0;
diff --git a/src/libaevol/JumpingMT.h b/src/libaevol/JumpingMT.h
index 4b0e38253..85b3ef6f4 100644
--- a/src/libaevol/JumpingMT.h
+++ b/src/libaevol/JumpingMT.h
@@ -101,7 +101,7 @@ class JumpingMT
     inline int64_t  random(int64_t max);  // ~
     int32_t         binomial_random(int32_t nb, double prob); // Binomial drawing of parameters (nb, prob)
     double          gaussian_random();                    // Double following a Standard Normal distribution
-    int32_t          roulette_random(double* probs, int32_t nb_elts); // Roulette selection
+    int32_t          roulette_random(double* probs, int32_t nb_elts, bool verbose = false); // Roulette selection
     void            multinomial_drawing (int32_t* destination, double* source, int32_t nb_drawings, int32_t colors);
     // Multinomial drawing of parameters (nb, {source[0], source[1], ... source[colors-1]})
 
diff --git a/src/libaevol/SIMD_Individual.cpp b/src/libaevol/SIMD_Individual.cpp
index 4d9561aa0..a44d22ef7 100644
--- a/src/libaevol/SIMD_Individual.cpp
+++ b/src/libaevol/SIMD_Individual.cpp
@@ -246,26 +246,32 @@ void SIMD_Individual::selection() {
                 local_fit_array[count]  = prev_internal_simd_struct[cur_x*grid_height+cur_y]->fitness;
 
 
-/*                    printf("Local fit %e %d %d %d -> %e\n",local_fit_array[count],cur_x,cur_y,cur_x*grid_height+cur_y,
-                           prev_internal_simd_struct[cur_x*grid_height+cur_y]->fitness);*/
+//                    printf("Local fit %e %d %d %d -> %e\n",local_fit_array[count],cur_x,cur_y,cur_x*grid_height+cur_y,
+//                           prev_internal_simd_struct[cur_x*grid_height+cur_y]->fitness);
 
                 local_meta_array[count]  = prev_internal_simd_struct[cur_x*grid_height+cur_y]->metaerror;
                 sum_local_fit += local_fit_array[count];
-/*                if (indiv_id == 268)
-                    printf("SIMD Local SUM Fit %e -- Fitness %e\n",sum_local_fit,local_fit_array[count]);*/
+                /*if (indiv_id == 0)
+                    printf("SIMD Local SUM Fit %e -- Fitness %e (CPU %e)\n",sum_local_fit,local_fit_array[count],exp_m_->world()->grid(x,y)->local_fit_array[count]);*/
                 count++;
             }
         }
 
         for(int16_t i = 0 ; i < neighborhood_size ; i++) {
             probs[i] = local_fit_array[i]/sum_local_fit;
-            /*if (i == 0)
-                printf("Local fit X %e %d %d %d -> %e\n",local_fit_array[i],cur_x,cur_y,cur_x*grid_height+cur_y,
+
+                /*printf("Local fit X %e %d %d %d -> %e\n",local_fit_array[i],cur_x,cur_y,cur_x*grid_height+cur_y,
                        prev_internal_simd_struct[cur_x*grid_height+cur_y]->fitness);*/
             //printf("%d -- prob[%d] : %e : fitness %e (%f) sum %e\n",indiv_id,i,probs[i],
             //       local_fit_array[i],local_meta_array[i],sum_local_fit);
         }
 
+        //printf("SIMD PRNG\n");
+        /*        bool verbose = false;
+        if (indiv_id == 2)  {
+            printf("SIMD PRNG\n");
+            verbose = true;
+        }*/
         int16_t found_org = exp_m_->world()->grid(x,y)->reprod_prng_simd_->roulette_random(probs, neighborhood_size);
 
         int16_t x_offset = (found_org / selection_scope_x) - 1;
@@ -276,26 +282,27 @@ void SIMD_Individual::selection() {
                        ((y+y_offset+grid_height) % grid_height);
 
 
-/*            for (int i = 0; i < neighborhood_size; i++) {
+            for (int i = 0; i < neighborhood_size; i++) {
                 float i_fit_1 = roundf(exp_m_->world()->grid(x,y)->probs[i] * 10000);
                 float i_fit_2 = roundf(probs[i] * 10000);
 
-                if (found_id != internal_simd_struct[indiv_id]->parent_id) {
+                if (found_id != next_generation_reproducer_[indiv_id]) {
 
-                    printf("For individual %d : Selection is diff SIMD %d CPU %d (Meta error %f -- %f || Fitness %e -- %e (%e %e diff %e -- %e %e -- %e %e)\n",
-                           indiv_id, found_id, internal_simd_struct[indiv_id]->parent_id,
-                           prev_internal_simd_struct[internal_simd_struct[indiv_id]->parent_id]->metaerror,
+                    printf("For individual %d : Selection is diff SIMD %d CPU %d (Meta error %f -- %f || Fitness %e -- %e)\n",
+                            // (Probs %e %e diff %e -- Fit Array %e %e -- Sum Fit %e %e)\n",
+                           indiv_id, found_id, next_generation_reproducer_[indiv_id],
+                           prev_internal_simd_struct[next_generation_reproducer_[indiv_id]]->metaerror,
                            prev_internal_simd_struct[found_id]->metaerror,
-                           prev_internal_simd_struct[internal_simd_struct[indiv_id]->parent_id]->fitness,
-                           prev_internal_simd_struct[found_id]->fitness,exp_m_->world()->grid(x,y)->probs[i],probs[i],
+                           prev_internal_simd_struct[next_generation_reproducer_[indiv_id]]->fitness,
+                           prev_internal_simd_struct[found_id]->fitness/*,exp_m_->world()->grid(x,y)->probs[i],probs[i],
                            exp_m_->world()->grid(x,y)->probs[i]-probs[i],
                            exp_m_->world()->grid(x,y)->local_fit_array[i],local_fit_array[i],
-                           exp_m_->world()->grid(x,y)->sum_local_fit,sum_local_fit
+                           exp_m_->world()->grid(x,y)->sum_local_fit,sum_local_fit*/
 
                     );
 
                 }
-            }*/
+            }
 
 
         delete [] local_fit_array;
@@ -4078,7 +4085,7 @@ void SIMD_Individual::run_a_step(double w_max, double selection_pressure,bool op
         for (int indiv_id = 0; indiv_id < exp_m_->nb_indivs(); indiv_id++) {
 #pragma omp task firstprivate(indiv_id)
             {
-            //if (optim_prom) check_selection(indiv_id);
+           // if (AeTime::time() > 0 && optim_prom) check_selection(indiv_id);
             if (standalone_ && optim_prom) {
 
                 selection(indiv_id);
@@ -4276,19 +4283,29 @@ void SIMD_Individual::run_a_step(double w_max, double selection_pressure,bool op
   //exit(-44);
   if (optim_prom) {
 //    printf("OPT -- Copy to old generation struct\n");
-    for (int indiv_id = 0; indiv_id < (int) exp_m_->nb_indivs(); indiv_id++) {
-      if (prev_internal_simd_struct[indiv_id]->usage_count_-1 == 0)
-        delete prev_internal_simd_struct[indiv_id];
-      else
-        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;
-    }
+//#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
+          {
+              usage_cpt = prev_internal_simd_struct[indiv_id]->usage_count_--;
+
+              if (usage_cpt == 0)
+                  delete prev_internal_simd_struct[indiv_id];
+          }
+
+          prev_internal_simd_struct[indiv_id] = internal_simd_struct[indiv_id];
+          internal_simd_struct[indiv_id] = nullptr;
+      }
   } else {
 //      printf("Copy to old generation struct\n");
-
-    for (int indiv_id = 0; indiv_id < (int) exp_m_->nb_indivs(); indiv_id++) {
+#pragma omp parallel
+#pragma omp single
+#pragma omp taskloop
+      for (int indiv_id = 0; indiv_id < (int) exp_m_->nb_indivs(); indiv_id++) {
 
       prev_internal_simd_struct[indiv_id] = internal_simd_struct[indiv_id];
       internal_simd_struct[indiv_id] = nullptr;
@@ -4630,6 +4647,7 @@ Internal_SIMD_Struct::Internal_SIMD_Struct(ExpManager* exp_m, Internal_SIMD_Stru
   count_prom = 0;
   exp_m_ = exp_m;
 
+  usage_count_ = 1;
   dna_ = new Dna_SIMD(clone->dna_,this,copy_dna);
 
   //promoters.resize(clone->promoters.size());
diff --git a/src/libaevol/Selection.cpp b/src/libaevol/Selection.cpp
index 246f0983b..105352323 100644
--- a/src/libaevol/Selection.cpp
+++ b/src/libaevol/Selection.cpp
@@ -1031,12 +1031,14 @@ Individual *Selection::do_local_competition (int16_t x, int16_t y) {
     for (int8_t j = -1 ; j < selection_scope_y_-1 ; j++) {
       cur_x = (x + i + grid_width)  % grid_width;
       cur_y = (y + j + grid_height) % grid_height;
-      //printf("%d %d : %lf %d\n",cur_x,cur_y,world->indiv_at(cur_x, cur_y)->fitness(),count);
 
       local_fit_array[count]  = world->indiv_at(cur_x, cur_y)->fitness();
       sort_fit_array[count]   = local_fit_array[count];
       initial_location[count] = count;
       sum_local_fit += local_fit_array[count];
+
+        //if (0 == x*grid_height+y) printf("%d %d : %e %d\n",cur_x,cur_y,world->indiv_at(cur_x, cur_y)->fitness(),count);
+
 /*        if (268 == x*grid_height+y)
             printf("CPU Local SUM Fit %e -- Fitness %e\n",sum_local_fit,local_fit_array[count]);*/
         count++;
@@ -1093,6 +1095,7 @@ Individual *Selection::do_local_competition (int16_t x, int16_t y) {
     case FITNESS_PROPORTIONATE : {
       for(int16_t i = 0 ; i < neighborhood_size ; i++) {
         probs[i] = local_fit_array[i]/sum_local_fit;
+         // if (0 == x*grid_height+y) printf("%d : %e %e\n",i,local_fit_array[i],sum_local_fit);
       }
 
       break;
@@ -1104,6 +1107,11 @@ Individual *Selection::do_local_competition (int16_t x, int16_t y) {
   }
 
   // pick one organism to reproduce, based on probs[] calculated above, using roulette selection
+    /*bool verbose = false;
+    if (2 == x*grid_height+y) {
+        printf("PRNG CPU\n");
+        verbose = true;
+    }*/
   int16_t found_org = world->grid(x,y)->reprod_prng_->roulette_random(probs, neighborhood_size);
 
   int16_t x_offset = (found_org / selection_scope_x_) - 1;
@@ -1113,9 +1121,13 @@ Individual *Selection::do_local_competition (int16_t x, int16_t y) {
   delete [] sort_fit_array;
   delete [] initial_location;
   delete [] probs;
-/*    world->grid(x,y)->probs = probs;
-    world->grid(x,y)->local_fit_array = local_fit_array;
-    world->grid(x,y)->sum_local_fit = sum_local_fit;*/
+
+    //world->grid(x,y)->probs = probs;
+    //world->grid(x,y)->local_fit_array = local_fit_array;
+    //world->grid(x,y)->sum_local_fit = sum_local_fit;
+
+    exp_m_->simd_individual->next_generation_reproducer_[x*grid_height+y] = ((x+x_offset+grid_width)  % grid_width)*grid_height+
+                                            ((y+y_offset+grid_height) % grid_height);
 
   return world->indiv_at((x+x_offset+grid_width)  % grid_width,
                              (y+y_offset+grid_height) % grid_height);
-- 
GitLab