【diffusers极速入门(十)】Flux-pipe 推理,完美利用任何显存大小,GPU显存节省终极方案(附代码)

系列文章目录



1-完美利用方案

  • 该方案可以根据所使用的 GPU 有多少显存空闲,即可设置对应的max_memory,最大化利用 GPU 的同时,保证不出现 OOM 问题。
  • 可以减少对 GPU 的显存需求,推理时间也不会过于慢。
import os
os.environ["CUDA_VISIBLE_DEVICES"] = "0"
os.environ["PYTORCH_CUDA_ALLOC_CONF"] = "expandable_segments:True"  # 减少显存碎片化

torch.inference_mode()  # 启用推理模式,减少显存占用

local_path = '/path/to/models/FLUX.1-Canny-dev'
# online_path: "black-forest-labs/FLUX.1-Canny-dev"

max_memory = {
    0: "39GiB",  # 限制 GPU 0 使用 39GB 显存 
}

torch_dtype = torch.bfloat16
pipe = FluxControlPipeline.from_pretrained(local_path, 
                                           torch_dtype=torch_dtype,
                                           device_map="balanced",
                                           max_memory=max_memory)  # 自动决定模型组件的设备分配    
processor = CannyDetector()

# pipe.to("cuda")
pipe.enable_vae_slicing()
pipe.enable_vae_tiling()  # 新增分块策略
pipe.enable_attention_slicing("max")  # 新增分块策略

基本概念

  • diffusers 库中,device_map 是一个非常有用的参数,它主要用于控制模型在不同计算设备(如 CPU、GPU 等)之间的分布,这对于处理大型模型时的内存管理和性能优化至关重要。

  • device_map 本质上是一个字典或字符串,用于指定模型的各个部分(如不同的层)应该被放置到哪个计算设备上。通过合理配置 device_map,可以将模型分布到多个 GPU 上,或者在 GPU 和 CPU 之间进行混合部署,以充分利用不同设备的计算资源并避免内存溢出。

使用场景

  • 多 GPU 系统:当你有多个 GPU 可用时,可以使用 device_map 将模型均匀地分布到这些 GPU 上,从而加速推理过程。
  • 内存受限:如果单个 GPU 的内存不足以容纳整个模型,你可以将部分模型放置到 CPU 上,或者在多个 GPU 之间拆分模型,以避免内存溢出错误。

其他场景示例

device_map 可以接受以下字符串字典两种类型的值。

使用字符串作为 device_map
  • "auto":自动将模型分布到可用的 GPU 上,如果没有足够的 GPU 内存,会将部分模型放到 CPU 上。
  • "balanced":尝试在所有可用的 GPU 之间均匀地分布模型,以平衡内存使用。
  • "balanced_low_0":与 "balanced" 类似,但会尽量减少第一个 GPU 的内存使用。
  • "sequential":按顺序将模型层依次分配到可用的 GPU 上。
  • "cpu":将整个模型加载到 CPU 上。
  • "cuda":将整个模型加载到第一个可用的 GPU 上。
from diffusers import StableDiffusionPipeline

# 使用 "auto" 自动分配模型到可用设备
pipeline = StableDiffusionPipeline.from_pretrained("runwayml/stable-diffusion-v1-5", device_map="auto")

# 生成图像
image = pipeline("A beautiful landscape").images[0]
image.save("landscape.png")
使用字典作为 device_map

字典的键是模型的模块名称,值是设备名称(如 "cpu""cuda:0""cuda:1" 等)。通过这种方式,你可以精确地指定每个模块应该放置的设备。

from diffusers import StableDiffusionPipeline

# 自定义设备映射
device_map = {
    "text_encoder": "cuda:0",
    "unet": "cuda:1",
    "vae": "cuda:0"
}

pipeline = StableDiffusionPipeline.from_pretrained("runwayml/stable-diffusion-v1-5", device_map=device_map)

# 生成图像
image = pipeline("A cute cat").images[0]
image.save("cat.png")

注意事项

  • 设备可用性:确保你指定的设备(如 cuda:1)是实际可用的,否则会抛出错误。
  • 内存管理:合理配置 device_map 可以避免内存溢出,但不同的分配策略可能会影响推理性能,需要根据实际情况进行调整。
  • 兼容性:某些模型可能不支持所有的 device_map 选项,使用时需要参考模型的文档。

2-超节省方案

  • 几乎不需要 GPU 的显存占有 (好像是纯 CPU 跑?),但推理时间会变慢很多。
import os
os.environ["CUDA_VISIBLE_DEVICES"] = "1"
os.environ["PYTORCH_CUDA_ALLOC_CONF"] = "expandable_segments:True"  # 减少显存碎片化

torch.inference_mode()  # 启用推理模式,减少显存占用

local_path = '/path/to/models/FLUX.1-Canny-dev'
# online_path: "black-forest-labs/FLUX.1-Canny-dev"

torch_dtype = torch.bfloat16
pipe = FluxControlPipeline.from_pretrained(local_path, 
                                           torch_dtype=torch_dtype,
                                           )  
pipe.enable_sequential_cpu_offload() # 推理几乎 0 显存占用
diffusers 原生 text-to-image 的 fft (Fast Fourier Transform) 方法使用的数据集为 parquet 格式,需要进行适配。 parquet 是一种列式存储格式,能够高效地存储和处理大规模数据。为了适配这种格式,我们需要执行以下步骤: 1. 读取数据集:使用 Parquet 库或工具,如 Apache Parquet、Dask 或 PyArrow,读取 parquet 格式的数据集文件。这些工具提供了函数和方法来加载和操作 parquet 数据集。 2. 数据预处理:根据 fft 方法的要求,对读取的数据进行必要的预处理。这可能包括数据类型转换、缺失值处理、数据清洗等步骤,以确保数据符合要求。 3. 调整数据结构:根据 fft 方法的输入要求,可能需要将 parquet 数据集的列或行重新排列以适应 fft 的输入结构。这可以通过列索引或行索引操作来实现。 4. 执行 fft:使用 fft 方法对预处理后的数据进行转换。可以使用现有的 fft 函数或库,如 numpy.fft 或 scipy.fft,对数据进行 fft 变换。根据具体需求,可能需要在这一步中设置相关参数,如采样频率、分辨率等。 5. 结果保存:将 fft 结果保存为适当的数据格式,以便后续使用或分析。parquet 格式是一种可选的选择,也可以将结果保存为其他常见的图像格式,如 PNG、JPEG 等。 通过以上步骤,我们可以将 diffusers 原生 text-to-image 的 fft 方法适配到 parquet 格式的数据集上。这样,我们可以充分利用 parquet 格式的优势,加快数据处理速度,并满足 fft 方法对数据结构的要求。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值