discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

When modules are cached?

RP
Ronaldo Persiano
Mon, Oct 28, 2019 2:15 PM

I have a demanding operator that is called many many times, each time with
a different non demanding purpose. I would expect that its operation was
done only for the first time and cached since there is no children or
parameter changes. However, the run time seems to indicate that the
operation is executed at each call.

I have a demanding operator that is called many many times, each time with a different non demanding purpose. I would expect that its operation was done only for the first time and cached since there is no children or parameter changes. However, the run time seems to indicate that the operation is executed at each call.
NH
nop head
Mon, Oct 28, 2019 2:52 PM

I think it is geometry that is cached with key from the module parameters
of the primitive that creates it. Are you sure they are all the same? and
the $ variables?

If the module has a lot of code that takes time to calculate, like a sweep,
then that will be executed each time I think. It is only the geometry that
isn't repeated.

Is this F5 or F6?

What happens if you wrap it with a render?

On Mon, 28 Oct 2019 at 14:16, Ronaldo Persiano rcmpersiano@gmail.com
wrote:

I have a demanding operator that is called many many times, each time with
a different non demanding purpose. I would expect that its operation was
done only for the first time and cached since there is no children or
parameter changes. However, the run time seems to indicate that the
operation is executed at each call.


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

I think it is geometry that is cached with key from the module parameters of the primitive that creates it. Are you sure they are all the same? and the $ variables? If the module has a lot of code that takes time to calculate, like a sweep, then that will be executed each time I think. It is only the geometry that isn't repeated. Is this F5 or F6? What happens if you wrap it with a render? On Mon, 28 Oct 2019 at 14:16, Ronaldo Persiano <rcmpersiano@gmail.com> wrote: > I have a demanding operator that is called many many times, each time with > a different non demanding purpose. I would expect that its operation was > done only for the first time and cached since there is no children or > parameter changes. However, the run time seems to indicate that the > operation is executed at each call. > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
RP
Ronaldo Persiano
Mon, Oct 28, 2019 3:58 PM

I think it is geometry that is cached with key from the module parameters
of the primitive that creates it. Are you sure they are all the same? and
the $ variables?

There is no $ variables and not even parameters in the operator module. It
returns just a simple 2D rectangle so the remaining code should be fast.

If the module has a lot of code that takes time to calculate, like a
sweep, then that will be executed each time I think. It is only the
geometry that isn't repeated.

It is not my case. It involves linear_extrude and projection though.

Is this F5 or F6?

F5

What happens if you wrap it with a render?

No benefit.

> I think it is geometry that is cached with key from the module parameters > of the primitive that creates it. Are you sure they are all the same? and > the $ variables? > There is no $ variables and not even parameters in the operator module. It returns just a simple 2D rectangle so the remaining code should be fast. > If the module has a lot of code that takes time to calculate, like a > sweep, then that will be executed each time I think. It is only the > geometry that isn't repeated. > It is not my case. It involves linear_extrude and projection though. > Is this F5 or F6? > F5 > What happens if you wrap it with a render? > No benefit.
NH
nop head
Mon, Oct 28, 2019 4:04 PM

Projection is very slow because it uses CGAL. I wonder if 2D geometry gets
cached because all the other 2D ops are very fast.

On Mon, 28 Oct 2019 at 15:59, Ronaldo Persiano rcmpersiano@gmail.com
wrote:

I think it is geometry that is cached with key from the module parameters

of the primitive that creates it. Are you sure they are all the same? and
the $ variables?

There is no $ variables and not even parameters in the operator module. It
returns just a simple 2D rectangle so the remaining code should be fast.

If the module has a lot of code that takes time to calculate, like a
sweep, then that will be executed each time I think. It is only the
geometry that isn't repeated.

It is not my case. It involves linear_extrude and projection though.

Is this F5 or F6?

F5

What happens if you wrap it with a render?

Projection is very slow because it uses CGAL. I wonder if 2D geometry gets cached because all the other 2D ops are very fast. On Mon, 28 Oct 2019 at 15:59, Ronaldo Persiano <rcmpersiano@gmail.com> wrote: > > I think it is geometry that is cached with key from the module parameters >> of the primitive that creates it. Are you sure they are all the same? and >> the $ variables? >> > > There is no $ variables and not even parameters in the operator module. It > returns just a simple 2D rectangle so the remaining code should be fast. > > >> If the module has a lot of code that takes time to calculate, like a >> sweep, then that will be executed each time I think. It is only the >> geometry that isn't repeated. >> > > It is not my case. It involves linear_extrude and projection though. > >> Is this F5 or F6? >> > > F5 > >> What happens if you wrap it with a render? >> > > No benefit. > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
RP
Ronaldo Persiano
Tue, Oct 29, 2019 4:50 PM

