Geometry Nodes: use lazy evaluation in repeat zone #112421
No reviewers
Labels
No Label
Interest
Alembic
Interest
Animation & Rigging
Interest
Asset Browser
Interest
Asset Browser Project Overview
Interest
Audio
Interest
Automated Testing
Interest
Blender Asset Bundle
Interest
BlendFile
Interest
Collada
Interest
Compatibility
Interest
Compositing
Interest
Core
Interest
Cycles
Interest
Dependency Graph
Interest
Development Management
Interest
EEVEE
Interest
EEVEE & Viewport
Interest
Freestyle
Interest
Geometry Nodes
Interest
Grease Pencil
Interest
ID Management
Interest
Images & Movies
Interest
Import Export
Interest
Line Art
Interest
Masking
Interest
Metal
Interest
Modeling
Interest
Modifiers
Interest
Motion Tracking
Interest
Nodes & Physics
Interest
OpenGL
Interest
Overlay
Interest
Overrides
Interest
Performance
Interest
Physics
Interest
Pipeline, Assets & IO
Interest
Platforms, Builds & Tests
Interest
Python API
Interest
Render & Cycles
Interest
Render Pipeline
Interest
Sculpt, Paint & Texture
Interest
Text Editor
Interest
Translations
Interest
Triaging
Interest
Undo
Interest
USD
Interest
User Interface
Interest
UV Editing
Interest
VFX & Video
Interest
Video Sequencer
Interest
Virtual Reality
Interest
Vulkan
Interest
Wayland
Interest
Workbench
Interest: X11
Legacy
Blender 2.8 Project
Legacy
Milestone 1: Basic, Local Asset Browser
Legacy
OpenGL Error
Meta
Good First Issue
Meta
Papercut
Meta
Retrospective
Meta
Security
Module
Animation & Rigging
Module
Core
Module
Development Management
Module
EEVEE & Viewport
Module
Grease Pencil
Module
Modeling
Module
Nodes & Physics
Module
Pipeline, Assets & IO
Module
Platforms, Builds & Tests
Module
Python API
Module
Render & Cycles
Module
Sculpt, Paint & Texture
Module
Triaging
Module
User Interface
Module
VFX & Video
Platform
FreeBSD
Platform
Linux
Platform
macOS
Platform
Windows
Priority
High
Priority
Low
Priority
Normal
Priority
Unbreak Now!
Status
Archived
Status
Confirmed
Status
Duplicate
Status
Needs Info from Developers
Status
Needs Information from User
Status
Needs Triage
Status
Resolved
Type
Bug
Type
Design
Type
Known Issue
Type
Patch
Type
Report
Type
To Do
No Milestone
No project
No Assignees
4 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: blender/blender#112421
Loading…
Reference in New Issue
No description provided.
Delete Branch "JacquesLucke/blender:lazy-repeat-zone"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The goal is to make the evaluation of repeat zones more efficient by making use of the lazy-function evaluation system. Performance is improved in two ways:
It is possible that some uses of repeat zones become slower with this refactor, especially when each iteration does very little work and there are a lot of iterations. The old implementation was not optimized for this use case either but now there is a bit more constant overhead per iteration than before.
On the bright side, this change can result in some very significant speedups.
800ms
to70ms
because different ico-spheres are generated in parallel.There is one todo comment for adding back-links for socket usages. Properly linking those up can result in better (shorter) life-times for anonymous attributes. Even without that, performance is already better than before.
The image below shows how the generated graph looks like with three iterations. Note that there are three loop body nodes which are chained. In the final implementation, there will also be backlinks for the socket usages (which currently have a
1
input). TheLogical Or
on the right outputs true when any of the loop bodies uses a border link (a link that passes data directly through the zone border, instead of the repeat input node).Building a lazy-function graph makes it possible to use the lazyness and multi-threading features of the lazy-function graph executor. This is much easier than reimplementing this behavior for repeat zones specifically (hence there was only single-threaded eager execution before).
@blender-bot build
@ -1496,0 +1578,4 @@
void *graph_executor_storage = nullptr;
bool multi_threading_enabled = false;
Vector<int> input_index_map;
Vector<int> output_index_map;
Can it be
IndexRange
instead ofVector
, filled byiota
?Note that the
output_index_map
is not anIndexRange
, the input map could be one in theory though.Main reason I didn't do this before is that I was contemplating to make this index-mapped-params a more general thing, but that doesn't seem necessary currently.
@ -1566,0 +1753,4 @@
}
/**
* Generate a lazy-function graph that contains contains the loop body (`body_fn_`) as many times
Typo:
contains contains
@ -1671,0 +1791,4 @@
VectorSet<lf::FunctionNode *> &lf_body_nodes = eval_storage.lf_body_nodes;
for ([[maybe_unused]] const int i : IndexRange(iterations)) {
lf::FunctionNode &lf_node = lf_graph.add_function(body_fn_);
eval_storage.lf_body_nodes.add_new(&lf_node);
Shorter alias:
lf_body_nodes.add_new(&lf_node);
;@blender-bot build
I find the need for
RepeatBodyNodeExecuteWrapper
a bit confusing. I know I'm just missing things, but I imagined that wrapping inside things wouldn't be necessary because there is a graph generated with the right number of iterations. I guess it's just needed to support logging a specific iteration?Other than that, this change seems straightforward actually.
@ -131,2 +131,4 @@
struct GeoNodesSideEffectNodes {
MultiValueMap<ComputeContextHash, const lf::FunctionNode *> nodes_by_context;
/**
* The repeat zone is identified by the compute context and the identifier of the repeat output
I guess it's the compute context of the parent of the repeat zone? Might be worth clarifying
@ -1643,0 +1815,4 @@
eval_storage.graph_executor.emplace(lf_graph,
lf_graph_inputs,
lf_graph_outputs,
std::move
?Updated the comment. I think the main thing you might be missing is that, while we create a graph with a node per iteration, all these nodes use the same
LazyFunction
internally.@blender-bot build
It might be nice to add that the overhead is proportional to the number of iterations, since I think that's how the algorithmic complexity is different than before.
Probably a stupid question, but just to be sure, the iterations in
iterations_by_repeat_zone
don't cause repeat zones that otherwise wouldn't be executed to be executed, right? Based on the code it looks fine.Not a stupid question. The repeat zone will not execute more iterations than what is passed into the Iterations input. However, if the repeat zone contains a side effect node such as a viewer, some iterations might evaluated even if the final output of the repeat zone is not used.
Does this threading means that it is possible to have the kind of iteration performance like in blur attribute node? Or is entirely different thing?
It's kind of unrelated. Whether you can benefit from multi-threading across multiple iterations in the repeat zone depends on your node tree. If the next iteration depends on the previous iteration (as it often does), things have to be done one after the other. Within individual nodes there is still multi-threading of course.
After stress testing repeat zone with zero operation inside it (the latest build after this pr merged and blender 4 alpha from back august) both suffer fps drop to 3.7 fps compared to using blur attribute node 70+ fps at 100000 iteration. (blur node get the same fps drop only after 4,000,000 iteration)
I believe this is worrisome if we are to build a performant simulation system
Edit:
It turns out that this is not specific to repeat zone but general serial operation in geometry nodes. I manually created 100000 connection with zero operation and this also do severe fps drop to about 5 fps