Python code developement: Shape.fuse() performance

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
Post Reply
MMue
Posts: 4
Joined: Thu Mar 16, 2023 7:39 am

Python code developement: Shape.fuse() performance

Post by MMue »

Hello everyone,

i am using FreeCAD to create a statistical shape in python 3.8.5. In the course of the programm i create several shapes and save those into a list. In the end i try to fuse the shapes by using:

creating Shapes:

Code: Select all

for i in range()
		for j in range()	
		    P1, P2, P3 = find_vertices(cross_sec_area[i][j],strut_direction[i], triangle_start_position[i][j])
		    P1=App.Vector(np.asarray(P1,dtype=np.float64)) #get edges of triangle
                    P2=App.Vector(np.asarray(P2,dtype=np.float64)) #convert to FreeCAD Vector
                    P3=App.Vector(np.asarray(P3,dtype=np.float64))
                    tri_outline=Part.makePolygon([P1,P2,P3,P1]) #create triangle outline as wire
                    tri_face = Part.Face(tri_outline) #create triangle as surface
                    extrud_vec = App.Vector(np.asarray(strut_direction[i] * length[i] / a,dtype=np.float64))
                    strut_element = tri_face.extrude(extrud_vec)  # extrude triangle along strut direction until next triangle starting point

                    if j == 0:
                        all_strut_element = Part.Shape(strut_element)

                    all_strut_element = all_strut_element.fuse(strut_element)

                if all_strut_element.common(res_cylinder).Length > 0:
                    strut_element_list.append(all_strut_element)
Trying to Fuse:

Code: Select all

    result2 = Part.Shape(strut_element_list[0])
    result2 = result2.fuse(strut_element_list[1:])

Since there are a lot of elements in the list (up to 3000 ) where every element consists of several fuses itself (all in all up to 80.000) the fuse() command takes a very long time (right now 24h, still calculating).

I figured that the elements in the list have to be of ShapeType: Compound and to not fuse element wise to accelerate the fuse() command.

Is there anything else i can do to make this faster?



Thank you all!

Mischa
User avatar
onekk
Veteran
Posts: 6144
Joined: Sat Jan 17, 2015 7:48 am
Contact:

Re: Python code developement: Shape.fuse() performance

Post by onekk »

MMue wrote: Thu Mar 16, 2023 7:47 am Hello everyone,
...

Mischa
It could be relevant to know even FreeCAD (FC for short) version and exact library versions, as there is OCCT library involved and OCCT version could be relevant too.

See maybe:

viewtopic.php?t=2264

for a descriptions of needed steps to supply them.

Take in account however that the work is single threaded, so it may be slow, and that fusion must intersect.

If I could suggest something, you could try to fuse them in much smaller chunks, provided that these chunks will intersect between them, but it is only a guess, as it depends on many variables, like your processor type and processor speed (as FC is mostly single threaded it uses only one core, something will be improved as some developer are working on it but actually it is not implemented yet in many part of FC).

Hope it helps.

Regards

Carlo D.
GitHub page: https://github.com/onekk/freecad-doc.
- In deep articles on FreeCAD.
- Learning how to model with scripting.
- Various other stuffs.

Blog: https://okkmkblog.wordpress.com/
MMue
Posts: 4
Joined: Thu Mar 16, 2023 7:39 am

Re: Python code developement: Shape.fuse() performance

Post by MMue »

Hi Carlo,

thank you for the reply.
my version: FreeCAD0.20.2 (sadly i cant give you details since my desktop version of FreeCAD wont open up)

I've got a workstation to work on:
CPU

AMD EPYC 7F72 24-Core Processor
Basisgeschwindigkeit: 3,19 GHz
Sockets: 2
Virtuelle Prozessoren: 24
Virtueller Computer: Ja

RAM 100,0 GB

Grafics: Nvidia Grid T4-16Q

Maybe python is not using the dedicated grafics and therefore its slower?

I will try your suggestions and will give you feedback :)

Thanks,
Mischa
User avatar
onekk
Veteran
Posts: 6144
Joined: Sat Jan 17, 2015 7:48 am
Contact:

Re: Python code developement: Shape.fuse() performance

Post by onekk »

MMue wrote: Thu Mar 16, 2023 10:01 am ...
Maybe python is not using the dedicated grafics and therefore its slower?
...

FreeCAD is using OpenGL to chow things, it is not using any of the "graphic acceleration hardware".

I don't know if OpenGL could be configured to use "graphic acceleration hardware", but from what I've seen probably not.

