Grasshopper

algorithmic modeling for Rhino

Python component taking longer to execute with each subsequent execution

Hey,

I wrote a simple script in the python component to project a bunch of curves onto a brep using the ghpythonlib.parallel feature. The code works. It works faster than the grasshopper component does at the beginning. But as I make changes to the input (or just hit the recompute button) the time it takes to execute increases. This has happened to me with other scripts I've written with the python component. Why does this happen? And how do I fix it? Does python hold onto data from one execution to the next? The only solution I have found is to relaunch Rhino. Even if I copy the component into a fresh grasshopper canvas, the computation time does not return to original.

The images below illustrate the time increase. I simply hit the recompute button between each pass. All inputs remain the same the whole time. There are 6400 curves being projected. I will say that with fewer curves, the increase in time is nonexistent or perceivable. (I have 24 GB RAM and it is did not even reach 50% of usage during the tests)

My python code:

import ghpythonlib.components as ghcomp
import ghpythonlib.parallel

def project (tempc):
tempresult=ghcomp.Project(tempc,B,D)
return tempresult

a=ghpythonlib.parallel.run(project,C,True)

I have attached the GH file with the inputs internalized if anyone wants to try for themselves.

Pass 1= 444ms

Pass 5= 610ms

Pass 10= 908ms

Pass 15= 1.2s

Pass 20= 1.4s

Views: 901

Attachments:

Replies to This Discussion

Hi Lawrence,

This is the issue with ghpythonlib.components module. Mcneel folks will probably fix this in the next couple of months. Until then you would have to use the direct Curve.ProjectToBrep method instead of ghcomp one. Check the attached file.

Attachments:

Thanks, I will await the fix then. Hopefully it comes soon. I am unfamiliar with the Rhino.geometry.curve... format (I see people using this but always stuck to ghcomp since it was similar to grasshopper). Why is it that we could not just "return crvs", but have to "return [crv for crv in crvs]". Doesn't project to brep produce only one crv?

You can have one curve, and one brep, but this curve when projected to brep, could be "broken" into a couple of curves. This is the reason why some methods (Curve.ProjectToBrep being on of them) return a list.
The way ghpythonlib.parallel.run function works is that it returns a list of objects (curves in this case) for each call of your "project" function. In case you set the third argument of the ghpythonlib.parallel.run function to "True" all these lists would be merged into one single list. The problem is that upper mentioned Curve.ProjectToBrep method does not really return a list, but something similar: a typed array. This typed array could not be merged into one single typed array if you set the third argument of the ghpythonlib.parallel.run function to "True". This is why I basically made a new regular python list from from every single typed array Curve.ProjectToBrep method returned using list comprehensions. I could have also just used a list() function instead to "convert" the typed curve array to a regular python list:

Instead of:

return [crv for crv in crvs]

used:

return list(crvs)

Attachments:

Thanks for the explanation. I tried to find out if crvs was a list by len(crvs) and it said 1, which is why I was so confused. While I still have you here, I was trying to project a point onto a brep(loft surface) using rhino common, but I ran into an error (Runtime error (ArgumentTypeException): expected IEnumerable[Brep], got Brep). What is the difference between an IEnumberable[Brep] and a single referenced brep?

import Rhino
import ghpythonlib.parallel

def project (_p):
temp=Rhino.Geometry.Intersect.Intersection.ProjectPointsToBreps(g,_p,d,.001)
return temp

a=ghpythonlib.parallel.run(project,p,True)

Attachments:

You can use some built in python functions on typed arrays too (len() being one of them). The reason why you got "1" is because your current definition projects one curve per "project" function call.
So you would have got "1" even if you call it on a regular python list:

NETcrvsA = Rhino.Geometry.Curve.ProjectToBrep(_c,B,D,tol)
print len(NETcrvsA)   # 1
regularPythonL = [crv for crv in crvs]
print len(regularPythonL)   # 1
return regularPythonL

In python: "IEnumberable" is a regular python list, or a typped list - .NET list, or a .NET array.
You wouldn't need the last two except in few cases, so basically when IEnumerable is required, you could supply a regular python list.


For this current method, it's one of those times when python gets a bit confused.
The error message should be: "expected IEnumerable[Point3d], got list"

What parallel.run function does, is that it takes a list of items(in this case list of points), and then picks one of them and supplies it to the function ("project"). So "_p" in the:

temp=Rhino.Geometry.Intersect.Intersection.ProjectPointsToBreps(g,_p,d,.001)

is a single point, not a list of points. Intersection.ProjectPointsToBreps method requires a list of points as an input (IEnumerable[Point3d]). You can fix this by "putting" your single point into a list:

temp=Rhino.Geometry.Intersect.Intersection.ProjectPointsToBreps(g,[_p],d,.001)

And by the way, the same thing which I mentioned above about the Curve.ProjectToBrep method, is valid for Intersection.ProjectPointsToBreps: it returns a typed array (if a brep has two parallel surfaces(top and bottom) the point would be projected to both of them), so you have to "convert" - or more precisely: create a new regular python list from it.
Check the attached file.

Attachments:

Hi Lawrence,

I noted this down (GH-1761). This appears to be a problem that is at least partially related to the Python interpreter we are using (IronPython). This means that this is not something we can easily fix. However, hopefully relatively soon, we are going to switch to a new version of IronPython, and the newer interpreter might be better at this.

I will check back this conversation once the new interpreter is ready for testing, as GhPython itself might need some adjustments.

Thank you for reporting this.

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

RSS

About

Translate

Search

Videos

  • Add Videos
  • View All

© 2024   Created by Scott Davidson.   Powered by

Badges  |  Report an Issue  |  Terms of Service