As illustration of my concerns, please look at the following code:

B();
A(50000) C();

module C() square(10,center=true);

module B() {
projection()
linear_extrude()
intersection(){
projection() rotate([10,20,30]) cube(1000,center=true);
projection() rotate([20,30,10]) cube(1000,center=true);
projection() rotate([30,10,20]) cube(1000,center=true);
square(10,center=true);
}
}

module A(n=0)
for(i=[for(i=0;i<n;i=i+1) i]) rotate(360*i/n) children();

B() is a very expensive way to construct the same geometry (a square) of
C(). None of them have parameters. A() is just a multiple rotation of its
children.

As is, this code runs in 4 sec in my machine. If I exchange the places of
B() and C() in the main code and flush the cache, the code runs in 23 sec.
I would expect that both B() and C() were evaluated once and their cached
geometry were used in both versions of the main code. If was that so, both
main code would have the same runtime.

What objects are cached? When they are cached?

As illustration of my concerns, please look at the following code: B(); A(50000) C(); module C() square(10,center=true); module B() { projection() linear_extrude() intersection(){ projection() rotate([10,20,30]) cube(1000,center=true); projection() rotate([20,30,10]) cube(1000,center=true); projection() rotate([30,10,20]) cube(1000,center=true); square(10,center=true); } } module A(n=0) for(i=[for(i=0;i<n;i=i+1) i]) rotate(360*i/n) children(); B() is a very expensive way to construct the same geometry (a square) of C(). None of them have parameters. A() is just a multiple rotation of its children. As is, this code runs in 4 sec in my machine. If I exchange the places of B() and C() in the main code and flush the cache, the code runs in 23 sec. I would expect that both B() and C() were evaluated once and their cached geometry were used in both versions of the main code. If was that so, both main code would have the same runtime. What objects are cached? When they are cached?
RP
Ronaldo Persiano
Wed, Oct 30, 2019 5:42 PM

I would expect that both B() and C() were evaluated once and their cached
geometry were used in both versions of the main code. If was that so, both
main code would have the same runtime.

Perhaps I have a wrong understanding on how cache is done or works. Any
clue on that is welcome.

> > I would expect that both B() and C() were evaluated once and their cached > geometry were used in both versions of the main code. If was that so, both > main code would have the same runtime. > Perhaps I have a wrong understanding on how cache is done or works. Any clue on that is welcome. >
M
MichaelAtOz
Thu, Oct 31, 2019 3:27 AM

Congratulations, you discovered a  crash
https://github.com/openscad/openscad/issues/3112  . So do not do
Display_CSG_Products...

In the console B(); A() C(); F5 has:

Parsing design (AST generation)...
Compiling design (CSG Tree generation)...
Compiling design (CSG Products generation)...
Geometries in cache: 8
Geometry cache size in bytes: 2704
CGAL Polyhedrons in cache: 0
CGAL cache size in bytes: 0
Compiling design (CSG Products normalization)...
Normalized CSG tree has 50001 elements
Compile and preview finished.
Total rendering time: 0 hours, 0 minutes, 3 seconds

Then do Design/Display_CSG_Tree. Don't close the Window.

Then change to C(); A() B(); Clear_Cache/F5 which shows:

Compiling design (CSG Tree generation)...
Compiling design (CSG Products generation)...
Geometries in cache: 8
Geometry cache size in bytes: 2704
CGAL Polyhedrons in cache: 0
CGAL cache size in bytes: 0
Compiling design (CSG Products normalization)...
Normalized CSG tree has 50001 elements
Compile and preview finished.
Total rendering time: 0 hours, 0 minutes, 21 seconds

Then do Design/Display_CSG_Tree. Compare the two trees, (if your's is the
same, the scroll bars behave strangely until you scroll a bit).

Note the 50001 elements.
The first has a few more complex elements and 50,000 odd simpler elements.
The second 50,000 odd complex elements.

The tree needs to be parsed to display the image.
I don't think it is cache related.
There are --debug <something> command line options that could show cache
activity, I'd have to guess the right values...


Admin - email* me if you need anything, or if I've done something stupid...

  • click on my MichaelAtOz label, there is a link to email me.