But a little consideration, "Graphics acceleration hardware" is made to process triangulations, for visualization purpose, or probably for "animation" purpose.


Here it is the OCCT core that is processing things, so if OCCT (the CAD engine) is not using multicore capabilities, you are stuck with only 1 Core and thing are slow, but I don't know internal working of OCCT to make affirmations, so take it as a "possibility" not as a "truth".

Regards

Carlo D.
GitHub page: https://github.com/onekk/freecad-doc.
- In deep articles on FreeCAD.
- Learning how to model with scripting.
- Various other stuffs.

Blog: https://okkmkblog.wordpress.com/
MMue
Posts: 4
Joined: Thu Mar 16, 2023 7:39 am

Re: Python code developement: Shape.fuse() performance

Post by MMue »

Hi Carlo,

i am not using FreeCAD to show things.
Actually i am only using the FreeCAD lib in python to generate the geometry and export it as a ".stp" file.

So from your suggestions i think graphics don't play a role.

Best regards,
Mischa
edwilliams16
Veteran
Posts: 3106
Joined: Thu Sep 24, 2020 10:31 pm
Location: Hawaii
Contact:

Re: Python code developement: Shape.fuse() performance

Post by edwilliams16 »

FreeCAD's Open Cascade core has a parallel option for boolean unions. I have no idea whether FreeCAD takes advantage of this.
If not, python apparently has the ability to create multi-processing scripts. In which case, I would consider building an octree of your objects using their bounding boxes and then fusing them depth first. Once working serially you can parcel out the fuses to processors.

https://dev.opencascade.org/doc/occt-7. ... gorithms_7
https://www.researchgate.net/publicatio ... y_Computer

From experience, making parallel scripts (I did in a language preceding python, optimized for numerical efficiency.) can be tricky - but this is about as straightforward as it gets.

@MMue
MMue
Posts: 4
Joined: Thu Mar 16, 2023 7:39 am

Re: Python code developement: Shape.fuse() performance

Post by MMue »

Dear Carlo,

i tried checking the intersections before boolean operation but i have a feeling i did this in the least performant way:
The checking of the intersections took longer than the fusion before.

Code: Select all

    
    print("...looking for intersecting struts...")
    dummy_elements = []
    with alive_bar(len(strut_element_list), force_tty=True) as bar:
        for i in range(0, len(strut_element_list)):
            if result2.common(strut_element_list[i]).Length > 0:
                dummy_elements.append(strut_element_list[i])
            bar()
    strut_element_list.remove(dummy_elements)
    print("...fuse dummy struts...", datetime.now())
    with alive_bar(1, force_tty=True) as bar:
        result2 = result2.fuse(dummy_elements)
        bar()
    print("...fuse remaining struts...", datetime.now())
    with alive_bar(1, force_tty=True) as bar:
        result2 = result2.fuse(strut_element_list)
        bar()

@edwilliams16 Thank you for the suggestion. I did multi-processing on python before (not in this context). Is there a function to automatically build the octrees or do i have to select the elements manually?

Thanks for all your helps,

Mischa
edwilliams16
Veteran
Posts: 3106
Joined: Thu Sep 24, 2020 10:31 pm
Location: Hawaii
Contact:

Re: Python code developement: Shape.fuse() performance

Post by edwilliams16 »

MMue wrote: Fri Mar 17, 2023 8:02 am
@edwilliams16 Thank you for the suggestion. I did multi-processing on python before (not in this context). Is there a function to automatically build the octrees or do i have to select the elements

Mischa
Somebody has probably done something you can use, but You’ll need to search.
jbi
Posts: 117
Joined: Sun Apr 24, 2016 3:28 pm

Re: Python code developement: Shape.fuse() performance

Post by jbi »

If this is only for displaying purposes to have a single element in the tree which you can handle you could do also

Code: Select all

Part.Compound([list of solids])
Depends what you want.
heda
Veteran
Posts: 1348
Joined: Sat Dec 12, 2015 5:49 pm

Re: Python code developement: Shape.fuse() performance

Post by heda »

afaict your script is not a runnable mvp.

anyhow, seems like you are working with tri's, kind of doubt that fusing prism's of tri's up to the tune of 80k prisms is a pragmatic approach.

maybe do a bit more math and stay in the tri/mesh world which always is (and will be) a faster world.

afaik, the only meaningful way to increase looped fusing is chunking it. the chunking you yourself have to arrange and govern, and you could then fire up multiple fc instances to get true multi-core processing (at expense of large initial start-up time, and slow interproccess communication, but if you are anyways on hours that won't matter much).

viewtopic.php?p=640180#p640180
Post Reply