FYI: ConcurrentBag fooled me for hours - why?

OK, I just recovered from a phenomenon (bug?) which really had me puzzled. I was collecting mesh edges, and I was doing so in parallel using a ConcurrentBag list-type to store my edge info. But I kept getting my edge lines flipped in arbitrary directions. I tried to skip the Parallel.For-loop and revert to a regular for-loop, but edges kept flippin’.

After “many hours” of debugging I finally tried to replace the ConcurrentBag (which I had introduced together with the Parallel.For-loop) with a regular List and voila! The edges (directions) started to behave again!

Just to demonstrate what I did:

    // **Skipping parallel & ConcurrentBag fixed the flippin' edges!**

    //var edge_segment_info= new ConcurrentBag<MeshEdgeIndexInfo>();
    var edge_segment_info= new List<MeshEdgeIndexInfo>();

    for (int i = 0; i < _TE.Count; i++)
    //Parallel.For(0, _TE.Count, i =>
      var connectedFaces = _TE.GetConnectedFaces(i);
      if (connectedFaces.Length == 1) // = is naked
        // Edge Vertice info
        var edge_segm = new MeshEdgeIndexInfo(i); // sets .TE_I = i
        var pair = _TE.GetTopologyVertices(i);
        edge_segm.TV_I = pair.I;
        edge_segm.TV_J = pair.J;

Q: How is it possible that the edges could get messed up due to using ConcurrentBag?

In any case, back to using arrays.

// Rolf

I found that using the combination ConcurrentBag + regular for-loop can make the data go bananas.

Edit: Nope, edges are still flipping
ConcurrentBag + Parallel.For works though (of course)

I’ve never seen this behavior before today.

// Rolf

Hi Rolf

… probably a stupid question …
Are the indices in the IndexPair returned by GetTopologyVertices() supposed to be ordered ?

1 Like

Hi @emilio,

Hm. Good question. They should be ordered, and once the edge is grabbed the “I” and “J” properties if the Vertices pair should be ordered as well. But for some reason they keep flipping the order.

The edge always stays the same (mesh.TopologyEdges.EdgeLine(i)), nothing strange there, and the vertices belongs to its edge index (mesh.TopologyEdges.GetTopologyVertices(i)) but the vertices seems to flip arbitrarily.

        var pair = _TE.GetTopologyVertices(i);
        edge_segm.TV_I = pair.I;   // <-- flips ... sometimes
        edge_segm.TV_J = pair.J;   // <-- flips ... sometimes

I just tried to restore Parallel.For with ConcurrentBags, but edge directions flips every now and then.

I’m really at loss with this. :worried:

// Rolf

1 Like

Now I’m spotting something. It is actually a subsequent recursive method which doesn’t return consistent results.

That is strange in itself, namely that a sequential method (no parallel involved) gives inconsistent results between runs, but at least I have the heavy Parallel part stable.

So, edges an their vertices really do stay ordered (…), anything else would of course have caused a “perfect storm” here on the forum… :slight_smile:

However, I now know where to dig deeper.

// Rolf

RhinoCommon doesn’t have any guarantee on thread safety, which might be an issue.

In the threaded part I’m only reading (and temporarily padding data into my own data structures) and thread safety is about writing safely, so in this case I found out that there’s actually no problem with the threaded part (instead it is something with a recursive algorithm called later in the code. I’m still debugging. Creepy one this…).

// Rolf

I’m moving this into Rhino Developer since it seems to be a purely RhinoCommon/.NET question.