Buckets:

hf-doc-build/doc / diffusers /v0.43.0 /vi /optimization /context_parallelism.md
mishig's picture
|
download
raw
13.4 kB
# Song song ngữ cảnh
[Context parallelism](https://huggingface.co/spaces/nanotron/ultrascale-playbook?section=context_parallelism) chia chuỗi đầu vào giữa các GPU, và mỗi GPU xử lý phần riêng của nó. Điều này làm giảm bộ nhớ trên mỗi GPU, hữu ích nhất cho các chuỗi dài như ảnh độ phân giải cao và video. Để so sánh với các chiến lược khác, xem [Distributed inference](../training/distributed_inference).
Context parallelism được thực thi bên trong attention backend, và chỉ một số backend hỗ trợ tính năng này. Nếu backend của bạn không hỗ trợ, `enable_parallelism` sẽ gây ra lỗi liệt kê các backend tương thích. Hãy chuyển đổi backend bằng [set_attention_backend()](/docs/diffusers/v0.43.0/vi/api/models/overview#diffusers.ModelMixin.set_attention_backend) và xem [các backend khả dụng](./attention_backends#available-backends) để có danh sách đầy đủ.
Cấu hình mọi biến thể bên dưới bằng [ContextParallelConfig](/docs/diffusers/v0.43.0/vi/api/parallel#diffusers.ContextParallelConfig).
| Biến thể | Cấu hình | Yêu cầu | Sử dụng khi |
|---|---|---|---|
| [Ring Attention](#ring-attention) | `ring_degree > 1` | chiều dài chuỗi phải chia hết cho `ring_degree` | các chuỗi dài và băng thông liên kết giữa các bộ xử lý bị hạn chế |
| [Ulysses Attention](#ulysses-attention) | `ulysses_degree > 1` | chiều dài chuỗi và số đầu chú ý phải chia hết cho `ulysses_degree` | các GPU của bạn có kết nối nhanh |
| [Unified Attention](#unified-attention) | `ring_degree > 1` và `ulysses_degree > 1` | ít nhất 4 GPU | bạn có nhiều thiết bị hơn số thiết bị mà Ulysses Attention có thể sử dụng một mình |
| [Ulysses Anything Attention](#ulysses-anything-attention) | `ulysses_degree > 1`, `ulysses_anything=True` | `ring_degree` phải bằng 1 | độ dài chuỗi hoặc số đầu không chia hết |
| [Ring Anything Attention](#ring-anything-attention) | `ring_degree > 1`, `ring_anything=True` | `ulysses_degree` phải là 1, chỉ suy luận, `attn_mask` phải là `None` | chiều dài chuỗi không chia hết |
## Ring Attention
[Ring Attention](https://huggingface.co/papers/2310.01889) truyền các khối key (K) và value (V) giữa các GPU được sắp xếp thành một vòng. Mỗi GPU tính toán attention với khối K/V mà nó đang giữ, sau đó truyền khối đó sang GPU tiếp theo. Sau một vòng lặp hoàn chỉnh, mọi GPU đều đã xem qua K/V của mọi token, và không có GPU nào giữ toàn bộ chuỗi.
Đặt `ring_degree` bằng số lượng GPU và truyền cấu hình vào phương thức `enable_parallelism()` của transformer.
```py
import os
import torch
from torch import distributed as dist
from diffusers import DiffusionPipeline, ContextParallelConfig
def setup_distributed():
if not dist.is_initialized():
dist.init_process_group(backend="nccl")
# torchrun sets LOCAL_RANK to this process's GPU index on its node
local_rank = int(os.environ["LOCAL_RANK"])
device = torch.device(f"cuda:{local_rank}")
torch.cuda.set_device(device)
return device
def main():
device = setup_distributed()
world_size = dist.get_world_size()
pipeline = DiffusionPipeline.from_pretrained(
"black-forest-labs/FLUX.1-dev", dtype=torch.bfloat16
).to(device)
pipeline.transformer.set_attention_backend("_native_cudnn")
cp_config = ContextParallelConfig(ring_degree=world_size)
pipeline.transformer.enable_parallelism(config=cp_config)
prompt = """
cinematic film still of a cat sipping a margarita in a pool in Palm Springs, California
highly detailed, high budget hollywood movie, cinemascope, moody, epic, gorgeous, film grain
"""
# Must specify generator so all ranks start with same latents (or pass your own)
generator = torch.Generator().manual_seed(42)
image = pipeline(
prompt,
guidance_scale=3.5,
num_inference_steps=50,
generator=generator,
).images[0]
if dist.get_rank() == 0:
image.save("output.png")
if dist.is_initialized():
dist.destroy_process_group()
if __name__ == "__main__":
main()
```
Lưu script dưới tên `ring_attention.py` và chạy bằng [torchrun](https://docs.pytorch.org/docs/stable/elastic/run.html) hoặc trình khởi chạy tương thích PyTorch khác. Đặt `--nproc-per-node` bằng số lượng GPU.
```bash
torchrun --nproc-per-node 2 ring_attention.py
```
Để thử các biến thể khác, hãy thay thế lời gọi `enable_parallelism` trong `ring_attention.py` bằng lời gọi từ phần tương ứng của chúng.
## Ulysses Attention
[Ulysses Attention](https://huggingface.co/papers/2309.14509) sử dụng giao tiếp *all-to-all*, trong đó mỗi GPU trao đổi dữ liệu với mọi GPU khác. Thao tác all-to-all đầu tiên nhóm lại dữ liệu để mỗi GPU giữ mọi token cho một tập con các attention head. Mỗi GPU tính toán attention cho các head của nó, và thao tác all-to-all thứ hai nhóm lại kết quả theo token cho lớp tiếp theo.
Đặt `ulysses_degree` bằng số lượng GPU và truyền cấu hình vào `enable_parallelism()`.
```py
pipeline.transformer.enable_parallelism(config=ContextParallelConfig(ulysses_degree=2))
```
## Unified Attention
[Unified Sequence Parallelism](https://huggingface.co/papers/2405.07719) kết hợp Ring Attention và Ulysses Attention. Nó thực hiện all-to-all để phân phối lại heads và tokens, chạy Ring Attention trên kết quả, sau đó đảo ngược all-to-all để khôi phục bố cục ban đầu. Ulysses song song hóa trên các attention heads và Ring song song hóa trên sequence, do đó khi kết hợp chúng có thể sử dụng nhiều GPU hơn so với chỉ dùng Ulysses.
Sử dụng Unified Attention khi bạn có ít nhất 4 GPU. Đặt cả `ulysses_degree` và `ring_degree` lớn hơn 1. Các GPU tạo thành một lưới 2D gồm `ulysses_degree * ring_degree` thiết bị, và mỗi GPU thuộc về một nhóm Ulysses và một nhóm Ring.
```py
pipeline.transformer.enable_parallelism(config=ContextParallelConfig(ulysses_degree=2, ring_degree=2))
```
Bảng chuẩn dưới đây so sánh Ulysses, Ring và Unified Attention trên 4 GPU H100 bằng [script này](https://github.com/huggingface/diffusers/pull/12693#issuecomment-3694727532). Mỗi hình ảnh sử dụng 50 bước suy luận.
| CP Backend | Thời gian / Ảnh (ms) | Bước / Giây | Bộ nhớ đỉnh (GB) |
|--------------------|------------------|-------------|------------------|
| ulysses | 6670.789 | 7.50 | 33.85 |
| ring | 13076.492 | 3.82 | 56.02 |
| unified_balanced | 11068.705 | 4.52 | 33.85 |
Ulysses có thông lượng cao nhất, nhưng không thể sử dụng nhiều GPU hơn số đầu chú ý (attention heads) của mô hình. Unified Attention loại bỏ giới hạn đó.
## Ulysses Anything Attention
Ulysses Attention yêu cầu độ dài chuỗi và số đầu attention phải chia hết cho `ulysses_degree`. [Ulysses Anything Attention](https://github.com/huggingface/diffusers/pull/12996) loại bỏ cả hai yêu cầu này. Bạn không thể kết hợp nó với Unified Attention, do đó `ring_degree` phải bằng 1.
Đặt `ulysses_degree` lớn hơn 1 và `ulysses_anything=True`.
```py
pipeline.transformer.enable_parallelism(config=ContextParallelConfig(ulysses_degree=2, ulysses_anything=True))
```
> [!TIP]
> Thêm backend `gloo` cho tensor CPU vào [init_process_group](https://docs.pytorch.org/docs/stable/distributed.html#torch.distributed.init_process_group). Điều này tránh được các đồng bộ hóa CUDA bắt buộc do các thao tác chuyển dữ liệu từ host sang thiết bị và từ thiết bị sang host gây ra.
```py
import torch.distributed as dist
dist.init_process_group(backend="cpu:gloo,cuda:nccl")
```
Bảng đánh giá dưới đây chạy FLUX.1-dev trên 4 GPU L20 bằng [script này](https://github.com/huggingface/diffusers/pull/12996#issuecomment-3797695999).
| CP Backend | Thời gian / Lặp (ms) | Bước / Giây | Bộ nhớ đỉnh (GB) | Hình dạng (HxW)|
|--------------------|------------------|-------------|------------------|------------|
| ulysses | 281.07 | 3.56 | 37.11 | 1024x1024 |
| ring | 351.34 | 2.85 | 37.01 | 1024x1024 |
| unified_balanced | 324.37 | 3.08 | 37.16 | 1024x1024 |
| ulysses_anything | 280.94 | 3.56 | 37.11 | 1024x1024 |
| ulysses | thất bại | thất bại | thất bại | 1008x1008 |
| ring | thất bại | thất bại | thất bại | 1008x1008 |
| unified_balanced | thất bại | thất bại | thất bại | 1008x1008 |
| ulysses_anything | 278.40 | 3.59 | 36.99 | 1008x1008 |
Ở kích thước 1008x1008, khi độ dài chuỗi không chia hết, chỉ có Ulysses Anything Attention được thực thi. Ở kích thước 1024x1024, hiệu năng của nó tương đương với Ulysses Attention tiêu chuẩn.
## Ring Anything Attention
Ring Attention yêu cầu độ dài chuỗi phải chia hết cho `ring_degree`. [Ring Anything Attention](https://github.com/huggingface/diffusers/pull/13545#issuecomment-4302195582) hỗ trợ mọi độ dài chuỗi. Nó đệm K/V cục bộ của mỗi GPU lên độ dài cục bộ dài nhất, thực hiện all-gather trên K/V đã đệm, và cắt mỗi khối về độ dài thực trước khi tính toán attention.
Bạn không thể kết hợp nó với Unified Attention, do đó `ulysses_degree` phải bằng 1. Đặt `ring_degree` lớn hơn 1 và `ring_anything=True`.
```py
pipeline.transformer.enable_parallelism(config=ContextParallelConfig(ring_degree=2, ring_anything=True))
```
Ring Anything Attention cũng được hưởng lợi từ backend `gloo` được trình bày trong [Ulysses Anything Attention](#ulysses-anything-attention).
> [!NOTE]
> Ring Anything Attention chỉ hỗ trợ suy luận, và `attn_mask` phải là `None`.
Bảng chuẩn (benchmark) bên dưới chạy FLUX.1-dev trên 4 GPU RTX 4090 (48GB).
| CP Backend | Thời gian / Lặp (ms) | Bước / Giây | Bộ nhớ đỉnh (GB) | Hình dạng (HxW)|
|--------------------|------------------|-------------|------------------|------------|
| ulysses | 259.07 | 3.86 | 33.83 | 1024x1024 |
| ring | 338.98 | 2.95 | 33.83 | 1024x1024 |
| unified_balanced | 321.54 | 3.11 | 33.83 | 1024x1024 |
| ulysses_anything | 259.07 | 3.86 | 33.83 | 1024x1024 |
| ring_anything | 340.14 | 2.94 | 33.83 | 1024x1024 |
| ulysses | thất bại | thất bại | thất bại | 1008x1008 |
| ring | thất bại | thất bại | thất bại | 1008x1008 |
| unified_balanced | thất bại | thất bại | thất bại | 1008x1008 |
| ulysses_anything | 253.16 | 3.95 | 33.75 | 1008x1008 |
| ring_anything | 335.57 | 2.98 | 33.75 | 1008x1008 |
Ring Anything Attention chạy ở kích thước 1008x1008 và cho hiệu suất tương đương với Ring Attention tiêu chuẩn. Để tìm hiểu về động lực và các đánh đổi, hãy xem [bình luận này](https://github.com/huggingface/diffusers/pull/13545#issuecomment-4304104462).
## Bật song song ngữ cảnh khi tải
Thay vì gọi `enable_parallelism` sau khi tải, hãy truyền [ContextParallelConfig](/docs/diffusers/v0.43.0/vi/api/parallel#diffusers.ContextParallelConfig) vào tham số `parallel_config` của [from_pretrained()](/docs/diffusers/v0.43.0/vi/api/models/overview#diffusers.ModelMixin.from_pretrained). Khởi tạo nhóm tiến trình trước, vì `from_pretrained` sẽ gây ra lỗi nếu `torch.distributed` chưa được khởi tạo. Chạy script bằng `torchrun`, như trong ví dụ [Ring Attention](#ring-attention).
```py
import os
import torch
from torch import distributed as dist
from diffusers import AutoModel, ContextParallelConfig, DiffusionPipeline
CKPT_ID = "black-forest-labs/FLUX.1-dev"
dist.init_process_group(backend="nccl")
local_rank = int(os.environ["LOCAL_RANK"])
device = torch.device(f"cuda:{local_rank}")
torch.cuda.set_device(device)
cp_config = ContextParallelConfig(ring_degree=dist.get_world_size())
transformer = AutoModel.from_pretrained(
CKPT_ID,
subfolder="transformer",
dtype=torch.bfloat16,
parallel_config=cp_config
)
pipeline = DiffusionPipeline.from_pretrained(
CKPT_ID, transformer=transformer, dtype=torch.bfloat16,
).to(device)
```

Xet Storage Details

Size:
13.4 kB
·
Xet hash:
53848a748d62376577829e41138b392bc5d2b77fbee478c27983fa34b89c1494

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.