New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Exploration of even lazier unions (bubbling through modules & transforms) for large speed ups #3637
base: master
Are you sure you want to change the base?
Conversation
…ildren lists Code is a bit horrible for now, but this works great with lazy-module
…ns or not) This could have two adverse effects: - Create more work down the line, e.g. transforming two heavy solids which intersection results in a very small one (that would have been cheaper to intersect). The benefits of potentially saving unions can be huge, though, esp. for complex patterns. - It could potentially defeat some of the caching logic? (TBC)
…p hull from rewrite logic)
Better reflects what it does (not: down intersections or other nodes, but might be worth doing that in the future for normal form?)
Copied goldens: for f in tests/regression/lazyunion-* ; do mkdir ${f/lazy/lazier} ; done for f in tests/output/lazierunion-cgalpng/lazierunion-* ; do cp $f `echo ${f/actual/expected} | sed 's/output/regression/'` ; done
Another option would be to do a fast-union over all the negative objects, then just one big difference at the end: |
Hah! I explored that AST rewrite before fast-union (in that branch), would be the next easy win for fast-union I think. Maybe only unioning the fast-unionable subtracted operands? I worry about the cost of unioning highly intersecting bodies vs. cheaper incremental differences. |
@ochafik please for the love of programmable CSG modeling, come back and complete this ultra useful work 😆 |
Caveat: hackish code not meant to be merged as is, more of a conversation starter. It’s functional tho, so feel free to patch it!
I’m a big fan of lazy unions (@kintel @thehans 👏)! However, some nodes (e.g.
translate
,color
,module
calls) still force the union of their children, which means lots of lost opportunities to avoid unions (I love the idea of letting them bubble up to the root of the tree and let others do the work, e.g. slicer).So… here are some proposals to take lazy-unions to the next level:
--enable=lazy-module
lets modules’ outputs flow through lazily (this should probably just be fenced behindlazy-union
, methinks)--enable=push-transforms-down-unions
pushes transforms down on their children (they will become lazy unions of transformed children when --enable=lazy-union, otherwise just a group / normal union). Useful in non-lazy cases thanks to the next feature...--enable=flatten-children
flattens nested ListNode, GroupNode and (compatible) CsgOpNode’s children lists. It helps boost the arity of top-level unions/intersections (which that other PR and follow ups can crunch for breakfast), and handles cases of inlining modules lazy output (also, much easier to parallelize).These three features skip nodes w/ special tags (
!
,%
, etc).Lots of failed tests, because trees are modified a lot and I’ve added a bunch of logs.
Context: I didn’t do this just to extend the reach of lazy unions, although this does help lots of models I tested: I was trying to parallelize rendering (didn’t realize others were busy at it in #2399 & #3193 🤦♂️ ) and I figured parallelism could be easier to implement with very flat trees (also ofc, with less unions to compute overall).
Ideally I’d like to try and turn much of the tree into disjunctive normal forms (union of intersections, probably leaving cachable nodes untouched), transform differences to more parallelizable (commutative) intersections (
A - B - C -… → A ⋂ ¬B ⋂ ¬C ⋂…
, “just” need to wire CGAL’s Nef complement operation for that?) and focus parallelization efforts on high-arity unions and intersections, which this PR provides in large amounts (I might clean up my low-footprint concurrency approach to discuss it in yet another PR, which will also make use of my union optimization in #3636)I’d love to get some feedback on this approach, happy to send separate PRs with some cleaner visiter/transformer pattern and lots of tests if that's a path that sounds sensible.