Unless specifically shown otherwise above, my contribution is in the Public Domain; to the extent possible under law, I have waived all copyright and related or neighbouring rights to this work. Obviously inclusion of works of previous authors is not included in the above.

The TPP is no simple “trade agreement.”  Fight it! http://www.ourfairdeal.org/  time is running out!

Sent from: http://forum.openscad.org/

Congratulations, you discovered a crash <https://github.com/openscad/openscad/issues/3112> . So do not do Display_CSG_Products... In the console B(); A() C(); F5 has: Parsing design (AST generation)... Compiling design (CSG Tree generation)... Compiling design (CSG Products generation)... Geometries in cache: 8 Geometry cache size in bytes: 2704 CGAL Polyhedrons in cache: 0 CGAL cache size in bytes: 0 Compiling design (CSG Products normalization)... Normalized CSG tree has 50001 elements Compile and preview finished. Total rendering time: 0 hours, 0 minutes, 3 seconds Then do Design/Display_CSG_Tree. Don't close the Window. Then change to C(); A() B(); Clear_Cache/F5 which shows: Compiling design (CSG Tree generation)... Compiling design (CSG Products generation)... Geometries in cache: 8 Geometry cache size in bytes: 2704 CGAL Polyhedrons in cache: 0 CGAL cache size in bytes: 0 Compiling design (CSG Products normalization)... Normalized CSG tree has 50001 elements Compile and preview finished. Total rendering time: 0 hours, 0 minutes, 21 seconds Then do Design/Display_CSG_Tree. Compare the two trees, (if your's is the same, the scroll bars behave strangely until you scroll a bit). Note the 50001 elements. The first has a few more complex elements and 50,000 odd simpler elements. The second 50,000 odd complex elements. The tree needs to be parsed to display the image. I don't think it is cache related. There are --debug <something> command line options that could show cache activity, I'd have to guess the right values... ----- Admin - email* me if you need anything, or if I've done something stupid... * click on my MichaelAtOz label, there is a link to email me. Unless specifically shown otherwise above, my contribution is in the Public Domain; to the extent possible under law, I have waived all copyright and related or neighbouring rights to this work. Obviously inclusion of works of previous authors is not included in the above. The TPP is no simple “trade agreement.” Fight it! http://www.ourfairdeal.org/ time is running out! -- Sent from: http://forum.openscad.org/
M
MichaelAtOz
Thu, Oct 31, 2019 3:30 AM

