Tasked componet generates different (inconsistent) results

Hello,

This is my first post to the forum so might sound a bit not so professional in regards programming terms and concepts.
I’m developing a system for managing real tree branches and one of the components has to split a mesh in parts. It creates a bounding box of the branch, a dozen of surfaces along a line and then after converting the surfaces to meshes I use the Mesh.Split() command. The thing is I made this component multi-threaded and when using tasks as by the official example on the Mcneel site the results are always different and less accurate than the single threaded solution. The code I use is the same for both. Anyone has and idea as to why this is happening? Also it is not very clear what is happening when all threads finish? When is the final data assigned to the output parameters? It seems as if the next components do not get all data and recomputing the solutions sometimes fixes the problem. Is there something code wise I should be doing? Expiring does not work.

BranchSlicerComponent.cs (20.1 KB)

Tasked run #1:

Tasked run #2:

Single thread - shows normal behaviour:

Hi @ankere

  • Did you try this in Rhino WIP?

MeshSplit is completely rewritten there, and the version for Rhino 5/6 will not get major updates in normal Service Releases.

Thanks,

Giulio


Giulio Piacentino
for Robert McNeel & Associates
giulio@mcneel.com

Thanks for the reply Giulio,
Unfortunately, I’m part of an academic environment and using beta software is not the best solution to achieve results. I will consult with my supervisors if I can use WIP version on the lab computers.

Nevertheless I also confirmed while debugging that results are sent to the output parameters before all threads finish. Is there an elegant way to tell the component to wait for all results before they are sent further?

Then, there might also be some problem in the implementation. As I am not super-informed on Grasshopper parallelized components, so I’m forwarding this request to @stevebaer and @DavidRutten.

I also remember that we discussed Mesh.Split a few months ago. We realized that the old non-WIP implementation of Mesh.Split was not guaranteed to be thread safe.

Please let me know when/if you have updates on Rhino WIP.

Thanks,

Giulio


Giulio Piacentino
for Robert McNeel & Associates
giulio@mcneel.com

How did you confirm this? I wouldn’t expect this to happen and am trying to get a better understanding of what you are seeing

Hello Steve,
The next components get lists with less elements than expected(or than the normal single thread) and throw exceptions. Recomputing does help but not always. It seems the exception comes from the SetData()? or I might be totally wrong. Here are two pictures:

This is the error run that says NullReference although there is data in Centrelines in all cases as I have taken care of the constructor of class handling the results.

public class SolveResults
{
    public SolveResults()
    {
        Centrelines = new List<Polyline>();
        Edges = new List<List<Polyline>>();
        Errors = new List<string>();
    }
    public List<Polyline> Centrelines { get; set; }
    public List<List<Polyline>> Edges { get; set; }
    public List<string> Errors { get; set; }
    public BoundingBox BBox { get; set; }
}

Next is the run before the exception and as can be seen the data in each polyline is around 10-18 points as it should be.

Here is also a trace if it can help:

System.NullReferenceException
HResult=0x80004003
Message=Object reference not set to an instance of an object.
Source=Grasshopper
StackTrace:
 at Grasshopper.Kernel.Types.GH_Curve..ctor(Curve curve)
 at Grasshopper.Kernel.GH_Convert.ToGeometricGoo(Object data)
 at Grasshopper.Kernel.Parameters.Param_Geometry.PreferredCast(Object data)
 at Grasshopper.Kernel.GH_Param`1.Cast_Object(Object data)
 at Grasshopper.Kernel.GH_Param`1.AddVolatileDataList(GH_Path path, IEnumerable list)
 at Grasshopper.Kernel.GH_Component.GH_StructureIterator.SetDataList(Int32 index, IEnumerable list, Int32 itemIndexOverride)
 at MakeCentreLines.MakeCentreLinesComponent.SolveInstance(IGH_DataAccess DA) in...\MakeCentreLines\MakeCentreLinesComponent.cs:line 147
 at Grasshopper.Kernel.GH_Component.Solution_Compute_MixedAccess(GH_StructureIterator it)

Did you have a chance to try this in V7? I would be good to know if you get different results

I tried today and at first glance it appears to be working but then in the next components it does not behave as expected. This code for one piece of the mesh would never return null (usually at k=0?) as naked edges in V6 but now it does several times:

 int dmc = mp.DisjointMeshCount;
 Mesh[] mpPieces = mp.SplitDisjointPieces();

     for (int k = 0; k < dmc; k++)
     {
         Polyline[] naked = mpPieces[k].GetNakedEdges();
     }

If this does not work my algorithm fails (even if I skip the null edges). It also seems the branch type detection that also uses naked edges fails. Result from run: