Buckets:
| # Tensor paralelliği | |
| [Tensor parallelism](https://huggingface.co/spaces/nanotron/ultrascale-playbook?section=tensor_parallelism), bir modelin ağırlık matrislerini cihazlar arasında parçalar. Her cihaz, her katman için sütun bazlı (`"colwise"`) veya satır bazlı (`"rowwise"`) bir dilim tutar ve kısmi bir sonuç hesaplar. Katman sınırındaki bir `AllReduce` veya `AllGather`, kısmi sonuçları birleştirerek tam çıktıyı oluşturur. [context parallelism](./context_parallelism)'den farklı olarak, cihaz başına *weight* belleğini azaltır; bu da bir modelin tek bir cihaza sığmadığı durumlarda işe yarar. Diğer stratejilerle karşılaştırmak için [Distributed inference](../training/distributed_inference) bölümüne bakın. | |
| ## Parçalı bir model yükleyin | |
| Modelin [from_pretrained()](/docs/diffusers/v0.43.0/tr/api/models/overview#diffusers.ModelMixin.from_pretrained) metodunun `parallel_config` argümanına bir [TensorParallelConfig](/docs/diffusers/v0.43.0/tr/api/parallel#diffusers.TensorParallelConfig) geçirin. `tp_degree`, parçalanacak cihaz sayısıdır ve modelin dikkat başı sayısına tam bölünmelidir. Model sınıfı, modül adlarını bir parçalama stiline eşleyen bir `_tp_plan` tanımlamalıdır. Bir modelin tensör paralelliğini destekleyip desteklemediğini kontrol etmek için, [Flux2Transformer2DModel](/docs/diffusers/v0.43.0/tr/api/models/flux2_transformer#diffusers.Flux2Transformer2DModel) gibi, sınıfında bu özniteliği arayın. | |
| Başka bir modele plan eklemek için [Bir modele tensör paralelliği ekleme](#add-tensor-parallelism-to-a-model) bölümüne bakın. | |
| Bu yöntemle yüklenirken, kontrol noktası okundukça parçalara ayrılır. Her rank, her ağırlığın yalnızca kendi dilimini okur ve doğrudan kendi GPU'suna yerleştirir; böylece hiçbir rank tam boyutlu bir ağırlık tutmaz. Rank başına bellek, `tp_degree` arttıkça azalır. | |
| ```py | |
| import os | |
| import torch | |
| from torch import distributed as dist | |
| from diffusers import DiffusionPipeline, Flux2Transformer2DModel, TensorParallelConfig | |
| def main(): | |
| dist.init_process_group(backend="nccl") | |
| rank, world_size = dist.get_rank(), dist.get_world_size() | |
| # 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) | |
| # Each rank reads only its own shard of every planned weight, straight onto its own GPU. | |
| transformer = Flux2Transformer2DModel.from_pretrained( | |
| "black-forest-labs/FLUX.2-dev", | |
| subfolder="transformer", | |
| dtype=torch.bfloat16, | |
| parallel_config=TensorParallelConfig(tp_degree=world_size), | |
| ) | |
| pipeline = DiffusionPipeline.from_pretrained( | |
| "black-forest-labs/FLUX.2-dev", transformer=transformer, dtype=torch.bfloat16 | |
| ) | |
| # The transformer is already on its device; move the remaining components individually. Do not call | |
| # `pipeline.to(device)` — that would move every rank's shards onto the same device. | |
| pipeline.text_encoder.to(device) | |
| pipeline.vae.to(device) | |
| generator = torch.Generator().manual_seed(42) | |
| image = pipeline(prompt="a cat holding a sign that says hello", generator=generator).images[0] | |
| if rank == 0: | |
| image.save("output.png") | |
| dist.destroy_process_group() | |
| if __name__ == "__main__": | |
| main() | |
| ``` | |
| Betik dosyasını `tensor_parallel_flux2.py` olarak kaydedin ve `torchrun` ile başlatın. | |
| ```shell | |
| torchrun --nproc-per-node 4 tensor_parallel_flux2.py | |
| ``` | |
| Betik, `tp_degree` değerini `world_size` olarak ayarladığından, `--nproc-per-node 4` komutu dönüştürücüyü 4 GPU arasında paylaştırır. | |
| Sadece transformer parçalanır. Her rank, metin kodlayıcısının tam bir kopyasını tutar; bu nedenle her GPU'nun, metin kodlayıcı ile transformer'ın kendine düşen payı için yeterli belleğe sahip olması gerekir. | |
| ## Yükleme performansı | |
| `parallel_config` ile yükleme, tam modeli yükleyip ardından `enable_parallelism()` çağrılmasından daha hızlıdır ve rank başına daha az CPU belleği kullanır. Aşağıdaki tablo, 4x A10G (23GB) üzerinde [black-forest-labs/FLUX.2-dev](https://huggingface.co/black-forest-labs/FLUX.2-dev) (yalnızca transformer, 32B parametre, bf16) için sonuçları göstermektedir. | |
| | tp_degree | yöntem | yüklenme süresi | zirve CPU/rank | | |
| |---|---|---|---| | |
| | 4 | `from_pretrained(parallel_config=...)` | 12.5s | 6,8 GB | | |
| | 4 | `from_pretrained` + `enable_parallelism` | 30.4s | 64,1 GB | | |
| ## Kısıtlamalar | |
| Tensor parallelism, bazı yükleme seçenekleri ve özelliklerle çalışmaz ve bölünmüş bir modeli kaydedemezsiniz. | |
| - `parallel_config` ile tensor-parallel yükleme, `device_map`, `quantization_config`, `low_cpu_mem_usage=False`, `use_flashpack=True` veya safetensors olmayan ağırlıklarla çalışmaz. Bunların her biri, tam checkpoint'i sessizce yüklemek yerine bir hata fırlatır. | |
| - Gergilik paralelliğinin, modelin nasıl bölündüğüne bakılmaksızın, kuantizasyon, offloading veya LoRA adaptörleriyle birleştirilmesi de bir hata oluşturur. | |
| - Bellekte zaten bulunan bir modeli parçalamak için aynı yapılandırmayla `enable_parallelism()` çağrılır. Bu yöntem önce tam modeli yükler ve ardından parçalar; bu nedenle her rank, tam checkpoint için bellek gerektirir. Bu maliyeti önlemek için yükleme sırasında `parallel_config` kullanılır. | |
| - Tensor-parallel bir modelin kaydedilmesi [save_pretrained()](/docs/diffusers/v0.43.0/tr/api/models/overview#diffusers.ModelMixin.save_pretrained) içinde bir hata oluşturur. Modeli parçalara ayırmadan önce kaydedin. | |
| ## Bir modele tensör paralelliği ekleyin | |
| Bu bölüm, bir Diffusers modeline tensör paralelliği desteği eklemek isteyen katkıda bulunanlar içindir. | |
| Tensor paralelliği, yalnızca modül adlarını bir parçalama stiline eşleyen `_tp_plan` sınıf özniteliğini tanımlayan modellerde çalışır. Bu özniteliği yazmak, çoğunlukla gizli boyutu *genişleten* her projeksiyonu, onu geri *daraltan* projeksiyonla eşleştirmek anlamına gelir. | |
| Her anahtar en fazla bir `*` içerebilir ve `*` işaretinden önceki bölüm bir [`nn.ModuleList`](https://pytorch.org/docs/stable/generated/torch.nn.ModuleList.html)'ye çözümlenmelidir, böylece bir girdi tüm blokları kapsar. `*` içermeyen bir anahtar, modelin kendisine uygulanır. Yollar modele göre göreli olarak tanımlanır. | |
| ### Colwise ve rowwise | |
| | Stil | Parçalar | Her sıra | Kullanım alanları | | |
| |---|---|---|---| | |
| | `"colwise"` | çıkış özellikleri (`weight` boyutu 0) | çıkışın bir dilimini hesaplar | `to_q`, `to_k`, `to_v`, FFN iç projeksiyonu | | |
| | `"rowwise"` | girdi özellikleri (`weight` boyutu 1) | kısmi bir toplam hesaplar | `to_out.0`, FFN çıkış projeksiyonu | | |
| | `"rowwise_split_input"` | girdi özellikleri (`weight` boyutu 1) | kopyalanmış girdinin diliminden kısmi bir toplam hesaplar | girdisi replike edilmiş, zaman adımları gömme değerini okuyan bir AdaLN modülasyon projeksiyonu gibi bağımsız bir projeksiyon | | |
| `"colwise"` ve `"rowwise"` değerlerini her zaman bu sırayla eşleştirin. `"colwise"` projeksiyonu çıktısını parçalı (sharded) bırakır, ardından gelen `"rowwise"` projeksiyonu bu parçayı doğrudan tüketir ve blok sınırındaki tek bir `AllReduce` işlemi sonucu yeniden oluşturur. Bu çiftin başka bir şekilde parçalanması, ortada bir toplama (gather) işlemi zorunlu kılar ve çok daha fazla iletişim gerektirir. | |
| Attention'da sütun bazlı Q, K ve V projeksiyonları her rank'a başların bir alt kümesini verir, bu nedenle `tp_degree` baş sayısına tam bölünmelidir. Encoder-stream kopyaları (`add_q_proj`, `to_add_out`, `ff_context`), image-stream karşılıklarıyla aynı deseni izler. | |
| ### Birleştirilmiş projeksiyonlar | |
| Tek bir `Linear`, parçalanan boyut boyunca birden fazla mantıksal tensörü paketlediğinde, düz `"colwise"`/`"rowwise"` dilimleri birleştirmenin üzerinden doğrudan geçer ve parçaları hizasız bırakır. Bunun yerine, her paketlenmiş bloğu bağımsız olarak parçalayan `PackedColwiseParallel`/`PackedRowwiseParallel` kullanın. | |
| ```py | |
| # in src/diffusers/models/transformers/your_model.py | |
| from ...hooks.tensor_parallel import PackedColwiseParallel, PackedRowwiseParallel | |
| ``` | |
| `blocks`, paketlenmiş boyutu bölen oransal tam sayılardan oluşan bir liste, geçirin. Örneğin, eşit yarımlara sahip bir SwiGLU gate ve up projection için `[1, 1]` veya `mlp_ratio=3` ile birleşik Q, K, V, gate ve up projection için `[1, 1, 1, 3, 3]` kullanın. | |
| ```py | |
| "transformer_blocks.*.ff.linear_in": PackedColwiseParallel([1, 1]), | |
| ``` | |
| Blok boyutları yalnızca yapılandırmadan biliniyorsa, `blocks` parametresini atlayın ve mutlak boyutları `__init__` sırasında `Linear` üzerinde `_tp_packed_col_blocks` veya `_tp_packed_row_blocks` olarak saklayın. | |
| ```py | |
| # in the attention module's __init__ | |
| self.to_out._tp_packed_row_blocks = [self.inner_dim, self.mlp_hidden_dim] | |
| ``` | |
| ```py | |
| # in the model's _tp_plan | |
| "single_transformer_blocks.*.attn.to_out": PackedRowwiseParallel(), | |
| ``` | |
| [`transformer_flux2.py`](https://github.com/huggingface/diffusers/blob/main/src/diffusers/models/transformers/transformer_flux2.py) içindeki plan her iki biçimi de kullanır. Çift akışlı SwiGLU çifti `blocks` değerini doğrudan iletir. Birleşik tek akışlı QKV ve MLP projeksiyonu, boyutları `mlp_ratio` ve `mlp_mult_factor` değerlerine bağlı olduğu için, bu boyutları `Flux2ParallelSelfAttention.__init__` içindeki `Linear` nesnesinde saklar. | |
| ### Dışarıda bırakılacaklar | |
| Plan dışı bırakılan modüller her sırada kopyalanır. Normalizasyon katmanlarını, yama ve metin gömme katmanlarını ile son `norm_out` ve `proj_out` katmanlarını dışarıda bırakın. Bunlar küçük olduğu için bunları bölümlere ayırmak az miktarda bellek tasarrufu sağlar ve iletişim yükü ekler. AdaLN modülasyonu (`img_mod` ve `txt_mod`) genellikle dışarıda bırakılacak kadar küçüktür. MiniMax-H3'ün `adaln_proj.linear` gibi büyük olduğunda, `"rowwise_split_input"` ile bölümlere ayırın. | |
| ### Kısıtlamalar ve doğrulama | |
| - `tp_degree`, `config.num_attention_heads`'i tam olarak bölmelidir. | |
| - Her paketlenmiş blok, yalnızca toplamları değil, *tek tek* `tp_degree` değerine bölünebilir olmalıdır. | |
| [from_pretrained()](/docs/diffusers/v0.43.0/tr/api/models/overview#diffusers.ModelMixin.from_pretrained) ve `enable_parallelism()`, herhangi bir ağırlık yüklenmeden veya bölünmeden önce her iki kontrolü de yapar. | |
| Yeni bir planı gözle değil, sayısal olarak doğrulayın: sabit bir tohumla tek bir cihazda üretim yapın, ardından tensor paralelliği altında tekrar üretin ve çıktıları karşılaştırın. Yanlış yerleştirilmiş bir `"colwise"`/`"rowwise"` genellikle yine de çalışır ve makul görünen ancak yanlış bir görüntü üretir. | |
| > [!TIP] | |
| > Benzer bir mimari için mevcut bir plandan başlayın. | |
| > | |
| > - [`transformer_qwenimage.py`](https://github.com/huggingface/diffusers/blob/main/src/diffusers/models/transformers/transformer_qwenimage.py) birleşik projeksiyon içermez, bu nedenle her giriş düz `"colwise"` veya `"rowwise"` şeklindedir. - [`transformer_flux.py`](https://github.com/huggingface/diffusers/blob/main/src/diffusers/models/transformers/transformer_flux.py) tek bir paketlenmiş satır bazlı projeksiyon ekler. - [`transformer_flux2.py`](https://github.com/huggingface/diffusers/blob/main/src/diffusers/models/transformers/transformer_flux2.py) her iki paketlenmiş stili de kullanır. | |
Xet Storage Details
- Size:
- 11.7 kB
- Xet hash:
- 7e34937cfd07250ab1d74a862f9355f3b089af8fa6e5a1fcede7108b7af8653f
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.