EPS Technical Manual
08 / 64
Файлы
08
PART I · WORKFLOW ENGINEERING FOR COMFYUI

Execution Model, Queue & Cache — почему граф запускается не слева направо

ComfyUI исполняет не рисунок на canvas, а dependency graph. Положение ноды на экране не задаёт порядок вычисления: runtime строит топологическую зависимость от requested outputs, переиспользует валидный cache и пересчитывает только то, что стало dirty или больше не совпадает по input signature.

CONFIRMEDExecutionList в текущем ComfyUI реализован поверх topological sort; execution.py отдельно сообщает cached nodes, а caching.py строит cache keys из class type, inputs и ancestry.
01 · FIRST PRINCIPLE

Canvas layout помогает человеку, но не определяет execution order

Нода справа может вычислиться только после того, как готовы все её реальные upstream dependencies. Нода слева, которая не нужна выбранному output route, не обязана участвовать в текущем выполнении только потому, что визуально находится «раньше».

Поэтому professional layout важен для чтения, но runtime truth находится в links и dependency graph.

02 · TOPOLOGICAL ORDER

ExecutionList разрешает зависимости, а не координаты нод

В текущем ComfyUI ExecutionList построен поверх topological sort. Перед выполнением ноды runtime должен иметь готовые значения тех upstream nodes, от которых она зависит.

Это объясняет, почему большое полотно можно свободно раскладывать по группам и колонкам: визуальный порядок предназначен для человека, dependency order — для engine.

CONFIRMED

ComfyUI implementation

comfy_execution/graph.py описывает ExecutionList как topological dissolve of the graph и отдельно отслеживает staged node, dependencies и cached values.

03 · OUTPUT TARGETS

Сначала определяется нужный результат, затем его upstream requirements

Execution engine формирует список output targets и добавляет их в execution list. Дальше вычисление раскрывает необходимые dependencies. Это полезная модель для диагностики: если хочешь понять, почему выполняется ветка, найди output, который от неё зависит.

В сложном production workflow это особенно важно для previews, saves и alternative branches: наличие ноды в JSON ещё не означает, что она нужна текущему result path.

04 · CACHE

Повторный Queue не обязательно означает повторный расчёт всего графа

ComfyUI хранит промежуточные outputs и при следующем запуске может использовать cached result, если input signature соответствующей ноды и её dependency context не изменились.

В execution.py cached nodes собираются отдельно и отправляются клиенту событием execution_cached. Это не «пропущенная» работа, а нормальная оптимизация графа.

Что произошлоОжидаемое поведение
Ничего relevant не изменилосьБольшая часть route может прийти из cache
Изменён upstream parameterИзменившаяся нода и зависимый downstream route требуют нового расчёта
Изменён unrelated branchНезависимый output route может сохранить валидный cache
Node сообщает собственный IS_CHANGED / fingerprintCache validity учитывает этот сигнал
05 · INPUT SIGNATURE

Cache связан не только с ID ноды, но и с её inputs и ancestry

Текущая caching implementation строит signature из class type, change fingerprint и inputs. Для linked inputs в signature учитывается ancestor и socket, а ancestry обходится детерминированно.

Отсюда важный production вывод: изменение master control upstream способно сделать dirty несколько downstream stages даже тогда, когда визуально ты редактировал только маленькую control-ноду.

CONFIRMED

CacheKeySetInputSignature

ComfyUI caching.py включает immediate node signature и ordered ancestry в cache key для input-signature cache.

06 · DIRTY PROPAGATION

Изменение нужно оценивать по downstream impact radius

Если shared seed, working resolution или selector изменён высоко в control plane, impact radius может быть большим. Если изменён локальный Color Match после готового cutout, пересчёт обычно ограничивается более поздней частью route.

Это ещё одна причина проектировать workflow модульно: хороший boundary уменьшает область пересчёта и делает диагностику понятнее.

07 · QUEUE

Queue Prompt — это запрос на вычисление graph state, а не команда «пройти все ноды»

Нажатие Queue отправляет runtime описание нужного состояния графа. Затем engine валидирует dependencies, определяет cached nodes и исполняет недостающую часть route.

Поэтому две очереди одного workflow могут заметно отличаться по времени: первая строит тяжёлые intermediates, следующая может переиспользовать значительную часть результатов.

08 · DEBUG METHOD

При странном поведении задавай три вопроса: selected? required? cached?

Эти три вопроса отделяют routing problem от execution problem. После них уже имеет смысл разбирать model loading, sampler, mask или VRAM.

QuestionЧто проверяем
SELECTED?Selector / switch действительно ведёт по этой ветке?
REQUIRED?Есть ли текущий output, который зависит от этой ветки?
CACHED?Node реально исполнилась заново или runtime использовал сохранённый output?
09 · HANSEN APPLICATION

Как это меняет чтение большого Hansen workflow

  • Не читать 252 nodes как список слева направо — сначала выбрать конкретный output/checkpoint.
  • От output пройти upstream и выписать только required route.
  • На каждом selector определить selected branch.
  • Отдельно отметить bypassed modules, чтобы не включать их в effective runtime map.
  • После Queue смотреть, какие checkpoints обновились, а какие остались cached.
  • При тесте менять одну переменную и оценивать её downstream impact radius.
10 · PRACTICE

Практика: доказать cache и dependency execution на маленьком графе

  • Запустить простой route до Preview/Save и зафиксировать время первого run.
  • Ничего не менять и повторить Queue; отметить, какие nodes runtime считает cached.
  • Изменить один поздний parameter и посмотреть, насколько коротким становится recalculated tail.
  • Изменить один ранний shared control и сравнить impact radius.
  • Переключить selector на alternative branch и увидеть, как меняется required ancestry.
  • Сформулировать словами: какая нода стала dirty первой и почему downstream пришлось пересчитать.