1

I have multiple objects (say circles) inside a square grid. Each circle is surrounded by grid vertices (say 4). Two circles can have the same surrounding grid vertices. Each circle updates its surrounding grid vertices.

I try locking the vertices, but I get an incorrect result when I run the code in parallel. Any ideas where the code could be flawed?

Any other approach I could use to execute the code correctly in parallel?

Parallel.ForEach(ArrayOfCircles, circle =>    
{
    for (var i = 0; i < circle.SurroundingVertices.Count; i++)
    {
        var n = circle.SurroundingVertices.ElementAt(i);

        lock (n)
        {
           n.ContactNormal[0] += circle.Volume;
           n.ContactNormal[1] += circle.Volume;
        }
    }
});
bibi
  • 3,671
  • 5
  • 34
  • 50
  • Without any more information, it looks to be okay. If you replace `Parallel.ForEach(ArrayOfCircles, circle => ` with *exactly* `foreach(var circle in ArrayOfCircles)`, does it work? (change nothing else!) – Rob Mar 10 '16 at 02:26
  • Yes, I am comparing Parallel.ForEach and foreach and notice a minor difference in the two. – Vibhav Bisht Mar 10 '16 at 02:30
  • What is `ContactNormal`? Can it be shared between vertices? – Rob Mar 10 '16 at 02:31
  • @Beast: What kind of "minor difference"? Could it be that you're just seeing different degrees of cumulative floating point "drift" cause by different order of execution? – spender Mar 10 '16 at 02:34
  • Also, can we see the definition of `Vertex`? – Rob Mar 10 '16 at 02:42
  • @Rob - No. Each vertex has its own ContactNormal. – Vibhav Bisht Mar 10 '16 at 02:47
  • @spender - It is possible. There are multiple division and multiplication operations executing in the code of which I posted just one snippet. Also, the same code is executed a 1000 times. The exact difference is -2.6835792335329 (not parallel) and -2.6835791463085 (in parallel) – Vibhav Bisht Mar 10 '16 at 02:47
  • @Rob - `Vertex` is a class containing properties like `ContactNormal` . `SurroundingVertices` is a List of vertices – Vibhav Bisht Mar 10 '16 at 02:57
  • Thank you guys. I will further scrutinize on my own. I just wanted to confirm my implementation of lock. – Vibhav Bisht Mar 10 '16 at 03:03
  • Is it not possible that the order in which the doubles are added could cause a difference, because of their nature – sQuir3l Mar 10 '16 at 05:39

1 Answers1

0

After extreme scrutiny, I realized that the error stems from cumulative floating point drift. The drift is magnified from the fact that the complete system is highly non-linear.

I came to this conclusion by eliminating drifts through converting all floats to decimals. See Limiting double to 3 decimal places.

Community
  • 1
  • 1