# تسريع الاستدلال

تكون نماذج الانتشار بطيئة عند الاستدلال لأن التوليد عملية تكرارية يتم فيها تحسين الضوضاء تدريجياً لتتحول إلى صورة أو فيديو عبر عدد معين من "الخطوات". لتسريع هذه العملية، يمكنك تجربة تجارب مع [مجدولات](../api/schedulers/overview) مختلفة، أو تقليل دقة أوزان النموذج لحسابات أسرع، أو استخدام آليات انتباه أكثر كفاءة في استخدام الذاكرة، وغير ذلك.

اجمع بين هذه التقنيات واستخدمها معًا لجعل الاستدلال أسرع مما لو استخدمت أي تقنية على حدة.

ستتناول هذه الدليل كيفية تسريع الاستدلال.

## نوع بيانات النموذج

تؤثر دقة أوزان النموذج ونوع البيانات على سرعة الاستدلال، لأن الدقة الأعلى تتطلب ذاكرة أكبر للتحميل ووقتًا أطول لتنفيذ العمليات الحسابية. يقوم PyTorch بتحميل أوزان النموذج بنوع float32 أو الدقة الكاملة افتراضيًا، لذا فإن تغيير نوع البيانات هو طريقة بسيطة للحصول على استدلال أسرع بسرعة.

bfloat16 يشبه float16 لكنه أكثر مقاومة للأخطاء العددية. يختلف دعم الأجهزة لـ bfloat16، لكن معظم وحدات معالجة الرسومات الحديثة قادرة على دعم bfloat16.

```py
import torch
from diffusers import StableDiffusionXLPipeline

pipeline = StableDiffusionXLPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0", dtype=torch.bfloat16
).to("cuda")  # or "mps", "xpu", "cpu"

prompt = "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k"
pipeline(prompt, num_inference_steps=30).images[0]
```

float16 مشابه لـ bfloat16 لكنه قد يكون أكثر عرضة للأخطاء العددية.

```py
import torch
from diffusers import StableDiffusionXLPipeline

pipeline = StableDiffusionXLPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0", dtype=torch.float16
).to("cuda")  # or "mps", "xpu", "cpu"

prompt = "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k"
pipeline(prompt, num_inference_steps=30).images[0]
```

