# الدفعية المستمرة

يعظّم الدفع المستمر (Continuous batching) استغلال وحدة معالجة الرسوميات (GPU) من خلال إعادة جدولة الدفعة ديناميكيًا في كل خطوة من خطوات التوليد. فمع انتهاء الطلبات، تنضم طلبات جديدة فورًا بدلاً من الانتظار حتى اكتمال الدفعة بأكملها. وبذلك تبقى وحدة معالجة الرسوميات مشغولة بالكامل ويظل معدل الإنتاجية مرتفعًا.

> [!TIP]
> للاستخدام في بيئات الإنتاج، استخدم [transformers serve](./serve-cli/serving_optims#continuous-batching). فهو يعتمد على [ContinuousBatchingManager](/docs/transformers/main/ar/main_classes/text_generation#transformers.ContinuousBatchingManager) ويعرض نقطة نهاية HTTP متوافقة مع OpenAI.

## generate_batch

يُتاح دعم الدفع المستمر (Continuous batching) من خلال [generate_batch()](/docs/transformers/main/ar/main_classes/text_generation#transformers.ContinuousMixin.generate_batch). مرّر قائمة من الموجهات المُرمّزة (tokenized prompts) وستحصل على النتائج الخاصة بها جميعاً عند اكتمالها. يتولى `generate_batch` جدولة المهام داخلياً، ويبقى في وضع الانتظار (blocks) حتى تكتمل جميع الطلبات.

لحالات الاستخدام المتعلقة بتقديم الخدمة والبث، استخدم [ContinuousBatchingManager](#continuousbatchingmanager) مباشرةً لإدارة الطلبات.

```py
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
from transformers.generation import ContinuousBatchingConfig, GenerationConfig

model = AutoModelForCausalLM.from_pretrained(
    "Qwen/Qwen3-4B",
    attn_implementation="flash_attention_2",
    device_map="auto",
    dtype=torch.bfloat16,
)
tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen3-4B")

prompts = [
    "What's up?",
    "Name a cat breed.",
    "Write a detailed history of quantum mechanics.",
]
inputs = [tokenizer.encode(p) for p in prompts]

generation_config = GenerationConfig(
    max_new_tokens=64,
    eos_token_id=tokenizer.eos_token_id,
)

outputs = model.generate_batch(inputs=inputs, generation_config=generation_config)

for request_id, output in outputs.items():
    text = tokenizer.decode(output.generated_tokens, skip_special_tokens=True)
    print(f"[{request_id}] {text}")
```

## ContinuousBatchingManager

يعمل [ContinuousBatchingManager](/docs/transformers/main/ar/main_classes/text_generation#transformers.ContinuousBatchingManager) بخيط خلفية (background thread) ويتيح لك إرسال الطلبات واستخراج النتائج بشكل مستقل. في كل خطوة توليد، يتحقق من الطلبات المكتملة ويحدد جدولة لطلبات جديدة للانضمام إلى الدفعة (batch). وهذا مفيد للبث (streaming) أو الخدمة في الوقت الفعلي أو إرسال الطلبات لحظة وصولها.

استخدم [continuous_batching_context_manager()](/docs/transformers/main/ar/main_classes/text_generation#transformers.ContinuousMixin.continuous_batching_context_manager) لبدء المُدير وإيقافه بأمان. يحتوي المثال أدناه على مدخلات بطول متغير. بمجرد اكتمال أقصر موجه، يغادر الدفعة بينما تستمر الموجهات الأطول في التوليد. مع الدفعات الثابتة، كان عليك ملء جميع الموجهات حتى الطول نفسه. تتيح لك الدفعات المستمرة تحرير الموجه المكتمل لبدء معالجة الموجه التالي فورًا.

```py
with model.continuous_batching_context_manager(generation_config=generation_config) as manager:
    manager.add_request(
        input_ids=tokenizer.encode("Write a detailed history of quantum mechanics."),
        request_id="long",
        max_new_tokens=512,
    )
    manager.add_request(
        input_ids=tokenizer.encode("What's up?"),
        request_id="short_0",
        max_new_tokens=32,
    )
    manager.add_request(
        input_ids=tokenizer.encode("Name a cat breed."),
        request_id="short_1",
        max_new_tokens=32,
    )

    for result in manager:
        text = tokenizer.decode(result.generated_tokens, skip_special_tokens=True)
        print(f"[{result.request_id}] {text}")
```

يمكنك أيضًا استدعاء [init_continuous_batching()](/docs/transformers/main/ar/main_classes/text_generation#transformers.ContinuousMixin.init_continuous_batching) لإدارة دورة الحياة بنفسك.

```py
manager = model.init_continuous_batching(generation_config=generation_config)
manager.start()

# submit and retrieve requests...
```

### إيقاف تشغيل المدير

يعمل المدير بخيط في الخلفية ويحتفظ بالموارد الموزعة. يتم إيقاف التشغيل في مرحلتين حتى تتمكن من اختيار ما تريد فعله مع العمل الجاري.

استدعِ [stop()](/docs/transformers/main/ar/main_classes/text_generation#transformers.ContinuousBatchingManager.stop) لإيقاف الخيط الخلفي. افتراضيًا، يتوقف المُدير عن قبول الطلبات الجديدة وينتظر حتى تنتهي الطلبات الموجودة في قائمة الانتظار والطلبات النشطة قبل خروج الخيط.

```py
manager.stop()
```

مرّر `hard_stop=True` للتخلي عن العمل المعلق فوراً. تُفشل الطلبات المجدولة والنشطة مع `RuntimeError` بدلاً من إتمامها.

```py
manager.stop(hard_stop=True)
```

بمجرد استدعاء `stop`، تتجاهل [add_request()](/docs/transformers/main/ar/main_classes/text_generation#transformers.ContinuousBatchingManager.add_request) و[add_requests()](/docs/transformers/main/ar/main_classes/text_generation#transformers.ContinuousBatchingManager.add_requests) الطلبات الجديدة وتسجّل تحذيرًا. يمكنك ما زال استدعاء `start` مرة أخرى لتشغيل جلسة توليد أخرى باستخدام نفس المُدير.

استدعِ [destroy()](/docs/transformers/main/ar/main_classes/text_generation#transformers.ContinuousBatchingManager.destroy) لتحرير الموارد الموزعة. يوقف `destroy` المُدير أولاً إذا كان ما يزال قيد التشغيل، ولا يمكن إعادة تشغيل المُدير بعد ذلك. استخدمه عند الانتهاء من الدفع المستمر (continuous batching) طوال عمر العملية.

```py
manager.destroy()
```

يتولى [continuous_batching_context_manager()](/docs/transformers/main/ar/main_classes/text_generation#transformers.ContinuousMixin.continuous_batching_context_manager) معالجة هذه العملية. فهو يستدعي `stop` عند الخروج، ويستدعي `destroy` ما لم تقم بتمرير `persistent_manager=True` لتخزين المدير في النموذج للجلسة التالية.

### إضافة الطلبات

يقوم [add_request()](/docs/transformers/main/ar/main_classes/text_generation#transformers.ContinuousBatchingManager.add_request) بإرسال طلب واحد. يمكنك تقديم `request_id` أو ترك المدير يولّد معرّفًا تلقائيًا.

```py
manager.add_request(input_ids=input_ids, request_id="my_request")
```

يقوم [add_requests()](/docs/transformers/main/ar/main_classes/text_generation#transformers.ContinuousBatchingManager.add_requests) بإرسال دفعة كاملة دفعة واحدة. وهو يرتّب المدخلات تلقائيًا لتعظيم إصابات ذاكرة التخزين المؤقت للبدايات المشتركة عند تمكين مشاركة الكتل.

```py
manager.add_requests(inputs=inputs)
```

إلغاء طلب باستخدام [cancel_request()](/docs/transformers/main/ar/main_classes/text_generation#transformers.ContinuousBatchingManager.cancel_request).

```py
manager.cancel_request(request_id="my_request")
```

### معاملات أخذ العينات لكل طلب

فعّل `per_request_processors` لتطبيق `temperature` و`top_k` و`top_p` بشكل مستقل لكل طلب ضمن نفس مسار الأمامي، مما يتيح استخدام معاملات أخذ عينات مختلفة للطلبات المختلفة (على سبيل المثال، مخرجات إبداعية ذات درجة حرارة عالية مقابل مخرجات دقيقة ذات درجة حرارة منخفضة).

```py
cb_config = ContinuousBatchingConfig(per_request_processors=True)

# each request gets its own sampling parameters
manager.add_request(input_ids=inputs_a, temperature=0.9, top_p=0.95)
manager.add_request(input_ids=inputs_b, temperature=0.1, top_k=10)
```

يجب أن يكون كل معامل في [GenerationConfig](/docs/transformers/main/ar/main_classes/text_generation#transformers.GenerationConfig) بقيمة غير افتراضية من أجل إنشاء معالج logits المرتبط به وقت التشغيل. على سبيل المثال، اضبط `temperature` على قيمة أخرى غير `None` أو `1` لدعم التحكم في درجة الحرارة لكل طلب. يمكن إنشاء الطلبات التي تكون درجة حرارتها `1` بعد ذلك.

### استرجاع النتائج

تكرّر على المدير لاستلام النتائج فور وصولها.

```py
for result in manager:
    print(tokenizer.decode(result.generated_tokens, skip_special_tokens=True))
```

تسترجع [get_result()](/docs/transformers/main/ar/main_classes/text_generation#transformers.ContinuousBatchingManager.get_result) النتيجة التالية من طابور المخرجات. مرّر `request_id` لتصفية طلب محدد. إذا لم تتطابق النتيجة التالية في الطابور، تُعاد إلى الطابور وتعيد الدالة `None`.

```py
# next available result
result = manager.get_result()

# filter for a specific request
result = manager.get_result(request_id="my_request")
```

### البث

اضبط `streaming=True` على الطلب، ثم استخدم [request_id_iter()](/docs/transformers/main/ar/main_classes/text_generation#transformers.ContinuousBatchingManager.request_id_iter) للتكرار على المخرجات الجزئية أثناء توليد الرموز.

```py
from transformers.generation.continuous_batching import RequestStatus

manager.add_request(input_ids=input_ids, request_id="streamed", streaming=True)

for chunk in manager.request_id_iter(request_id="streamed"):
    token = tokenizer.decode(chunk.generated_tokens[-1:], skip_special_tokens=True)
    print(token, end="", flush=True)
    if chunk.status == RequestStatus.FINISHED:
        break
```

## ContinuousBatchingConfig

يتحكم [ContinuousBatchingConfig](/docs/transformers/main/ar/main_classes/continuous_batching#transformers.ContinuousBatchingConfig) في ذاكرة KV، والجدولة، ورسوم CUDA، واستخدام الذاكرة، وغيرها. مرّره إلى `generate_batch` أو [init_continuous_batching()](/docs/transformers/main/ar/main_classes/text_generation#transformers.ContinuousMixin.init_continuous_batching) عبر الحجة `continuous_batching_config`، بشكل منفصل عن [GenerationConfig](/docs/transformers/main/ar/main_classes/text_generation#transformers.GenerationConfig). تصف الإعدادات الثنائيتان أشياء مختلفة. فـ[GenerationConfig](/docs/transformers/main/ar/main_classes/text_generation#transformers.GenerationConfig) يركّز على النموذج ويحتوي على معاملات العينة والتوقف، بينما يركّز [ContinuousBatchingConfig](/docs/transformers/main/ar/main_classes/continuous_batching#transformers.ContinuousBatchingConfig) على العتاد ويحتوي على معاملات الذاكرة والجدولة.

> [!WARNING]
> إعداد `continuous_batching_config` على [GenerationConfig](/docs/transformers/main/ar/main_classes/text_generation#transformers.GenerationConfig) لم يعد مدعوماً، ويُصدر تحذيراً `FutureWarning`، وسيتم إزالته في الإصدار v5.19.

بشكل افتراضي، يكون `max_batch_tokens` بقيمة `8192`، محددًا بذاكرة وحدة معالجة الرسوميات المتاحة ولا يقل أبدًا عن `256`، بينما يملأ `num_blocks` الذاكرة المتبقية. استخدم الجدول أدناه لمساعدتك في اختيار الميزات المناسبة.

| ميزة | الذاكرة | معدل الإنتاجية | زمن الاستجابة |
|---|---|---|---|
| `max_memory_percent` / `page_size` | ✓ يتحكم في ميزانية KV | | |
| `max_batch_tokens` | ↑ مخازن إدخال أكبر | ✓ دفعات تمهيد أكبر | ✓ زمن TTFT عند كونه محكومًا بالتهيئة المسبقة |
| `scheduler` | | ✓ سياسة الجدولة | ✓ TTFT |
| رسوم CUDA | ↑ تخزين الرسم البياني | ✓ تقليل نفقات الإرسال | ✓ |
| الدفعة غير المتزامنة | ↑ ~2× مخازن الإدخال/الإخراج | ✓ يتداخل مع المعالج المركزي/وحدة معالجة الرسوميات | |
| التجميع | ↑ زمن الإحماء فقط | ✓ عمليات تمرير أمامي أسرع | ✓ |
| مسار فك الترميز السريع | ↑ جدول الكتل لكل طلب | ✓ خطوات فك الترميز فقط أسرع | ✓ |
| إزاحة المعالجة إلى وحدة المعالجة المركزية | ↑ ذاكرة وحدة المعالجة المركزية المثبتة | ✓ يتخطى بعض عمليات إعادة التمهيد | |
| التخزين المؤقت للبادئة | ↓ كتل KV المشتركة | ✓ يتخطى التعبئة الأولية المكررة | ✓ TTFT |
| الانتباه الصفحي | ↓ لا تجزئة | ✓ عضوية ديناميكية للدفع | |
| نافذة المنزلقة | ↓ ذاكرة KV محدودة لكل طبقة | | |
| المعالجات لكل طلب | | ✓ معلمات أخذ عينات مختلطة لكل دفعة | |
| `max_requests_per_batch` | ↓ يحدّ من مخزن القيم اللوجستية | ✓ تحديد حد لحجم الدفعة | |
| `safety_margin` | | | ✓ يحمي زمن فك الترميز |

```py
from transformers.generation import ContinuousBatchingConfig

cb_config = ContinuousBatchingConfig(
    max_memory_percent=0.8,
    page_size=256,           # KV cache page size in tokens
    scheduler_type="fifo",        # "fifo" or "prefill_first"
)

outputs = model.generate_batch(
    inputs=inputs,
    generation_config=generation_config,
    continuous_batching_config=cb_config,
)
```

### حجم صفحة ذاكرة KV

`page_size` يحدد عدد رموز KV التي تستوعبها صفحة الانتباه الكاملة الواحدة لطبقة واحدة. يجب أن يكون هذا الرقم على الأقل `4`، وإلا فإن التهيئة تثير `ValueError`. القيمة الافتراضية `256` تعمل لمعظم الأحمال.

> [!NOTE]
> تم إيقاف استخدام معامل `block_size` واستبداله بـ `page_size`.

تقليل حجم الصفحة يزيد من كفاءة إدارة المسجل، لكنه يهدر مساحة عندما يتوقف تسلسل في منتصف الصفحة. في المقابل، تُهدر الصفحات الأصغر مساحة أقل، لكنها تتطلب إدارة مسجل أكثر. عادةً لا تحتاج إلى ضبط `page_size`. إذا كان حمل عملك يحتوي على العديد من الطلبات القصيرة، جرّب قيمة أصغر. أما إذا كان يحتوي على عدد قليل من الطلبات الطويلة جداً، جرّب قيمة أكبر. راجع [إدارة الذاكرة](./continuous_batching_architecture#memory-management) لمعرفة كيفية تداخل الصفحات والكتل والمقاطع معاً.

```py
cb_config = ContinuousBatchingConfig(page_size=128)
```

### حجم دفعة التعبئة المسبقة

`max_batch_tokens` يحدد ميزانية الرموز لمرور أمامي واحد، أي الحد الأقصى لعدد رموز الاستعلام التي يعالجها النموذج دفعة واحدة. يؤدي زيادة الميزانية إلى حشد المزيد من رموز الموجز في كل عملية تعبئة مسبقة، مما يرفع معدل إنتاجية التعبئة المسبقة ويقلل زمن الوصول إلى الرمز الأول في الأحمال التي تعتمد بشكل كبير على الموجزات. يقسم المجدول الموجزات التي تتجاوز الميزانية عبر خطوات متعددة. راجع [التعبئة المسبقة المقسمة](./continuous_batching_architecture#chunked-prefill) لمعرفة كيفية معالجة الموجزات التي تتجاوز الحجم.

افتراضيًا، تكون قيمة `max_batch_tokens` هي `8192`. وتُقيَّد هذه القيمة بذاكرة وحدة معالجة الرسوميات المتاحة، حتى لا تُزاحم تensors المدخلات لكل دفعة ذاكرة KV cache، كما أنها لا تنخفض أبدًا عن `256`. على وحدة معالجة رسوميات ذات ذاكرة حرة محدودة، يُخفض هذا القيد القيمة عن `8192`.

يستمد `max_batch_tokens` و`num_blocks` من ميزانية الذاكرة نفسها، لذا فهما يتبادلان التأثير مع بعضهما البعض. ميزانية الرموز الأكبر تخصص مخازن إدخال أكبر وتترك عددًا أقل من كتل ذاكرة KV للطلبات المتزامنة أو الطويلة. ارفع قيمة `max_batch_tokens` لزيادة معدل معالجة التمهيد (prefill) عندما تتوفر لديك ذاكرة إضافية، وقلّلها لتحرير الذاكرة من أجل المزيد من كتل KV أو لتجنب أخطاء نفاد الذاكرة.

```py
cb_config = ContinuousBatchingConfig(max_batch_tokens=16384)
```

### حدود الدفعات والجدولة

يحدد `max_requests_per_batch` الحد الأقصى لعدد الطلبات التي تُنفَّذ في تمريرة أمامية واحدة. ينتج النموذج متجه logits بحجم يعتمد على عدد رموز الدفعة وحجم قاموس الكلمات، ويُحوَّل إلى `fp32` لأغراض العينة، مما يضاعف حجم الذاكرة المستهلكة. بما أن كل طلب يحتاج فقط إلى توقع الرمز التالي، فإن تقليل هذا الحد الأقصى يحافظ على صغر حجم هذا المتجه ويتجنب أخطاء نفاد الذاكرة في الدفعات التي تركز على مرحلة التهيئة (prefill) مع القواميس الكبيرة. افتراضيًا، يُضبط هذا الحد على عدد الأوامر المُرسلة، مع قيمة احتياطية قدرها 1024، ثم يُقيَّد ليلائم `max_batch_tokens` و`num_blocks`.

```py
cb_config = ContinuousBatchingConfig(max_requests_per_batch=256)
```

يحتجز `safety_margin` نسبة من سعة الكاش المتاحة للطلبات النشطة. عندما تنخفض السعة المتاحة دون `safety_margin` (وهي نسبة من إجمالي حجم الكاش)، يتوقف الجدول عن قبول طلبات جديدة ويستمر فقط في فك ترميز الطلبات الجارية بالفعل. وهذا يعطي الأولوية لإنهاء العمل النشط على بدء طلبات جديدة، مما يحمي زمن استجابة فك الترميز ويؤخر [offloading](./continuous_batching_architecture#offloading). يجب أن تقع القيمة بين `0` و`1`، حيث يؤدي تحديد `0` إلى تعطيل الهامش.

```py
cb_config = ContinuousBatchingConfig(safety_margin=0.15)
```

يعتمد الافتراضي على مُجدول المهام. فبالنسبة إلى مُجدول FIFO، يكون `0.15`، وبالنسبة إلى `prefill_first`، يكون `0.0`. راجع [القبول](./continuous_batching_architecture#admission) لمعرفة كيفية تفاعل الهامش مع الجدولة.

### احتمالات السجل

يعيد [ContinuousBatchingConfig](/docs/transformers/main/ar/main_classes/continuous_batching#transformers.ContinuousBatchingConfig) احتمال السجل (log probability) لكل رمز مُولَّد عند تعيين `return_logprobs=True`. وهذا مفيد في تعزيز التعلم (RL) حيث تُعد قيم logprobs مدخلاً لبعض حلقات التدريب.

```py
cb_config = ContinuousBatchingConfig(return_logprobs=True)

# generate_batch()

for request_id, output in outputs.items():
    for token_id, log_prob in zip(output.generated_tokens, output.logprobs):
        token = tokenizer.decode([token_id])
        print(f"{token} | logprob: {log_prob}")
```

### رسوم CUDA

تُزيل رسوم CUDA الرسوم الإضافية المرتبطة بإرسال الأوامر من وحدة المعالجة المركزية (CPU) عن طريق تسجيل مخطط تنفيذ وحدة معالجة الرسوميات (GPU) مرة واحدة ثم إعادة تشغيله للدفعات التي تتطابق أشكالها. فعّلها صراحةً باستخدام `use_cuda_graph=True`.

```py
cb_config = ContinuousBatchingConfig(use_cuda_graph=True)
```

عند التفعيل، يقوم المدير بتعبئة أطوال الاستعلام وقيم KV إلى فترات ثابتة بحيث تتكرر الأشكال وتُعاد استخدام الرسوم البيانية. تقلل القيم الأصغر لـ `q_padding_interval_size` و`kv_padding_interval_size` من هدر الحسابات المخصصة للتعبئة، لكن هذا يعني وجود أشكال فريدة أكثر يجب على الرسم البياني تسجيلها وتخزينها، مما يستهلك ذاكرة أكبر.

```py
cb_config = ContinuousBatchingConfig(
    use_cuda_graph=True,
    q_padding_interval_size=64,
    kv_padding_interval_size=16384,
)
```

### الدفعة غير المتزامنة

يتداخل الدفع غير المتزامن (Async batching) بين جدولة وحدة المعالجة المركزية (CPU) للدفعة التالية وحساب وحدة معالجة الرسوميات (GPU) للدفعة الحالية. يتطلب هذا الأمر استخدام مخططات CUDA (CUDA graphs) ويضاعف تقريبًا ذاكرة الفيديو (VRAM) المستخدمة لمصفوفات الإدخال.

```py
cb_config = ContinuousBatchingConfig(
    use_cuda_graph=True,
    use_async_batching=True,
)
```

### التجميع

يطبّق `default_compile_level` على عمليات التمرير الأمامي (forward passes) للنموذج `torch.compile`. تقوم عملية التجميع (compilation) بتبديل تكلفة إحماء تُدفع مرة واحدة مقابل تسريع عمليات التمرير الأمامي أثناء التوليد. تؤدي المستويات الأعلى إلى تنفيذ تحسينات أكثر عدوانية، مما يحسّن معدل الإنتاجية (throughput) لكنه يطيل مدة الإحماء. حافظ على المستوى منخفضًا أثناء الاختبارات وتكرار قياس الأداء (benchmark iteration)، وارفعه في حالات التشغيل (serving) طويلة الأمد حيث تُعوَّض تكلفة الإحماء عبر العديد من الطلبات.

يتراوح المستوى من `0` إلى `3`. المستوى `0` هو الافتراضي ويتخطى التجميع بالكامل.

| المستوى | `mode` | `dynamic` | المفاضلة |
|---|---|---|---|
| 0 | — | — | بدون تجميع (الافتراضي)، أسرع بدء تشغيل |
| 1 | `default` | `True` | تحسين متواضع في السرعة، فترة إحماء قصيرة |
| 2 | `max-autotune-no-cudagraphs` | `True` | سرعة أكبر، فترة إحماء أطول |
| 3 | `max-autotune-no-cudagraphs` | `False` | أعلى معدل إنتاجية، أطول فترة إحماء |

```py
cb_config = ContinuousBatchingConfig(default_compile_level=1)
```

توفّر هذه المستويّة إعداد [CompileConfig](/docs/transformers/main/ar/internal/generation_utils#transformers.CompileConfig) افتراضيًا لمساري التنفيذ varlen وdecode. ولا تنطبق إلا على المسار الذي لا يحتوي على إعداد صريح، لذا فإن `varlen_compile_config` و`decode_compile_config` لها الأولوية عند ضبطها. وفي ظل FlashAttention، يتخطّى مسار varlen عملية التجميع لأن `max_length_k` يُسبّب إعادة تجميع متكررة، وبالتالي فإن المستويّة تؤثر فقط على مسار decode في تلك الحالة.

### مسار فك الترميز السريع

عندما يحتوي الدفعة على طلبات فك ترميز فقط (رمز استعلام واحد لكل تسلسل)، يمكن للمدير إرسال الطلب إلى نواة `flash_attn_with_kvcache` بدلاً من نواة الطول المتغير. هذا أسرع من مسار varlen لأن النواة تقرأ وتكتب ذاكرة KV المقسمة إلى كتل في مكانها عبر جدول كتل بدلاً من المرور عبر تحديث يدوي. راجع [الانتباه المقسم إلى كتل](./paged_attention) للتفاصيل على مستوى النواة.

يُحدَّد حجم المسار السريع بواسطة `max_blocks_per_request`، وهو الذي يحدد أبعاد جدول الكتل لكل طلب. افتراضيًا، يتم استنتاج هذا الحجم تلقائيًا. إذا تم ضبط `max_prompt_length` و`max_generated_length` على المُدير، فإن جدول الكتل يُحدَّد حجمه ليتناسب مع أقصى طول للتسلسل. وإلا، يُستخدم حد افتراضي احتياطي (32 كتلة لكل طلب).

اضبط `max_blocks_per_request` على قيمة محددة لتحديد حجم جدول الكتل صراحةً. يكون هذا مفيدًا عندما تعرف الحد الأقصى لطول التسلسل لكل طلب وتريد تحديد التكلفة الذاكرة لجدول الكتل.

```py
cb_config = ContinuousBatchingConfig(max_blocks_per_request=64)
```

اضبط `max_blocks_per_request=0` لتعطيل المسار السريع وإجبار كل دفعة على المرور عبر نواة varlen. يستعيد هذا السلوك السابق للقيمة الافتراضية، وهو مفيد عندما لا يتوفر المسار السريع لتنفيذ الانتباه لديك (كما يقوم المدير بتعطيله تلقائيًا عندما لا يمكن استخدام النواة الأساسية).

```py
cb_config = ContinuousBatchingConfig(max_blocks_per_request=0)
```

تعتمد المسار السريع على نواة `flash_attn_with_kvcache`، وهي متاحة لمجموعتين من تركيبات الأجهزة وتنفيذ الانتباه.

| الجهاز | `attn_implementation` |
|---|---|
| CUDA | `flash_attention_2` أو `flash_attention_3` |
| XPU | [flash_attention_2](https://huggingface.co/kernels-community/flash-attn2) |

في أي تركيبة أخرى، أو عندما لا يمكن استيراد النواة، يلجأ المدير إلى مسار varlen. يسجّل تحذيرًا فقط عند تعيين `max_blocks_per_request` بشكل صريح.

يدعم الانتباه الكامل جداول كتل النواة، بينما لا يدعم الانتباه المنزلق ذلك. إذا احتوى النموذج على أي طبقات انتباه منزلق، بما في ذلك النماذج الهجينة التي تستخدم أيضاً الانتباه الكامل، فإن التهيئة تفرض قيمة `max_blocks_per_request` على `0`، وتُستبدل أي قيمة غير صفرية تحددها. ثم يسجّل المدير أن مسار فك الترميز السريع غير متاح لأن بعض أنواع الانتباه في النموذج لا تدعم جداول كتل النواة.

### إزاحة المعالجة إلى وحدة المعالجة المركزية

ينسخ نقل المعالجة إلى وحدة المعالجة المركزية (CPU) كتل ذاكرة KV المُستبعَدة إلى مخزن CPU مثبّت مُخصَّص مسبقًا عندما تمتلئ ذاكرة KV على وحدة معالجة الرسوميات (GPU). بعد أن يصبح مساحة التخزين متاحة، ينسخ المدير الكتل مرة أخرى إلى وحدة معالجة الرسوميات (GPU) ويستأنف الطلب دون إعادة حساب موجهه (prompt) والرموز المولَّدة.

اضبط `cpu_offload_space` على مساحة التبديل في المعالج المركزي بوحدة غيغابايت. القيمة الافتراضية، `0.0`، تعطل نقل المهام إلى المعالج المركزي.

```py
cb_config = ContinuousBatchingConfig(cpu_offload_space=8.0)
```

بشكل افتراضي، يحدّ `cpu_offload_space_safety_threshold=0.8` المساحة المطلوبة إلى 80% من ذاكرة الوصول العشوائي المتاحة في النظام عند تثبيت `psutil`. اضبط `cpu_offload_space=None` لتحديد حجم بركة التبديل من عتبة الأمان.

### مهلة انتهاء الوقت للتوازي على مستوى الموتر

في إطار توازي الموترات، ينشئ المُدير مجموعة اتصال على وحدة المعالجة المركزية لتنسيق إرسال الطلبات وإلغائها وإيقاف التشغيل عبر الرتب. يحدد `cpu_group_timeout` المدة القصوى التي يمكن أن تتوقف فيها عملية جماعية على هذه المجموعة قبل أن ينهار العملية. إذا تعطلت رتبة واحدة، يمنع المهلة الزمنية الرتب الأخرى من الانتظار إلى الأبد.

اضبط مهلة زمنية أطول للأحمال التي تُصدر عمليات جماعية نادرة الحدوث، أو مرّر `None` لتعطيلها.

```py
cb_config = ContinuousBatchingConfig(cpu_group_timeout=600.0)
```

### التخزين المؤقت للبادئة

عندما تتشارك طلبات متعددة بادئًا مشتركًا، مثل موجه النظام، يعيد المدير استخدام كتل ذاكرة KV الخاصة بها بدلاً من إعادة حسابها. القيمة الافتراضية لـ `allow_block_sharing` هي `True`. يكون مشاركة البادئ نشطة فقط عندما تدعم جميع مُخصِّصي أنواع الانتباه المشاركة، لذا فإن النماذج التي تعتمد كليًا على الانتباه فقط هي التي تستخدمه. تُعطَّل هذه الميزة في النماذج الانزلاقية البحتة والنماذج الهجينة حتى عندما تكون قيمة `allow_block_sharing` هي `True`.

```py
cb_config = ContinuousBatchingConfig(
    allow_block_sharing=True,  # default
)
```

## اختر واجهة خلفية للانتباه

Continuous batching supports FlashAttention, SDPA, and `"paged|eager"`. Set `attn_implementation` when you load the model.

| الواجهة الخلفية | `attn_implementation` | المتطلبات |
|---|---|---|
| FlashAttention 2 | "flash_attention_2" | حزمة `flash-attn` أو `kernels` |
| FlashAttention 3 | "flash_attention_3" | حزمة `flash-attn-3` أو `kernels` |
| SDPA (أصلي في PyTorch) | "sdpa" | لا شيء |
| مباشر | "paged&#124;eager" | لا شيء |

```py
model = AutoModelForCausalLM.from_pretrained(
    "Qwen/Qwen3-4B",
    attn_implementation="flash_attention_2",
    device_map="auto",
    dtype=torch.bfloat16,
)
```

يعمل الدفع المستمر (Continuous batching) بشكل أسرع مع FlashAttention مقارنةً بـ eager أو SDPA، وذلك بشكل رئيسي لأن FlashAttention لا يحتاج إلى قناع انتباه (attention mask). إذا كان النموذج يدعم FlashAttention، فإن النموذج المحمّل باستخدام `"eager"` أو `"sdpa"` ينتقل إلى FlashAttention 3، أو إلى FlashAttention 2 إذا لم يكن FlashAttention 3 مثبّتًا، مع تسجيل تحذير. أما إذا لم يكن أيٌّ من النسختين مثبّتًا، فلا يتغير الواجهة الخلفية (backend).

للحفاظ على eager أو SDPA، على سبيل المثال عند إجراء الاختبارات، اضبط `auto_switch_to_flash=False` في [ContinuousBatchingConfig](/docs/transformers/main/ar/main_classes/continuous_batching#transformers.ContinuousBatchingConfig). في كل مرة يبقى فيها الخادم الخلفي `"eager"`، يعمل التقطيع المستمر (continuous batching) بـ `"paged|eager"` بدلاً من ذلك.

## توازي الموتر

بالنسبة إلى النماذج التي تكون كبيرة جدًا بحيث لا تتسع على وحدة معالجة رسومية واحدة، قسّم الأوزان عبر الأجهزة باستخدام توازي الموترات. اضبط عدد الأجهزة باستخدام `DistributedConfig(tp_size=N)`. يقرأ الدفع المستمر حجم توازي الموترات من النموذج لتحديد حجم ذاكرة KV الصفحية لكل شريحة. راجع [توازي الموترات](./tensor_parallelism) للاطلاع على قائمة البنى المدعومة وكيفية عمل التقسيم.

```py
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer, DistributedConfig
from transformers.generation import ContinuousBatchingConfig, GenerationConfig

distributed_config = DistributedConfig(tp_size=4)
model = AutoModelForCausalLM.from_pretrained(
    "Qwen/Qwen3-32B",
    attn_implementation="flash_attention_2",
    distributed_config=distributed_config,
)
tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen3-32B")

inputs = [tokenizer.encode(p) for p in ["What's up?", "Name a cat breed."]]
generation_config = GenerationConfig(max_new_tokens=64, eos_token_id=tokenizer.eos_token_id)

outputs = model.generate_batch(inputs=inputs, generation_config=generation_config)
```

شغّل السكربت باستخدام `torchrun`، مع ضبط `--nproc-per-node` على عدد وحدات معالجة الرسوميات التي تريد توزيع الشرائح عليها.

```shell
torchrun --nproc-per-node 4 cb_tp.py
```

يجب أن يكون حجم التوازي للتينسور قاسماً لعدد رؤوس المفاتيح والقيم `num_key_value_heads` في النموذج (تحقق من إعدادات النموذج). وإلا، فسيُطلق ذاكرة الصفحات المخزّنة خطأً عند بدء التشغيل، لذا اختر قيمة مناسبة لـ `--nproc-per-node`.

> [!WARNING]
> لا تضبط `device_map` مع `distributed_config`. يتعارض الاثنان لأن `device_map` يضع الوحدات الكاملة على وحدات معالجة رسومات محددة، بينما يقسم توازلي المصفوفات (Tensor Parallelism) نفس المعاملات عبر جميع وحدات معالجة الرسومات.

## انتباه النافذة المنزلقة

تعمل النماذج التي تستخدم انتباه النافذة المنزلقة (Mistral، Gemma 2) مع الدفع المستمر. تستخدم طبقات النافذة `SlidingAttentionCacheAllocator`، الذي يحتفظ فقط بنافذة ثابتة من الرموز الحديثة من خلال إعادة تدوير مجموعة صغيرة من الصفحات. يأتي نوع الانتباه من `layer_types` أو `sliding_window` الخاص بالنموذج، وليس من [ContinuousBatchingConfig](/docs/transformers/main/ar/main_classes/continuous_batching#transformers.ContinuousBatchingConfig).

```py
from transformers import AutoConfig, AutoModelForCausalLM

config = AutoConfig.from_pretrained("google/gemma-2-2b")
config.sliding_window = 4096

model = AutoModelForCausalLM.from_pretrained(
    "google/gemma-2-2b",
    config=config,
    attn_implementation="sdpa",
    device_map="auto",
    dtype=torch.bfloat16,
)
```

يتم تعطيل [تخزين البادئة](#prefix-caching) و[مسار فك الترميز السريع](#decode-fast-path) في أي وقت يكون فيه الانتباه المنزلق حاضراً، بما في ذلك النماذج الهجينة التي تحتوي أيضاً على طبقات انتباه كاملة.

## الخطوات التالية

- يتناول [منشور المدونة حول الدفع المستمر](https://huggingface.co/blog/continuous_batching) تخزين KV في ذاكرة مؤقتة، والتعبئة المقطّعة، والجدولة الديناميكية، مع أرقام معايير الأداء.
- للنظر بعمق أكبر في كيفية عمل نظام الدفع المستمر، راجع وثيقة [بنية الدفع المستمر](./continuous_batching_architecture).

