Choosing a minimum among lows using Parallel.ForEach

I am new to C #, Parallel.ForEachand .NET in general. I want to parallelize a search involving thousands of places. For each location, I compute a large distance in a circle. This is a calculation that I want to extend to different cores. My question is: how to do this if I have only one streaming local variable, as in this example MSPL TPL ? As a result, I have looked at Interlockedand saw his options Add, CompareExchange, Decrement, Exchange, Incrementand Read, but I do not just add, increase, decrease, or testing for equality. I want to return an object on several threads running in parallel, with the shortest commondistance. My gut says it should be easy, that I have to create a small object that wraps Locationand distance, but how can I get the best answer from each stream, and then choose the shortest distance between them? Here is a non-parallel version:

Location findClosestLocation(Location myLocation, List<Location> allLocations)
{
  double closest = double.MaxValue;
  Location closestLoc = null;
  foreach (Location aLoc in allLocations)
  {
    if (aLoc != myLocation)
    {
      double d = greatCircle(myLocation, aLoc);
      if (d < closest)
      {
        closest = d;
        closestLoc = aLoc;
      }
    }
  }
  return closestLoc;
}

I saw a DDJ blog post that seemed to offer good advice, but I wondered if this was the best advice. I see the author sorting through arrays and wondering if there is a more functional way to do this. In a functional world, I would use map, lambdaand min.

+5
source share
1 answer

- PLINQ:

Location findClosestLocation(Location myLocation, List<Location> allLocations)
{
     return allLocations
               .AsParallel()
               .Min(location => greatCircle(myLocation, location));
}

, , . , Parallel. - , . , .

Parallel.ForEach, . :

Location findClosestLocation(Location myLocation, List<Location> allLocations)
{
  double closest = double.MaxValue;
  Location closestLoc = null;
  object sync = new object();

  Parallel.ForEach<Location, Tuple<double,Location>(
      allLocations,
      () => new Tuple(double.MaxValue, null),
      (location, loopState, localState) =>
      {
          double d = greatCircle(myLocation, aLoc);
          if (d < localState.Item1)
              return new Tuple(d, aLoc);
          else
              return localState;
      },
      localState =>
      {
          lock(sync)
          {
              if (localState.Item1 < closest)
              {
                  closest = localState.Item1;
                  closestLoc = localState.Item2;
              }
          }
      }
  );
  return closestLoc;
}

. , , .

+10

All Articles