تُدعم وضع [TensorFloat-32 (tf32)](https://blogs.nvidia.com/blog/2020/05/14/tensorfloat-32-precision-format/) على وحدات معالجة الرسوميات NVIDIA Ampere، حيث يقوم بحساب عمليات الالتفاف وضرب المصفوفات في tf32. وتبقى التخزين والعمليات الأخرى في float32. وهذا يتيح حسابات أسرع بشكل كبير عند دمجه مع bfloat16 أو float16.

PyTorch يُفعّل وضع tf32 للعمليات التجميعية (convolutions) افتراضياً فقط، وستحتاج إلى تفعيله صراحةً لعمليات ضرب المصفوفات.

```py
import torch
from diffusers import StableDiffusionXLPipeline

torch.backends.cuda.matmul.allow_tf32 = True

pipeline = StableDiffusionXLPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0", dtype=torch.bfloat16
).to("cuda")  # or "mps", "xpu", "cpu"

prompt = "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k"
pipeline(prompt, num_inference_steps=30).images[0]
```

راجع مستندات [التدريب بدقة مختلطة](https://huggingface.co/docs/transformers/en/perf_train_gpu_one#mixed-precision) لمزيد من التفاصيل.

## انتباه منتج نقطي مُصعّد

> [!TIP]
> تحسّن الانتباه الموفّر للذاكرة سرعة الاستدلال *و* [استهلاك الذاكرة](./memory#memory-efficient-attention)!

[انتباه حاصل الضرب النقطي المُقَيَّم (SDPA)](https://pytorch.org/docs/stable/generated/torch.nn.functional.scaled_dot_product_attention.html) ينفّذ عدة واجهات خلفية للانتباه، وهي [FlashAttention](https://github.com/Dao-AILab/flash-attention) و[xFormers](https://github.com/facebookresearch/xformers) وتنفيذ أصلي بلغة C++. يقوم تلقائيًا باختيار الواجهة الخلفية الأكثر ملاءمة لمعداتك.

يتم تفعيل SDPA افتراضيًا إذا كنت تستخدم PyTorch >= 2.0 ولا يلزم إجراء أي تغييرات إضافية على الكود الخاص بك. ومع ذلك، يمكنك تجربة تجارب مع واجهات خلفية انتباه أخرى إذا كنت ترغب في اختيار واجهتك الخاصة. يستخدم المثال أدناه مدير السياق [torch.nn.attention.sdpa_kernel](https://pytorch.org/docs/stable/generated/torch.nn.attention.sdpa_kernel.html) لتفعيل الانتباه الفعال.

```py
from torch.nn.attention import SDPBackend, sdpa_kernel
import torch
from diffusers import StableDiffusionXLPipeline

pipeline = StableDiffusionXLPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0", dtype=torch.bfloat16
).to("cuda")  # or "mps", "xpu", "cpu"

prompt = "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k"

with sdpa_kernel(SDPBackend.EFFICIENT_ATTENTION):
  image = pipeline(prompt, num_inference_steps=30).images[0]
```

## torch.compile

يسرّع [torch.compile](https://pytorch.org/tutorials/intermediate/torch_compile_tutorial.html) الاستدلال من خلال ترميز كود PyTorch وعملياته إلى نوى مُحسّنة. يقوم Diffusers عادةً بترميز النماذج الأكثر كثافة في الحسابات مثل UNet أو transformer أو VAE.

فعّل إعدادات المُجمِّع التالية للحصول على أقصى سرعة (راجع [القائمة الكاملة](https://github.com/pytorch/pytorch/blob/main/torch/_inductor/config.py) لمعرفة المزيد من الخيارات).

```py
import torch
from diffusers import StableDiffusionXLPipeline

torch._inductor.config.conv_1x1_as_mm = True
torch._inductor.config.coordinate_descent_tuning = True
torch._inductor.config.epilogue_fusion = False
torch._inductor.config.coordinate_descent_check_all_directions = True
```

حمّل UNet وVAE وجمعهما. هناك عدة أوضاع مختلفة يمكنك الاختيار من بينها، لكن `"max-autotune"` يُحسّن لأقصى سرعة عن طريق التجميع إلى CUDA graph. تُقلّل رسوم CUDA بشكل فعال من العبء التشغيلي من خلال إطلاق عمليات GPU متعددة عبر عملية CPU واحدة.

> [!TIP]
> With PyTorch 2.3.1, you can control the caching behavior of torch.compile. This is particularly beneficial for compilation modes like `"max-autotune"` which performs a grid-search over several compilation flags to find the optimal configuration. Learn more in the [Compile Time Caching in torch.compile](https://pytorch.org/tutorials/recipes/torch_compile_caching_tutorial.html) tutorial.

يُحسّن تغيير تخطيط الذاكرة إلى [channels_last](./memory#torchchannelslast) من كفاءة الذاكرة وسرعة الاستدلال.

```py
pipeline = StableDiffusionXLPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0", dtype=torch.float16
).to("cuda")  # or "mps", "xpu", "cpu"
pipeline.unet.to(memory_format=torch.channels_last)
pipeline.vae.to(memory_format=torch.channels_last)
pipeline.unet = torch.compile(
    pipeline.unet, mode="max-autotune", fullgraph=True
)
pipeline.vae.decode = torch.compile(
    pipeline.vae.decode,
    mode="max-autotune",
    fullgraph=True
)

prompt = "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k"
pipeline(prompt, num_inference_steps=30).images[0]
```

تكون عملية التجميع بطيئة في المرة الأولى، لكن بمجرد اكتمالها، تصبح أسرع بشكل ملحوظ. حاول استخدام خط الأنابيب المُجمَّع فقط على نفس نوع عمليات الاستدلال. استدعاء خط الأنابيب المُجمَّع على حجم صورة مختلف يعيد تشغيل عملية التجميع، وهي عملية بطيئة وغير فعّالة.

### تجميع الأشكال الديناميكية

> [!TIP]
> تأكد دائمًا من استخدام الإصدار اليومي (nightly) من PyTorch للحصول على دعم أفضل.

يحافظ `torch.compile` على تتبع أشكال المدخلات والشروط، وإذا كانت هذه مختلفة، يعيد تجميع النموذج. على سبيل المثال، إذا تم تجميع نموذج على صورة بدقة 1024x1024 واستُخدم على صورة بدقة مختلفة، فإن ذلك يستدعي إعادة التجميع.

لتجنب إعادة التجميع، أضف `dynamic=True` لمحاولة توليد نواة (kernel) أكثر ديناميكية لتجنب إعادة التجميع عند تغيّر الشروط.

```diff
+ torch.fx.experimental._config.use_duck_shape = False
+ pipeline.unet = torch.compile(
    pipeline.unet, fullgraph=True, dynamic=True
)
```

يُوجِّه تحديد `use_duck_shape=False` المُجمِّع (Compiler) بشأن ما إذا كان ينبغي له استخدام المتغير الرمزي نفسه لتمثيل أحجام المدخلات المتطابقة. لمزيد من التفاصيل، راجع هذا [تعليق](https://github.com/huggingface/diffusers/pull/11327#discussion_r2047659790).

قد لا تستفيد جميع النماذج من التجميع الديناميكي بشكل مباشر وقد تتطلب تعديلات. راجع هذا [PR](https://github.com/huggingface/diffusers/pull/11297/) الذي حسّن تنفيذ [AuraFlowPipeline](/docs/diffusers/main/ar/api/pipelines/aura_flow#diffusers.AuraFlowPipeline) للاستفادة من التجميع الديناميكي.

لا تتردد في فتح مشكلة إذا لم يعمل التجميع الديناميكي كما هو متوقع لنموذج Diffusers.

### التجميع الإقليمي

يقوم [التجميع الإقليمي](https://docs.pytorch.org/tutorials/recipes/regional_compilation.html) بتقليل زمن بدء التشغيل البارد من خلال تجميع *الكتلة أو الكتل الصغيرة والمتكررة بشكل متكرر* من النموذج - وهي عادةً طبقة محوّلة - مما يتيح إعادة استخدام المخرجات المُجمَّعة لكل ظهور تالٍ. بالنسبة للعديد من معماريات الانتشار، يحقق هذا نفس تسارعات وقت التشغيل كما في تجميع المخطط الكامل، ويقلل زمن التجميع بمقدار 8 إلى 10 أضعاف.

استخدم طريقة [compile_repeated_blocks()](/docs/diffusers/main/ar/api/models/overview#diffusers.ModelMixin.compile_repeated_blocks)، وهي أداة مساعدة تغلف `torch.compile`، على أي مكوّن مثل نموذج الترانسفورمر كما هو موضح أدناه.

```py
# pip install -U diffusers
import torch
from diffusers import StableDiffusionXLPipeline

pipeline = StableDiffusionXLPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0",
    dtype=torch.float16,
).to("cuda")  # or "mps", "xpu", "cpu"

# compile only the repeated transformer layers inside the UNet
pipeline.unet.compile_repeated_blocks(fullgraph=True)
```

لتفعيل التجميع الإقليمي لنموذج جديد، أضف سمة `_repeated_blocks` إلى فئة النموذج تحتوي على أسماء الفئات (كسلاسل نصية) للكتل التي تريد تجميعها.

```py
class MyUNet(ModelMixin):
    _repeated_blocks = ("Transformer2DModel",)  # ← compiled by default
```

> [!TIP]
> لمزيد من أمثلة التجميع الإقليمية، راجع [PR](https://github.com/huggingface/diffusers/pull/11705) المرجعي.

يوجد أيضًا طريقة [compile_regions](https://github.com/huggingface/accelerate/blob/273799c85d849a1954a4f2e65767216eb37fa089/src/accelerate/utils/other.py#L78) في [Accelerate](https://huggingface.co/docs/accelerate/index) تختار تلقائيًا الكتل المرشحة داخل النموذج لتجميعها. يتم تجميع بقية الرسم البياني بشكل منفصل. هذا مفيد للتجارب السريعة لأنه لا توجد خيارات كثيرة لتحديد الكتل المراد تجميعها أو تعديل أعلام التجميع.

```py
# pip install -U accelerate
import torch
from diffusers import StableDiffusionXLPipeline
from accelerate.utils import compile_regions

pipeline = StableDiffusionXLPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0", dtype=torch.float16
).to("cuda")  # or "mps", "xpu", "cpu"
pipeline.unet = compile_regions(pipeline.unet, mode="reduce-overhead", fullgraph=True)
```

[compile_repeated_blocks()](/docs/diffusers/main/ar/api/models/overview#diffusers.ModelMixin.compile_repeated_blocks) صريحةٌ عمدًا. اذكر الكتل التي تريد تكرارها في `_repeated_blocks` ولن يُجمّع المُساعد سوى تلك الكتل. فهي توفر سلوكًا متوقعًا وسهولةً في الاستدلال حول إعادة استخدام ذاكرة التخزين المؤقت في سطرٍ واحد من الكود.

### انقطاعات الرسم البياني

من المهم تحديد `fullgraph=True` في torch.compile للتأكد من عدم وجود انقطاعات في الرسم البياني للنموذج الأساسي. وهذا يتيح لك الاستفادة من torch.compile دون أي تدهور في الأداء. بالنسبة إلى UNet وVAE، يغيّر هذا الطريقة التي تصل بها إلى متغيرات الإرجاع.

```diff
- latents = unet(
-   latents, timestep=timestep, encoder_hidden_states=prompt_embeds
-).sample

+ latents = unet(
+   latents, timestep=timestep, encoder_hidden_states=prompt_embeds, return_dict=False
+)[0]
```

### مزامنة وحدة معالجة الرسوميات

تُستدعى الدالة `step()` [على](https://github.com/huggingface/diffusers/blob/1d686bac8146037e97f3fd8c56e4063230f71751/src/diffusers/pipelines/stable_diffusion_xl/pipeline_stable_diffusion_xl.py#L1228) المجدول بعد كل تنبؤ يصدره مُزيل الضوضاء، ويُستخدم [فهرسة](https://github.com/huggingface/diffusers/blob/1d686bac8146037e97f3fd8c56e4063230f71751/src/diffusers/schedulers/scheduling_euler_discrete.py#L476) متغير `sigmas`. عند وضعه على وحدة معالجة الرسوميات، يُدخل تأخيراً بسبب مزامنة الاتصال بين وحدة المعالجة المركزية ووحدة معالجة الرسوميات. ويصبح هذا التأخير أكثر وضوحاً عندما يكون مُزيل الضوضاء مُجمَّعاً بالفعل.

بشكل عام، يجب أن [تبقى على وحدة المعالجة المركزية (CPU)](https://github.com/huggingface/diffusers/blob/35a969d297cba69110d175ee79c59312b9f49e1e/src/diffusers/schedulers/scheduling_euler_discrete.py#L240) `sigmas` لتجنب مزامنة الاتصال وزمن الاستجابة.

> [!TIP]
> راجع منشور المدونة [torch.compile و Diffusers: دليل عملي لتحقيق الأداء الأقصى](https://pytorch.org/blog/torch-compile-and-diffusers-a-hands-on-guide-to-peak-performance/) لتعظيم الأداء باستخدام `torch.compile` لنماذج الانتشار.

### المعايير

راجع مجموعة بيانات [diffusers/benchmarks](https://huggingface.co/datasets/diffusers/benchmarks) للاطلاع على بيانات زمن الاستدلال واستهلاك الذاكرة للخطوط الأنابيب المُجمّعة.

تحتوي مستودعة [diffusers-torchao](https://github.com/sayakpaul/diffusers-torchao#benchmarking-results) أيضًا على نتائج قياس الأداء للإصدارات المُجمَّعة من Flux وCogVideoX.

## النوى

[Kernels](https://huggingface.co/docs/kernels/index) هو مكتبة لبناء وتوزيع وتحميل نوى الحساب المُحسَّنة على [Hub](https://huggingface.co/kernels-community). يدعم مكتبة [attention](./attention_backends#setattentionbackend) النوى المخصصة لنوى CUDA للعمليات مثل RMSNorm وGEGLU وRoPE وAdaLN.

يُبيّن دليل [تكامل خط أنابيب Diffusers](https://github.com/huggingface/kernels/blob/main/kernel-builder/skills/cuda-kernels/references/diffusers-integration.md) كيفية دمج نواة مع مهارة [إضافة cuda-kernels](https://github.com/huggingface/kernels/blob/main/kernel-builder/skills/cuda-kernels/SKILL.md). تُمكّن هذه المهارة وكيلًا، مثل Claude أو Codex، من كتابة نوى مخصصة موجهة نحو نموذج محدد وأجهزتك.

> [!TIP]
> قم بتثبيت مهارة [إضافة cuda-kernels](https://github.com/huggingface/kernels/blob/main/kernel-builder/skills/cuda-kernels/SKILL.md) لتعليم الوكيل كيفية كتابة نواة. يغطي منشور المدونة [النوى المخصصة للجميع من Codex وClaude](https://huggingface.co/blog/custom-cuda-kernels-agent-skills) هذا الموضوع بتفصيل أكبر.

على سبيل المثال، نواة RMSNorm مخصصة (مولّدة بواسطة مهارة `add cuda-kernels`) مع [torch.compile](#torchcompile) تسرّع توليد LTX-Video بمقدار 1.43x على H100.

<iframe src="https://huggingface.co/datasets/docs-benchmarks/kernel-ltx-video/embed/viewer/default/train" frameborder="0" width="100%" height="560px"
>

## التكميم الديناميكي

تحسّن [التكميم الديناميكي](https://docs.pytorch.org/ao/main/api_reference/generated/torchao.quantization.Int8DynamicActivationInt8WeightConfig.html) سرعة الاستدلال عن طريق تقليل الدقة لتمكين عمليات حسابية أسرع. يحدد هذا النوع المعين من التكميم كيفية توسيع التنشيطات بناءً على البيانات أثناء التشغيل بدلاً من استخدام عامل توسيع ثابت. ونتيجةً لذلك، يكون عامل التوسيع متوافقًا بشكل أدق مع البيانات.

يطبّق المثال أدناه [التكميم الديناميكي int8](https://docs.pytorch.org/ao/main/api_reference/generated/torchao.quantization.Int8DynamicActivationInt8WeightConfig.html) على UNet وVAE باستخدام مكتبة [torchao](../quantization/torchao).

> [!TIP]
> راجع مستندات [torchao](../quantization/torchao) لدينا لمعرفة المزيد حول كيفية استخدام تكامل Diffusers مع torchao.

اضبط وسوم المُجمِّع للحصول على أقصى سرعة.

```py
import torch
from torchao import apply_dynamic_quant
from diffusers import StableDiffusionXLPipeline

torch._inductor.config.conv_1x1_as_mm = True
torch._inductor.config.coordinate_descent_tuning = True
torch._inductor.config.epilogue_fusion = False
torch._inductor.config.coordinate_descent_check_all_directions = True
torch._inductor.config.force_fuse_int_mm_with_mul = True
torch._inductor.config.use_mixed_mm = True
```

استبعاد بعض طبقات الخطية في UNet وVAE التي لا تستفيد من التكميم الديناميكي باستخدام [dynamic_quant_filter_fn](https://github.com/huggingface/diffusion-fast/blob/0f169640b1db106fe6a479f78c1ed3bfaeba3386/utils/pipeline_utils.py#L16).

```py
pipeline = StableDiffusionXLPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0", dtype=torch.bfloat16
).to("cuda")  # or "mps", "xpu", "cpu"

apply_dynamic_quant(pipeline.unet, dynamic_quant_filter_fn)
apply_dynamic_quant(pipeline.vae, dynamic_quant_filter_fn)

prompt = "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k"
pipeline(prompt, num_inference_steps=30).images[0]
```

## مصفوفات الإسقاط المدمجة

> [!WARNING]
> طريقة [fuse_qkv_projections](https://github.com/huggingface/diffusers/blob/58431f102cf39c3c8a569f32d71b2ea8caa461e1/src/diffusers/pipelines/pipeline_utils.py#L2034) تجريبية، والدعم فيها محدود في الغالب لأنابيب Stable Diffusion. اطّلع على هذا [PR](https://github.com/huggingface/diffusers/pull/6179) لمعرفة المزيد حول كيفية تفعيلها لأنابيب أخرى

يُستَخرَج مدخل إلى ثلاثة فضاءات فرعية، ممثلة بمصفوفات الإسقاط Q وK وV، داخل كتلة الانتباه. عادةً ما تُحسب هذه الإسقاطات بشكل منفصل، لكن يمكنك دمجها أفقيًا في مصفوفة واحدة وتنفيذ الإسقاط في خطوة واحدة. يزيد هذا من حجم عمليات ضرب المصفوفات الخاصة بإسقاطات المدخلات، كما يحسّن أثر التكميم.

```py
pipeline.fuse_qkv_projections()
```

## الموارد

- اقرأ منشور المدونة [عرض Flux Fast: جعل Flux يعمل بسرعة على H100s](https://pytorch.org/blog/presenting-flux-fast-making-flux-go-brrr-on-h100s/) لمعرفة المزيد حول كيفية دمج جميع هذه التحسينات مع [TorchInductor](https://docs.pytorch.org/docs/stable/torch.compiler.html) و [AOTInductor](https://docs.pytorch.org/docs/stable/torch.compiler_aot_inductor.html) للحصول على تسريع يقارب 2.5x باستخدام الوصفات من [flux-fast](https://github.com/huggingface/flux-fast).

    تدعم هذه الوصفات أجهزة AMD و [Flux.1 Kontext Dev](https://huggingface.co/black-forest-labs/FLUX.1-Kontext-dev).
- اقرأ منشور المدونة [torch.compile و Diffusers: دليل عملي لأداء ذروة](https://pytorch.org/blog/torch-compile-and-diffusers-a-hands-on-guide-to-peak-performance/)
لزيادة الأداء عند استخدام `torch.compile`.

