Первая заметка о stageload измеряла один пайплайн, Pixal3D. У пайплайна text-to-image та же форма: текстовый энкодер, денойзер и декодер изображения работают друг за другом. Поэтому 6 октября я измерил такой пайплайн, Qwen-Image-2.1 в diffusers, на том же Mac с 48 ГБ. Его текстовый энкодер занимает 16,3 ГБ, трансформер 13,3 ГБ, а VAE 1,3 ГБ. Каждый прогон делал одно изображение 1024 × 1024 за 20 шагов, в своём процессе под сторожем памяти.
Eager — это обычный from_pretrained(...).to("mps"). В режиме staged две большие модели пайплайна заменены заглушками. На .config они отвечают из чекпойнта, чтобы пайплайн мог прочитать конфиг до начала денойзинга, а при любом другом обращении загружают настоящую модель. Три хука отмечают начало стадий: encode_prompt, prepare_latents и _unpack_latents. Код пайплайна не менялся.

При кодировании и денойзинге eager держался на 31–33 ГБ. Декодированию VAE нужно ещё около 11 ГБ сверх весов, и это подняло его до 43,6 ГБ; своп вырос на 8 ГБ, и сторож остановил прогон раньше, чем тот записал изображение. Staged выгрузил трансформер до декодирования. Его пик был 19,0 ГБ при кодировании и 14,4 ГБ при декодировании, и ни в одном из двух прогонов он не добавил свопа.
На загрузку двух моделей staged потратил 13 с. Денойзинг занял 109 с в его первом прогоне, 79 с во втором и 77,5 с у eager; почему первый прогон был медленнее, по его трассе не видно.
Что я не смог показать
Два прогона staged дали одно и то же изображение бит в бит. Eager на этом Mac изображения не дал, поэтому эти прогоны не показывают, что загрузка по стадиям даёт то же изображение, что и eager. Ещё более ранний прогон eager не прошёл даже загрузку: он стартовал через минуту после окончания видеозадачи, и своп вырос на 10 ГБ за 18 с.
Код лежит в bench/qwen_image.py, а трассы и сводка — в репозитории.