I wonder whether collapsing the redundant
group() {
group() {
would improve it somewhat??


Admin - email* me if you need anything, or if I've done something stupid...

  • click on my MichaelAtOz label, there is a link to email me.

Unless specifically shown otherwise above, my contribution is in the Public Domain; to the extent possible under law, I have waived all copyright and related or neighbouring rights to this work. Obviously inclusion of works of previous authors is not included in the above.

The TPP is no simple “trade agreement.”  Fight it! http://www.ourfairdeal.org/  time is running out!

Sent from: http://forum.openscad.org/

I wonder whether collapsing the redundant group() { group() { would improve it somewhat?? ----- Admin - email* me if you need anything, or if I've done something stupid... * click on my MichaelAtOz label, there is a link to email me. Unless specifically shown otherwise above, my contribution is in the Public Domain; to the extent possible under law, I have waived all copyright and related or neighbouring rights to this work. Obviously inclusion of works of previous authors is not included in the above. The TPP is no simple “trade agreement.” Fight it! http://www.ourfairdeal.org/ time is running out! -- Sent from: http://forum.openscad.org/
RP
Ronaldo Persiano
Fri, Nov 1, 2019 6:12 PM

Thank you, Michael, for expending your time on that. I have not gotten any
crash with version 2019.01-RC4. I guess it will depend on the
available memory to display the CSG tree.

As we say in Portuguese,I have shot what I saw and hit what I haven't.
Besides, the code I have presented was a failed attempt to illustrate with
a small code the problem I am having in my original code. Here is a better
illustration although not as simple.

I have devised the following code to find the bounding box of a 2D object:

module bbox()
intersection() {
ext = pow(2,16);
hull() {
translate([ ext,    0]) children();
translate([-ext,    0]) children();
}
hull() {
translate([    0, ext]) children();
translate([    0,-ext]) children();
}
}

It returns the bounding box (a rectangle) of 2D objects with points away
from the origin less than pow(2,15) (or something like that).

It is rather efficient even with complex 2D geometries:

n = 270;

text = S(n);
font = "Palatino Linotype:style=Italic";

// just a complex 2D model
module T() resize([100,0])
text(text,font=font,valign="center",halign="center");

// creates a string with n capital S
function S(n,s="") = n<=0? s: S(n-1,str(s,"S"));

T();

bbx() T();

But things get a bit convoluted when bbx() is called many times even over
the same object:

module complexbbx(p)
intersection(){
render() bbox() children();
bbox() children();
bbox() children();
bbox() children();
bbox() children();
bbox() children();
bbox() children();
bbox() children();
bbox() children();
}

complexbbx([1,1]) T();

This last code requires 18 sec on my machine while a simple call to bbx()
T() requires 2 sec.

In the next code,  bbox() children() is called just once but the
intersection of 9 squares is still done:

module complexbbx2(p)
intersection(){
render() bbox() children();
square([100,10],center=true);
square([100,10],center=true);
square([100,10],center=true);
square([100,10],center=true);
square([100,10],center=true);
square([100,10],center=true);
square([100,10],center=true);
square([100,10],center=true);
}

Now,  complexbbx2([1,1]) T()  requires only 2 sec to run which shows 9
rectangle intersection is negligible when compared to bbox(). It also shows
that the bbox() children() in  complexbbx() is not being cached but instead
computed again and again.

So, the question in this  thread subject remains unanswered. Is there any
way I could enforce that bbox() children() in  complexbbx() be cached?

Thank you, Michael, for expending your time on that. I have not gotten any crash with version 2019.01-RC4. I guess it will depend on the available memory to display the CSG tree. As we say in Portuguese,I have shot what I saw and hit what I haven't. Besides, the code I have presented was a failed attempt to illustrate with a small code the problem I am having in my original code. Here is a better illustration although not as simple. I have devised the following code to find the bounding box of a 2D object: module bbox() intersection() { ext = pow(2,16); hull() { translate([ ext, 0]) children(); translate([-ext, 0]) children(); } hull() { translate([ 0, ext]) children(); translate([ 0,-ext]) children(); } } It returns the bounding box (a rectangle) of 2D objects with points away from the origin less than pow(2,15) (or something like that). It is rather efficient even with complex 2D geometries: n = 270; text = S(n); font = "Palatino Linotype:style=Italic"; // just a complex 2D model module T() resize([100,0]) text(text,font=font,valign="center",halign="center"); // creates a string with n capital S function S(n,s="") = n<=0? s: S(n-1,str(s,"S")); T(); bbx() T(); But things get a bit convoluted when bbx() is called many times even over the same object: module complexbbx(p) intersection(){ render() bbox() children(); bbox() children(); bbox() children(); bbox() children(); bbox() children(); bbox() children(); bbox() children(); bbox() children(); bbox() children(); } complexbbx([1,1]) T(); This last code requires 18 sec on my machine while a simple call to bbx() T() requires 2 sec. In the next code, bbox() children() is called just once but the intersection of 9 squares is still done: module complexbbx2(p) intersection(){ render() bbox() children(); square([100,10],center=true); square([100,10],center=true); square([100,10],center=true); square([100,10],center=true); square([100,10],center=true); square([100,10],center=true); square([100,10],center=true); square([100,10],center=true); } Now, complexbbx2([1,1]) T() requires only 2 sec to run which shows 9 rectangle intersection is negligible when compared to bbox(). It also shows that the bbox() children() in complexbbx() is not being cached but instead computed again and again. So, the question in this thread subject remains unanswered. Is there any way I could enforce that bbox() children() in complexbbx() be cached?
NH
nop head
Fri, Nov 1, 2019 7:43 PM

I think it needs an answer from one of the developers but my guess is that
2D objects are not cached at all. They live in a world of their own with 64
bit fixed point numbers. Most 2D operations are blindingly fast compared to
the very slow 3D CGAL stuff, so it would normally not give much speed
increase to cache them.

On Fri, 1 Nov 2019 at 18:13, Ronaldo Persiano rcmpersiano@gmail.com wrote:

Thank you, Michael, for expending your time on that. I have not gotten any
crash with version 2019.01-RC4. I guess it will depend on the
available memory to display the CSG tree.

As we say in Portuguese,I have shot what I saw and hit what I haven't.
Besides, the code I have presented was a failed attempt to illustrate with
a small code the problem I am having in my original code. Here is a better
illustration although not as simple.

I have devised the following code to find the bounding box of a 2D object:

module bbox()
intersection() {
ext = pow(2,16);
hull() {
translate([ ext,    0]) children();
translate([-ext,    0]) children();
}
hull() {
translate([    0, ext]) children();
translate([    0,-ext]) children();
}
}

It returns the bounding box (a rectangle) of 2D objects with points away
from the origin less than pow(2,15) (or something like that).

It is rather efficient even with complex 2D geometries:

n = 270;

text = S(n);
font = "Palatino Linotype:style=Italic";

// just a complex 2D model
module T() resize([100,0])
text(text,font=font,valign="center",halign="center");

// creates a string with n capital S
function S(n,s="") = n<=0? s: S(n-1,str(s,"S"));

T();

bbx() T();

But things get a bit convoluted when bbx() is called many times even over
the same object:

module complexbbx(p)
intersection(){
render() bbox() children();
bbox() children();
bbox() children();
bbox() children();
bbox() children();
bbox() children();
bbox() children();
bbox() children();
bbox() children();
}

complexbbx([1,1]) T();

This last code requires 18 sec on my machine while a simple call to bbx()
T() requires 2 sec.

In the next code,  bbox() children() is called just once but the
intersection of 9 squares is still done:

module complexbbx2(p)
intersection(){
render() bbox() children();
square([100,10],center=true);
square([100,10],center=true);
square([100,10],center=true);
square([100,10],center=true);
square([100,10],center=true);
square([100,10],center=true);
square([100,10],center=true);
square([100,10],center=true);
}

Now,  complexbbx2([1,1]) T()  requires only 2 sec to run which shows 9
rectangle intersection is negligible when compared to bbox(). It also shows
that the bbox() children() in  complexbbx() is not being cached but instead
computed again and again.

So, the question in this  thread subject remains unanswered. Is there any
way I could enforce that bbox() children() in  complexbbx() be cached?


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

I think it needs an answer from one of the developers but my guess is that 2D objects are not cached at all. They live in a world of their own with 64 bit fixed point numbers. Most 2D operations are blindingly fast compared to the very slow 3D CGAL stuff, so it would normally not give much speed increase to cache them. On Fri, 1 Nov 2019 at 18:13, Ronaldo Persiano <rcmpersiano@gmail.com> wrote: > Thank you, Michael, for expending your time on that. I have not gotten any > crash with version 2019.01-RC4. I guess it will depend on the > available memory to display the CSG tree. > > As we say in Portuguese,I have shot what I saw and hit what I haven't. > Besides, the code I have presented was a failed attempt to illustrate with > a small code the problem I am having in my original code. Here is a better > illustration although not as simple. > > I have devised the following code to find the bounding box of a 2D object: > > module bbox() > intersection() { > ext = pow(2,16); > hull() { > translate([ ext, 0]) children(); > translate([-ext, 0]) children(); > } > hull() { > translate([ 0, ext]) children(); > translate([ 0,-ext]) children(); > } > } > > > It returns the bounding box (a rectangle) of 2D objects with points away > from the origin less than pow(2,15) (or something like that). > > It is rather efficient even with complex 2D geometries: > > n = 270; > > text = S(n); > font = "Palatino Linotype:style=Italic"; > > // just a complex 2D model > module T() resize([100,0]) > text(text,font=font,valign="center",halign="center"); > > // creates a string with n capital S > function S(n,s="") = n<=0? s: S(n-1,str(s,"S")); > > T(); > > bbx() T(); > > > But things get a bit convoluted when bbx() is called many times even over > the same object: > > module complexbbx(p) > intersection(){ > render() bbox() children(); > bbox() children(); > bbox() children(); > bbox() children(); > bbox() children(); > bbox() children(); > bbox() children(); > bbox() children(); > bbox() children(); > } > > complexbbx([1,1]) T(); > > > This last code requires 18 sec on my machine while a simple call to bbx() > T() requires 2 sec. > > In the next code, bbox() children() is called just once but the > intersection of 9 squares is still done: > > module complexbbx2(p) > intersection(){ > render() bbox() children(); > square([100,10],center=true); > square([100,10],center=true); > square([100,10],center=true); > square([100,10],center=true); > square([100,10],center=true); > square([100,10],center=true); > square([100,10],center=true); > square([100,10],center=true); > } > > > Now, complexbbx2([1,1]) T() requires only 2 sec to run which shows 9 > rectangle intersection is negligible when compared to bbox(). It also shows > that the bbox() children() in complexbbx() is not being cached but instead > computed again and again. > > So, the question in this thread subject remains unanswered. Is there any > way I could enforce that bbox() children() in complexbbx() be cached? > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >