• Fooocus框架代码分析


    由于Fooocus的优秀推理能力,后续考虑从webui切换到Fooocus上,因此对其中的代码要进行深入分析,Fooocus的sdxl版本在11g的显存上跑起来压力不大,但是webui的sdxl版本起码12g。尤其要对比其和webui的优化点,但是在代码层面,并不是和webui同一档次的框架,webui采用了支持hook式的插件系统,但是fooocus因为其midjourney的指向,所以并不是走三方插件的路子。

    在autodl上:python launch.py --listen --port 6006

    entry_with_update.py

    1. # 启动
    2. python entry_with_update.py --listen
    3. launch.py ->
    4. prepare_environment()->
    5. ini_comfy_args()->
    6. - args_manager.py -> args = comfy_cli.args ->backend/headless/comfy/cli_args.py
    7. download_models()->
    8. webui.py ->
    9. - run_button.click().then(fn=generate_clicked)->
    10. -- modules/async_worker.py->workers()->threading.Thread(target=worker).start()
    11. -- handler()-> # 传入参数并配置
    12. -- prompt_processing/vary/upscale/inpaint/controlnet/
    13. -- imgs = pipeline.process_diffusin(...)->

    modules/default_pipeline.py -> process_diffusion() 主pipeline,webui中是StableDiffusionProcessingTxt2Img和StableDiffusionProcessingImg2Img两个核心接口。

    1. if latent is None:
    2. empty_latent = core.generate_empty_latent(width,height,1)
    3. else:
    4. empty_latent = latent
    5. sampled_latent = core.ksampler(final_unet,final_refiner,positive_cond,negative_cond,empty_latent,steps,denoise,callback,cfg_scale,sampler_name,scheduler_name,switch)
    6. decoded_latent = core.decode_vae(vae,sampled_latent,...)
    7. images = core.pytorch_to_numpy(decoded_latent)

    默认方法:refresh_everything()

    1. refresh_everything()->
    2. refresh_refiner_model(refiner_model_name)
    3. refresh_base_model(base_model_name)
    4. refresh_loras(loras)
    5. prepare_text_encoder(True)

    core.py -> generate_empty_latent()

    1. opEmptyLatentImage.generate(width,height,batch_size)[0]
    2. - backend/headless/nodes.py -> EmptyLatentImage.generate()
    3. - latent = torch.zeros([bs,4,height//8,width//8]) -> {'samples':latent}

    core.py->ksampler()->backend/headless/comfy/sample.py

    1. core->ksampler()
    2. latent_image = latent['sampler']
    3. noise = comfy.sample.prepare_noise(latent_image,seed,...)
    4. samples = comfy.sample.sample(model,noise,steps,cfg,sampler_name,scheduler,positive,negative,latent_image,...)
    5. - backend/headless/comfy/sample.py->sample()
    6. - real_model,positive_copy,negative_copy,noise_mask,models=prepare_sampling(model,noise.shape,positive...)
    7. - sampler = comfy.samplers.KSampler(...)
    8. - sampler = sampler.sample(noise,positive_copy,negative_copy,cfg,latent_image...)
    9. -- sampler = sampler_class(self.sampler)
    10. -- sample(self.model,noise,positive,...)

    sampler_class()->backend/headless/comfy/samplers.py

    1. sampler_class(name)->
    2. sampler = ksampler(name)->class KSAMPLER(Sampler)

    sample->modules/sample_hijack.py (backend/headless/comfy/samplers.py) 劫持了comfy中的sample

    1. sample_hijack(model,noise,positive,negative,cfg,device,sampler,sigmas,model_options,latent_image,denoise_mask,callback,...) ->
    2. positive = positive[:]
    3. negative = negative[:]
    4. model_wrap = model_wrap(model)
    5. - model_denoise = CFGNoisePredictor(model)
    6. - model_wrap = k_diffusion_external.CompVisDenoiser(model_denoise)
    7. calculate_start_end_timesteps(model_wrap,negative)
    8. calculate_start_end_timesteps(model_wrap,positive)
    9. for c in positive/negative:
    10. create_cond_with_same_area_if_none(negative/positive,c)
    11. pre_run_control(model_wrap,negative+positive) # cfg相关
    12. latent_image = model.process_latent_in(latent_image)
    13. samples = samplers.sample(model_wrap,sigmas,extra_args,...)
    14. model.process_latent_out(samples)

    backend/headless/comfy/samplers.py

    1. class KSAMPLER->sample(model_wrap,sigmas,extra_args,callback,...)
    2. model_k = KSamplerOInpaint(model_wrap)
    3. if sampler_name == "dpm_fast":
    4. samples = k_diffusion_sampling.sample_dpm_fast(model_k,noise,...)
    5. elif sampler_name == "dpm_adaptive":
    6. samples = k_diffusion_sampling.sample_dpm_adaptive(model_k,noise,...)
    7. else:
    8. samples = getattr(k_diffusion_sampling,"sample_{}".format(sampler_name))(model_k,noise,...)

    backend/headless/comfy/k_diffusion/sampling.py

    1. sampler_dpmpp_2m_sde_gpu(model,x,sigmas,extra_args,callback,...)
    2. noise_sampler = BrownianTreeNoiseSampler(x,sigma_min,..) if noise_sampler is None else noise_sampler
    3. sample_dpmpp_2m_sde(model,x,...)

    sample_dpmpp_2m_sde

    1. for i in trange(len(sigmas)-1):
    2. denoised = model(x,sigmas[i]*s_in,**extra_args)
    3. if callback is not None:
    4. callback({'x':x,'i':i,'sigma':sigma[i],'sigma_hat':sigmas[i],'denoised':denoised})
    5. if sigmas[i+1] == 0:
    6. x = denoised
    7. else:
    8. # DPM-Solver++(2M) SDE
    9. t, s = -sigmas[i].log(), -sigmas[i + 1].log()
    10. h = s - t
    11. eta_h = eta * h
    12. x = sigmas[i + 1] / sigmas[i] * (-eta_h).exp() * x + (-h - eta_h).expm1().neg() * denoised
    13. if old_denoised is not None:
    14. r = h_last / h
    15. if solver_type == 'heun':
    16. x = x + ((-h - eta_h).expm1().neg() / (-h - eta_h) + 1) * (1 / r) * (denoised - old_denoised)
    17. elif solver_type == 'midpoint':
    18. x = x + 0.5 * (-h - eta_h).expm1().neg() * (1 / r) * (denoised - old_denoised)
    19. if eta:
    20. x = x + noise_sampler(sigmas[i], sigmas[i + 1]) * sigmas[i + 1] * (-2 * eta_h).expm1().neg().sqrt() * s_noise

    backend/headless/nodes.py 节点就是类

    1. NODE_CLASS_MAPPINGS = {
    2. "KSampler": KSampler,
    3. "CheckpointLoaderSimple": CheckpointLoaderSimple,
    4. "CLIPTextEncode": CLIPTextEncode,
    5. "CLIPSetLastLayer": CLIPSetLastLayer,
    6. "VAEDecode": VAEDecode,
    7. "VAEEncode": VAEEncode,
    8. "VAEEncodeForInpaint": VAEEncodeForInpaint,
    9. "VAELoader": VAELoader,
    10. "EmptyLatentImage": EmptyLatentImage,
    11. "LatentUpscale": LatentUpscale,
    12. "LatentUpscaleBy": LatentUpscaleBy,
    13. "LatentFromBatch": LatentFromBatch,
    14. "RepeatLatentBatch": RepeatLatentBatch,
    15. "SaveImage": SaveImage,
    16. "PreviewImage": PreviewImage,
    17. "LoadImage": LoadImage,
    18. "LoadImageMask": LoadImageMask,
    19. "ImageScale": ImageScale,
    20. "ImageScaleBy": ImageScaleBy,
    21. "ImageInvert": ImageInvert,
    22. "ImageBatch": ImageBatch,
    23. "ImagePadForOutpaint": ImagePadForOutpaint,
    24. "EmptyImage": EmptyImage,
    25. "ConditioningAverage": ConditioningAverage,
    26. "ConditioningCombine": ConditioningCombine,
    27. "ConditioningConcat": ConditioningConcat,
    28. "ConditioningSetArea": ConditioningSetArea,
    29. "ConditioningSetAreaPercentage": ConditioningSetAreaPercentage,
    30. "ConditioningSetMask": ConditioningSetMask,
    31. "KSamplerAdvanced": KSamplerAdvanced,
    32. "SetLatentNoiseMask": SetLatentNoiseMask,
    33. "LatentComposite": LatentComposite,
    34. "LatentBlend": LatentBlend,
    35. "LatentRotate": LatentRotate,
    36. "LatentFlip": LatentFlip,
    37. "LatentCrop": LatentCrop,
    38. "LoraLoader": LoraLoader,
    39. "CLIPLoader": CLIPLoader,
    40. "UNETLoader": UNETLoader,
    41. "DualCLIPLoader": DualCLIPLoader,
    42. "CLIPVisionEncode": CLIPVisionEncode,
    43. "StyleModelApply": StyleModelApply,
    44. "unCLIPConditioning": unCLIPConditioning,
    45. "ControlNetApply": ControlNetApply,
    46. "ControlNetApplyAdvanced": ControlNetApplyAdvanced,
    47. "ControlNetLoader": ControlNetLoader,
    48. "DiffControlNetLoader": DiffControlNetLoader,
    49. "StyleModelLoader": StyleModelLoader,
    50. "CLIPVisionLoader": CLIPVisionLoader,
    51. "VAEDecodeTiled": VAEDecodeTiled,
    52. "VAEEncodeTiled": VAEEncodeTiled,
    53. "unCLIPCheckpointLoader": unCLIPCheckpointLoader,
    54. "GLIGENLoader": GLIGENLoader,
    55. "GLIGENTextBoxApply": GLIGENTextBoxApply,
    56. "CheckpointLoader": CheckpointLoader,
    57. "DiffusersLoader": DiffusersLoader,
    58. "LoadLatent": LoadLatent,
    59. "SaveLatent": SaveLatent,
    60. "ConditioningZeroOut": ConditioningZeroOut,
    61. "ConditioningSetTimestepRange": ConditioningSetTimestepRange,
    62. }

  • 相关阅读:
    SpringBoot SpringBoot 开发实用篇 4 数据层解决方案 4.5 SpringBoot 整合 Redis
    浅谈基于QT的截图工具的设计与实现
    Android 获取短信验证
    【LeetCode】试题总结:深度优先搜索 (DFS)
    vuex 学习之路
    ChartDirector 7.1.0 for VB Crack
    C++模板初阶
    酒店解决方案近呗科技
    决斗者优化算法:一种受决斗者如何在决斗中提高能力启发的算法(Matlab代码实现)
    云原生之k8s--------Kubernetes原理
  • 原文地址:https://blog.csdn.net/u012193416/article/details/133770053