updated readme with header anchor link
This commit is contained in:
@@ -41,7 +41,7 @@ In the `example_workflows/` folder of this repo, I have included example Wan 2.2
|
||||
|
||||
- **Control execution order & free memory:**
|
||||
|
||||
The `🔷 Control Order & Free Memory` node ensures that all of the input-connected nodes finish executing first before the output-connected nodes start executing. Hence to control the execution order of nodes, you can split your workflow into multiple groups of nodes with differing execution priorities and connect all nodes that should execute first to the input slots of this node, and all nodes that should execute later to the output slots of this node, ensuring that the correct data is being passed from the "persist_any_N" input slot to its corresponding "N"th output slot. You can then chain additional groups of nodes with as many `🔷 Control Order & Free Memory` nodes as you need, until all groups of nodes are connected together to form a single, sequential flow of execution from start to finish. Optionally, toggle "free_memory" ON on this node to unload all models and free as much VRAM & RAM as possible at the node's position, while preserving all the passthrough data. You can connect as many passthrough data as you need through this node, and each of them can be a different data type (e.g. latents, conditioning, images, models, etc.). If any of the passthrough data are models and they were not already unloaded by the sender nodes, they will stay loaded and survive the "free_memory" operation (Please refer to [Limitations](#limitations) for more details). Also, when "free_memory" is ON, this node will print a descriptive message on the ComfyUI session terminal where you can check how much VRAM & RAM has been freed.
|
||||
The `🔷 Control Order & Free Memory` node ensures that all of the input-connected nodes finish executing first before the output-connected nodes start executing. Hence to control the execution order of nodes, you can split your workflow into multiple groups of nodes with differing execution priorities and connect all nodes that should execute first to the input slots of this node, and all nodes that should execute later to the output slots of this node, ensuring that the correct data is being passed from the "persist_any_N" input slot to its corresponding "N"th output slot. You can then chain additional groups of nodes with as many `🔷 Control Order & Free Memory` nodes as you need, until all groups of nodes are connected together to form a single, sequential flow of execution from start to finish. Optionally, toggle "free_memory" ON on this node to unload all models and free as much VRAM & RAM as possible at the node's position, while preserving all the passthrough data. You can connect as many passthrough data as you need through this node, and each of them can be a different data type (e.g. latents, conditioning, images, models, etc.). If any of the passthrough data are models and they were not already unloaded by the sender nodes, they will stay loaded and survive the "free_memory" operation (please refer to [Limitations](#limitations) for more details). Also, when "free_memory" is ON, this node will print a descriptive message on the ComfyUI session terminal where you can check how much VRAM & RAM has been freed.
|
||||
|
||||
- **Connecting this node into loader-type nodes:**
|
||||
|
||||
@@ -61,15 +61,15 @@ In the `example_workflows/` folder of this repo, I have included example Wan 2.2
|
||||
- Adaptively expands input & output slots to support infinitely many dynamic passthrough data of any type (*).
|
||||
- Linear passthrough design that focuses on one group of related nodes at a time and routes only necessary outputs to the next group of nodes helps with "cable management", tidying up the connections that can get messy as the workflow grows large, making them easier to understand and maintain.
|
||||
|
||||
## ℹ️ Limitations
|
||||
## <a name="limitations"></a>ℹ️ Limitations
|
||||
|
||||
- Please note that this node is built upon the current ComfyUI implementation of the "comfy.model_management.py" module for memory management, and ComfyUI extension hooks & prototype hijacking patterns for making dynamic updates to the node's UI elements. Hence, it is possible that some features of the node may stop working in future updates of ComfyUI. For more information, you may find these Docs useful:
|
||||
- [ComfyUI model management](https://github.com/Comfy-Org/ComfyUI/blob/master/comfy/model_management.py)
|
||||
- [ComfyUI custom extension hooks](https://docs.comfy.org/custom-nodes/js/javascript_hooks)
|
||||
- [LiteGraph.js](https://tamats.com/projects/litegraph/doc/classes/LGraphNode.html)
|
||||
- You may notice that system RAM usage often does not drop as significantly as GPU VRAM does after this node's "free_memory" operation runs. This is expected behavior in the current implementation of ComfyUI, as ComfyUI intentionally caches the output of every executed node in RAM (e.g. latents, images, conditionings, tensors, etc.) with strong references that survive any py garbage collection invoked from inside the custom node's logic, and only releases those references after the entire "prompt execution" finishes (see [execution.py](https://github.com/Comfy-Org/ComfyUI/blob/master/execution.py), [comfy_execution/caching.py](https://github.com/Comfy-Org/ComfyUI/blob/master/comfy_execution/caching.py)). This is an intentional optimization design by ComfyUI so that downstream nodes can reuse upstream outputs instantly without re-computation. The "free_memory" operation of this custom node already does the maximum possible cleanup with (model unloading + explicit gc.collect() + double device cache clearing before and after the garbage collection to collect as much lingering tensors as possible, etc.). Hence, any RAM that remains allocated after this node runs is ComfyUI's deliberate output caching, which is best to leave up to ComfyUI to manage & optimize behind the scenes across multiple workflow runs.
|
||||
- CLIP models (and other text encoders) behave differently from diffusion models. In most workflows, ComfyUI automatically unloads the CLIP model immediately after the conditioning nodes (CLIPTextEncode, CLIPTextEncodeFlux, etc.) finish (refer to https://github.com/Comfy-Org/ComfyUI/blob/master/comfy/model_management.py). Hence, if you route the CLIP model through this node, the node will often receive an already-unloaded “husk” object, and passing this object to a later conditioning node can cause malformed conditioning outputs or OutOfMemory errors when you feed them into KSamplers. This is an inherent behaviour of the `Load CLIP (Comfy Core)` node which my custom node (that executes later in the graph) cannot prevent. As a workaround, do not rely on passing the CLIP model itself through this node. Instead, you could generate the conditioning immediately after loading CLIP, and only pass the resulting conditioning outputs through to persist_any_N. If you need the CLIP model later, you can always reload it with a new `Load CLIP (Comfy Core)` node in the subsequent chains. Diffusion models, VAEs, and most other large models managed by ComfyUI do persist correctly when routed through this node.
|
||||
- GGUF / Quantized Models: Some GGUF loaders have custom unloading logic that may not always respect the keep_loaded feature of this node's free_memory operation, hence may drop itself before entering the node much like how CLIP models behave. But again, this can be mitigated by loading the model back in on the subsequent chains whenever you need them.
|
||||
- CLIP models (and other text encoders) behave differently from diffusion models. In most workflows, ComfyUI automatically unloads the CLIP model immediately after the conditioning nodes (CLIPTextEncode, CLIPTextEncodeFlux, etc.) finish (see [comfy/model_management.py](https://github.com/Comfy-Org/ComfyUI/blob/master/comfy/model_management.py)). Hence, if you route the CLIP model through this node, the node will often receive an already-unloaded “husk” object, and passing this object to a later conditioning node can cause malformed conditioning outputs or OutOfMemory errors when you feed them into KSamplers. This is an inherent behaviour of the `Load CLIP (Comfy Core)` node which my custom node (that executes later in the graph) cannot prevent. As a workaround, do not rely on passing the CLIP model itself through this node. Instead, you could generate the conditioning immediately after loading CLIP, and only pass the resulting conditioning outputs through to persist_any_N. If you need the CLIP model later, you can always reload it with a new `Load CLIP (Comfy Core)` node in the subsequent chains. Diffusion models, VAEs, and most other large models managed by ComfyUI do persist correctly when routed through this node.
|
||||
- Some GGUF / Quantized model loaders have custom unloading logic that may not always respect the keep_loaded feature of this node's free_memory operation, hence may drop itself before entering the node much like how CLIP models behave. But again, this can be mitigated by loading the model back in on the subsequent chains whenever you need them.
|
||||
|
||||
## ❤️ Inspired By
|
||||
|
||||
|
||||
Reference in New Issue
Block a user