2

I am attempting to parallelize a for-loop that runs within a genetic algorithm using OpenMP and am encountering a segfault, and I'm assuming its a thread-safety issue.

What is unclear to me, and perhaps may be a lack of knowledge on my part for C++ threading, is that there should not be any cross-talk going on between variables as I can see it.

For reference, here is the loop that I am parallelizing:

void GA::evaluate(double cfgNRG, double cfgNA, double cfgAC)
{
  // Evaluate individuals in the population:
  #pragma omp parallel num_threads(3)
  {
    #pragma omp for
    for(unsigned int indv = 0; indv < population_.size(); ++indv)
    {
      std::cout << "Individual [" << indv << "]" << std::endl;
      // Retrieve the individual:
      Genome& genome = population_[indv];

      // Have we already evaluated this individual?
      if(genome.is_evaluated()) {
          continue;
      }

      // Evaluate individual:
      {
        GA::SimulationResults results = evaluate(genome, cfgNRG, cfgNA, cfgAC);
        genome.set_trace(results.first);
        genome.set_fitness(results.second);
      }
    }
  }

  // Sort the population:
  sort_population();
}

The issue comes within the internal evaluate function. However, the only variable acted upon is the genome variable that is pulled out of the population_ vector. I had thought that acting upon a single variable (that does not interact with anything else until the end of the for loop) would be thread-safe, and yet, I receive the segfault. If I define the evaluate function to be critical, the program works as normal (and also, the program works just fine without parallelizing).

My one thought was that the threads were not being joined at the end of the loop, however according to the documentation a join should automatically occur on the closing brace after my parallel declaration.

erik
  • 3,810
  • 6
  • 32
  • 63
  • 1
    Yes, acting on a single (not shared) variable is thread-safe. Are you 100% sure that `evaluate` (or any of the functions called by `evaluate`) does not access ANY member-variable of `GA`, or any global variables? And that none have any static variables? You could also try valgrind's drd (but be aware to read the section about OpenMP), or Intel's Inspector (if you have access to it). – Sedenion Jul 10 '14 at 16:13
  • I am still going through the code, but at this point it looks like I'm not accessing any other member of GA. However, there are a bunch of calls to pull in instances of `boost::shared_ptr`s...would grabbing instances of those cause an issue? – erik Jul 10 '14 at 16:44
  • Though since I'm not writing to the `shared_ptr` (according to [this](http://stackoverflow.com/questions/692438/is-boost-shared-ptr-xxx-thread-safe)) and only reading, I suppose that should also be thread-safe. – erik Jul 10 '14 at 17:19
  • `std::cout << ...` is not thread safe. That could conceivably cause a segfault down the line, but I don't know how likely it is or if there is some other issue. – Nicu Stiurca Jul 10 '14 at 18:23
  • Does `population_` change in any way during the call to `evaluate`? Because that could invalidate `genome` references in other threads. – Nicu Stiurca Jul 10 '14 at 18:27
  • I can remove the cout and try...`population_` does not change. My guess is its going to be something minor buried deep within my codebase that I haven't posted. – erik Jul 10 '14 at 19:24
  • @SchighSchagh I doubt that `std::cout` is the problem, although of course it is possible. The only problem I noticed so far (in practice) with `cout` and multithreading were jumbled lines. – Sedenion Jul 11 '14 at 06:27
  • I noticed the same, and removing them actually did not help. Can public/private members of subclasses have any effect? For example, class `Genome` has a private member `Trace`, which is updated throughout execution of the `evaluate` function. However, it is tied directly to that particular `genome` and no other. – erik Jul 11 '14 at 18:02
  • `My guess is its going to be something minor buried deep within my codebase that I haven't posted.` In that case, we can't help you. Try posting an SSCCE. – Nicu Stiurca Jul 11 '14 at 19:17
  • Or try using valgrind drd/Intel Inspector – Sedenion Jul 12 '14 at 17:53
  • Ok, I'll give valgrind a shot. If I can't find anything, I'll post some more code. I hesitate, as the `evaluate` function gets to be quite complex to try and post. – erik Jul 14 '14 at 01:47
  • Be sure to read the section about OpenMP; otherwise you get'll a lot of false positives. – Sedenion Jul 14 '14 at 07:37

0 Answers0