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.

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:

Do you think it is possible to make something to ensure the split is thread safe in Rhino 6? Is there any chance of getting that function to be thread safe in future service release?

I was thinking about locking the split but then the result is just as bit faster than the single thread:

Monitor.Enter(_lock);
Mesh[] meshParts = M.Split(cut_planes);
Monitor.Exit(_lock);

Or maybe I should define my own split function? Is there some reference or code I can check for that?

1 Like

I think there’s no point to make things multithreaded if there’s a megalock. It all resorts to single thread anyways. There’s no plan to make major improvements to mesh split in Rhino 6 at this point.

Thank you Giulio,

I understand that you will not make any changes to v6 but as there is not clear release date on 7 and I cannot use betas I really need to make this work fast with version 6 for now. I’m planning on splitting hundreds of elements and even if I we have Ryzen 9 and Nvidia 2080Ti at lab its not fast enough when I use only one core and my GPU is Idle.

Any further suggestions are welcome.

For V6, I don’t know how to help. Try V7. I am unaware of other things I can do, also.

Thank you for your work Giulio,
I think I was a bit too emotional at that time. Its a tough time.

1 Like

Hello again @piac

I fixed all the code of my plugin to work fine for R7 but then after the latest updates ( 7.5 + ) it is totally messed again internally. Is there some new way cut mesh works that is different from 7.5?
Here is an example of the strange vertical lines that should not be there:


and more clear

how it should be:

Currently I am using the single argument method, but maybe should specify tolerance but that would require the other parameters as well? I currently have a multitask component so dont want to run this in different thread again:

Hi Anton, did you try 7.10 o 7.11? 7.5 is very old…
Also, if after updating you still get this problem, I’ll have to get a sample with code and geometry in order to be able to repeat the problem!

Thanks,

Giulio


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

Yes I tried both 7.10 and 7.11 which seem to not work as expected. I do not know exactly when this stopped working as at lower density (number of slices) works even now. I did development on 7.0 and 7.2 and I believe tested again on 7.5 with density of 24, 30, or 60+ when it was working as expected.

As this is still ongoing research I can’t share the code to wider public yet but I will send you a message with samples and code if that’s fine with you.

@piac Is there any info on what is really happening? Is it related to RhinoCommon or other possible problem? If there is no easy fix guess I have to roll back my Rhino.

Hi Anton @ankere, given the circumstances with code not being sharable and the lack of a repeatable case, I think all we can try is to organize a meeting where you show the problem. Please keep in mind that multithreading can be intricate. Even the fact that Rhino 7 is faster than Rhino 6 might cause some problems to show up.

Are tomorrow (Tuesday) or the next day (Wednesday) good days for you? I am in the CET timezone.

Thanks,

Giulio


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

Hi,

I’m going to be busy today and tomorrow with a presentation. Would it be possible to have the meeting on 4th or 5th? I am in Japanese time so I can do anything from your morning to around 13:00h. How about 10:00 your time if you are free?

Best

Sure, that would work. I can be on Zoom, Skype, or Google Meet.
Please @-mention me any time you write a message so I get a notification.

1 Like