Transformers documentation
التوازي الخبير
التوازي الخبير
التوازي بين الخبراء هو استراتيجية توازي مخصصة لنماذج مزيج الخبراء (MoE). يتواجد كل خبير في طبقة التغذية الأمامية الخاصة به على مُسرِّع عتاد مختلف. يقوم الموجِّه بإرسال الرموز إلى الخبراء المناسبين وجمع النتائج. يتيح هذا النهج توسيع النماذج إلى أعداد أكبر بكثير من المعلمات دون زيادة تكلفة الحساب، لأن كل رمز يُفعِّل عدداً قليلاً فقط من الخبراء.
DistributedConfig
فعّل توازي الخبراء باستخدام فئة DistributedConfig والحجة ep_size. تعتمد معظم نماذج MoE افتراضيًا على token dispatch، لذا يمكن تعيين ep_size بشكل مستقل عن tp_size. لا تزال بعض النماذج، مثل Llama 4 و Gemma 4، تعتمد افتراضيًا على الأقنعة و all-reduce ("ep_router" و "moe_tp_experts" في model.ep_plan). كما يتوفر استخدام الأقنعة على أي نموذج مع تجاوز ep_plan، ويتطلب ذلك ep_size=tp_size حتى يتلقى كل رتبة في مجموعة الخبراء الرموز نفسها.
import os
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
from transformers.distributed.configuration_utils import DistributedConfig
distributed_config = DistributedConfig(
tp_size=int(os.environ["WORLD_SIZE"]),
ep_size=int(os.environ["WORLD_SIZE"]),
)
model = AutoModelForCausalLM.from_pretrained(
"openai/gpt-oss-120b",
distributed_config=distributed_config,
)يحدد كل نموذج MoE خطتين في ملفه الإعدادي: base_model_tp_plan للوحدات الكثيفة وbase_model_ep_plan للخبراء. وتُعرض هاتان الخطتان على النموذج المحمّل على شكل model.tp_plan وmodel.ep_plan. عند استخدام tp_size > 1 وep_size > 1، تُطبَّق الخطتان معًا: حيث يقوم خط التوازي على مستوى المصفوفات بتقسيم وحدات الانتباه ووحدات MLP الكثيفة، بينما يقوم خط التوازي على مستوى الخبراء بتقسيم الخبراء. ولأن قواعد EP لها الأولوية على قواعد TP بالنسبة لنفس الوحدات، فإن أوزان الخبراء تُقسَّم مرة واحدة فقط، وذلك وفق خط EP. وفي خط EP، يقوم نمط GroupedGemmParallel بتقسيم أوزان الخبراء على طول بُعد الخبراء بحيث يحمّل كل rank الخبراء المحليين لديه فقط، بينما يقوم ep_router بإخفاء الخبراء الموجودة على ranks أخرى قبل أن يجمع all-reduce مخرجات الخبراء.
يُطبَّق tp_plan فقط عندما يكون tp_size > 1، وep_plan فقط عندما يكون ep_size > 1. عند تفعيل TP وتعطيل EP، يُطبَّق خطة TP الكاملة، بما في ذلك قواعد الخبراء.
تختص قاعدة الأمامي الخبير في ep_plan بكيفية وصول الرموز إلى الخبراء:
| قاعدة | آلية | تخطيط |
|---|---|---|
"moe_tp_experts" مع "ep_router" على الموجّه | التخفي والجمع الشامل: يقوم كل رتبة بتشغيل خبرائها المحليين على الدفعة الكاملة، ويقوم الموجّه بتخفي الآخرين، ثم يجمع الجمع الشامل المخرجات | ep_size=tp_size |
"ep_dispatch_experts" | توزيع الرموز: يحتفظ كل رتبة برموزها الخاصة ولا يتبادل إلا أزواج (الرمز، الخبير) الموجَّهة عبر مجموعتين من عمليات all-to-all | ep_size مضاعف لـ tp_size يقسم fsdp_size * tp_size |
استخدام
enable_expert_parallel=Trueدون تحديدep_sizeأصبح غير مدعوم، ويُصدر تحذيرًا من نوعFutureWarning. يقوم هذا الإعداد بتقسيم الخبراء فقط، تمامًا كما فيep_size=tp_size, tp_plan={}.
شغّل سكربت الاستدلال الخاص بك باستخدام torchrun. يجب أن يساوي عدد العمليات tp_size * fsdp_size * pp_size، وأن يقسم ep_size عدد الخبراء قسمة تامة.
torchrun --nproc-per-node 8 your_script.py
التجاوز على الخطط
مرّر tp_plan={...} أو ep_plan={...} إلى DistributedConfig لتجاوز قواعد محددة في الخطط المحددة مسبقًا. تُحفظ القواعد غير المحددة، وتُخزَّن الخطط المدمجة على النموذج. يجب أن يطابق كل مفتاح وحدةً أو معاملًا أو عنصرًا موجودًا في الخطة؛ وإلا فسيُطلق التحميل ValueError قبل تقسيم أي شيء. استخدم المسار الكامل كما يظهر من النموذج المحمّل، لذا model.layers.* لنموذج LM السببي وlayers.* لنموذه الأساسي.
distributed_config = DistributedConfig(
tp_size=4,
ep_size=4,
tp_plan={"model.layers.*.self_attn.q_proj": "colwise_rep"},
ep_plan={"model.layers.*.mlp.experts.down_proj": "grouped_gemm"},
)تقديم خطة لا يستنتج أحجام التوازي: اضبط tp_size وep_size بشكل صريح.
تعتمد معظم نماذج MoE افتراضيًا على "ep_dispatch_experts". لاستخدام الأقنعة (masking) و all-reduce بدلاً من ذلك، اضبط ep_size=tp_size وأعد كتابة كلٍّ من قواعد التوجيه (router) وقواعد الأمامية (forward) للخبراء (يعتمد اسم وحدة التوجيه على النموذج، مثل mlp.router في gpt-oss):
distributed_config = DistributedConfig(
tp_size=4,
ep_size=4,
ep_plan={
"model.layers.*.mlp.gate": "ep_router",
"model.layers.*.mlp.experts": "moe_tp_experts",
},
)وعلى العكس من ذلك، تجاوز قاعدة الأمامية للخبراء في نموذج يستخدم الخطة التي تعتمد على الأقنعة باستخدام "ep_dispatch_experts" لتوزيع الرموز. يتم تجاهل قاعدة الموجّه في هذه الحالة، لأن التوزيع يحتاج إلى معرفات الخبراء العالمية لإيجاد مالك كل خبير.
توزيع الرموز
With token dispatch, each rank trains on its own part of the batch. At every MoE layer, a rank routes its tokens, sends each (token, expert) pair to the rank that owns the expert with an all-to-all, runs its local experts on what it receives, gets the results back with a second all-to-all and combines them with the routing weights. Only the routed activations and expert outputs travel, and no rank computes experts for tokens it does not own.
from transformers import AutoModelForCausalLM
from transformers.distributed import DistributedConfig
distributed_config = DistributedConfig(
tp_size=1,
fsdp_size=8,
ep_size=4,
)
model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen3-30B-A3B", distributed_config=distributed_config)عند tp_size=1، يجب أن يكون ep_size قاسماً لـ fsdp_size وعدد الخبراء، ولا يكون الانتباه مقيداً بـ num_key_value_heads. أما بالنسبة لباقي النموذج:
- تُقسَّم المعاملات خارج الخبراء باستخدام FSDP2 عبر
fsdp، مما يقلل من تدرجاتها. - تُقسَّم الخبراء عبر
ep، وعندما يكونefsdp_size = fsdp_size * tp_size // ep_sizeأكبر من واحد، تُقسَّم أيضًا عبرefsdpباستخدام تقسيم FSDP. وهي دائمًا مُغلَّفة بـ FSDP، لذا فإنfsdp_mixed_precisionوfsdp_cpu_offloadتنطبق عليها أيضًا، وsave_pretrained() تجمعها مثل أي معامل آخر. - يحتوي مجموعة التوازي الخبير على
ep_size / tp_sizeدفعات، لذا فإن تدرج الخبير هو مجموع على ذلك العدد من الدفعات. تقسيمefsdpيقسم علىfsdp_sizeبدلاً من حجم مجموعته، مما يعطي متوسط FSDP2 لكل دفعة الذي تتخذه للوحدات الكثيفة. - يعالج كل خبير محلي أيضًا صفًا واحدًا من الحشو الصفري في كل طبقة. أما المرتبة التي لم تتلقِ خبراؤها أي رموز، فإنها تشارك لا تزال في عملية all-to-all العكسية وتقليل تدرجات الخبراء.
كيف يتم دمج الأحجام
tp_size * fsdp_sizeهو عدد العمليات.ep_sizeلا يضيف شيئًا: فهو يعيد تجميع نفس الرتب لأوزان الخبراء فقط.- يقسم
ep_sizeقائمة الخبراء إلىep_sizeكتل. يحسب كل رتبةnum_experts / ep_sizeمن الخبراء، وتحتفظep_sizeرتب متتالية بمجموعة كاملة واحدة. تلك المجموعة من الرتب هي المجموعة التي يعمل فيها all-to-all. efsdp_size = fsdp_size * tp_size / ep_sizeهو عدد النسخ الكاملة الموجودة من مجموعة الخبراء. تقوم الرتب الموجودة في نفس الموقع في النسخ المختلفة بتجزئة هؤلاء الخبراء من أجل الذاكرة، ثم تُوسط تدرجاتهم، تماماً كما تفعل FSDP مع الوحدات الكثيفة.- يعتمد الدفعة التي يحتفظ بها كل رتبة على
fsdpفقط. تتكوّن الرتب المتتالية من مجموعة TP وتحصل على نفس الدفعة؛ بينما تحصل مجموعاتfsdp_sizeعلى دفعات مختلفة.
ثماني عمليات، tp_size=2, fsdp_size=4، ثمانية خبراء:
rank 0 1 2 3 4 5 6 7 batch [====B0====] [====B1====] [====B2====] [====B3====] one batch per TP pair tp 0 1 0 1 0 1 0 1 ep_size=2 E0-3 E4-7 E0-3 E4-7 E0-3 E4-7 E0-3 E4-7 group = a TP pair, efsdp_size=4 ep_size=4 E0E1 E2E3 E4E5 E6E7 E0E1 E2E3 E4E5 E6E7 group = two pairs, efsdp_size=2 ep_size=8 E0 E1 E2 E3 E4 E5 E6 E7 group = all ranks, efsdp_size=1
ينجم عن الصورة عددان:
- داخل مجموعة EP، يوجد كل رمز
tp_sizeمرات، مرة واحدة لكل رتبة من الزوج الذي يحمل دفعته. ولا يعتمد هذا علىep_size. - تحتوي مجموعة EP على
ep_size / tp_sizeدفعات مختلفة. وهذا هو العدد الذي تُجمَّع عليه تدرّجات الخبير.
مع توازي الموترات
اضبط tp_size > 1 لتقسيم الوحدات الكثيفة وفق خطة TP بينما تستخدم الخبراء الإرسال. على ثمانية عمليات:
distributed_config = DistributedConfig(
tp_size=2,
fsdp_size=4,
ep_size=4,
)تستقبل كل زوج من رتب TP الدفعة (batch) نفسها، لأن توازي الموترات (tensor parallelism) يكرر التفعيلات (activations) داخل الزوج. إذا أرسلت كلتا الرتب جميع رموزها (tokens)، فإن الرتبة التي تمتلك خبيرًا (expert) ستتلقى كل رمز مرتين، وتحسبه مرتين، وستتضاعف تدرج أوزانه (weight gradient). نظرًا لأن الخبراء كاملون على رتبة واحدة، فلا يمكن تقسيم النسخة المكررة عبر الأوزان، وغالبًا ما تكون الرتبة المالكة رتبة أخرى، فلا يمكن حل المشكلة عبر الملكية كما تفعل عملية الإخفاء (masking). لذلك يقسم الزوج الصفوف: ترسل كل رتبة TP جزءًا منفصلًا 1 / tp_size من الرموز، وتعود النتائج إلى الرتبة التي أرسلتها، ثم تعيد عملية all-reduce على الزوج للنصفين المملوءين بالصفر استعادة المخرجات المكررة التي تتوقعها الطبقة التالية. يتم التقسيم حسب tp_size وليس ep_size، لأن الرتب التي تحمل دفعة فقط هي التي يمكنها إرسالها. تمتد مجموعات الخبراء عبر أربع رتب، وكل خبير مقسّم عبر FSDP على efsdp_size = 2 رتبة، بينما تمتد مجموعة FSDP للجذع (trunk) عبر أربع رتب. لا تزال قيود TP المعتادة للنموذج، مثل قابلية رؤوس الانتباه (attention-heads) للقسمة، تنطبق على الوحدات الكثيفة (dense modules). قد تكون شرائح الرموز غير متساوية أو فارغة، بما في ذلك أثناء فك ترميز رمز واحد.
لا يمكن دمج توزيع الرموز (Token dispatch) مع توازي الخطوط (pipeline parallelism) بعد؛ استخدم pp_size=1 (لم يتم الاختبار بعد)
تستخدم كل من هذه الإعدادات ثمانية وحدات معالجة رسومية (GPU):
| الإعداد | النتيجة |
|---|---|
DistributedConfig(tp_size=4, fsdp_size=2, ep_size=4) | التوزيع عبر مجموعات TP من أربعة، حيث تقطع كل مجموعة دفعتها إلى أربعة (الخطة الافتراضية)؛ ما لم تحدد ep_plan لاستخدام EP المقنّع القديم |
DistributedConfig(tp_size=1, fsdp_size=8, ep_size=4) | Dispatch مع دفعة مستقلة على كل رتبة، دون تقطيع، وخبراء مُقسَّمين عبر أزواج من الرتب باستخدام FSDP. |
DistributedConfig(tp_size=2, fsdp_size=4, ep_size=4) | أرسل باستخدام زوج TP لكل دفعة، حيث يقسم كل زوج دفعته إلى نصفين؛ دفعتان لكل مجموعة خبراء. |
DistributedConfig(tp_size=8, ep_size=8) | أرسل مع مشاركة كل رتبة دفعة واحدة، مقسّمة إلى ثمانية، أو استخدم الإخفاء (masking) وجميع الاختزال (all-reduce) لخطة مخفية. |
لا يأخذ Trainer بعد في الحسبان إرسال الرموز: فعدّ الدفعات والرموز يفترض تخطيط all-reduce، حيث تتشارك رتب مجموعة TP دفعة واحدة وتوجد
fsdp_sizeشظايا موازية للبيانات. تأتي دعم Trainer للإرسال في متابعة لاحقة.
الدمج مع FSDP2
يقوم توازي الموترات وتوازي الخبراء بتقسيم الأوزان عبر tp، لكن حالة المُحسِّن (optimizer) والوحدات التي لا تخضع لقاعدة ما تبقى مكررة على كل رتبة ضمن المجموعة، مما يحد من حجم النموذج الذي يمكن تدريبه. أضف FSDP2 على بُعد شبكة ثانٍ باستخدام fsdp_size. مع استخدام الأقنعة (masking) و all-reduce، حافظ على ep_size=tp_size ومرر `ep_plan={“layers..mlp.gate”: “ep_router”, “layers..mlp.experts”: “moe_tp_experts”}“.
from transformers import AutoModelForCausalLM
from transformers.distributed import DistributedConfig
distributed_config = DistributedConfig(
tp_size=4,
ep_size=4, # expert parallel size, must match tp_size with masking and all-reduce
fsdp_size=2, # data parallel shards
ep_plan={
"model.layers.*.mlp.gate": "ep_router",
"model.layers.*.mlp.experts": "moe_tp_experts",
},
)
model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen3-30B-A3B", distributed_config=distributed_config)حمّل النموذج كما هو معتاد، ثم درّبه باستخدام Trainer. يقوم هذا بإيجاد معيار التدرج عبر كلا الشبكتين ومنح كل شبكة مجموعة معلمات خاصة بها في المُحسِّن. تجمع save_model() الأوزان المجزأة في نقطة تحقق عادية. يتطلب هذا accelerate>=1.12 حتى يتمكن Trainer من عكس tp_size وfsdp_size إلى ~Accelerate.ParallelismConfig.
يقارن الجدول أدناه التدريب باستخدام EP فقط مع التدريب ثنائي الأبعاد EP+FSDP2 على 8 وحدات GPU من نوع H100. يتكون عبء العمل من الضبط الكامل لنموذج Qwen3-30B-A3 بدقة bf16 عند طول تسلسل يبلغ 2048. تقلل شظايا FSDP الإضافية من ذروة الذاكرة، وتنخفض سرعة المعالجة (رموز/ثانية) قليلاً لأن FSDP2 يقوم بجمع (all-gathers) وتشتيت (reduce-scatters) الخبراء عبر fsdp.
| الإعداد | رموز/ثانية/وحدة معالجة رسومية | ذروة الذاكرة/وحدة معالجة الرسوميات |
|---|---|---|
tp_size=8 | 3485 | 38.6 GB |
tp_size=4, fsdp_size=2 | 2900 | 34.2 GB |
tp_size=2, fsdp_size=4 | 2830 | 32.3 GB |
لا يُدعَم استئناف التدريب من نقطة تحقق بعد للنماذج التي تُقسَّم عند التحميل، لذا يقبل Trainer فقط
save_only_model=Trueأوsave_strategy="no"لها.
مرجع الواجهة البرمجية
فئة transformers.DistributedConfig
< source >( tp_size: int | None = Nonetp_plan: typing.Union[dict[str, str], typing.Literal['auto'], NoneType] = Noneenable_sequence_parallel: bool = Falseenable_expert_parallel: bool = Falsefsdp_size: int | None = Nonefsdp_plan: dict[str, str] | None = Nonefsdp_cpu_offload: bool = Falsefsdp_mixed_precision: bool = Falsepp_size: int | None = Noneep_size: int | None = Noneep_plan: dict[str, str] | None = None )
المعاملات
- tp_size (
int، اختياري) — عدد الأجهزة للتوازي على مستوى الموترات. إذا كانNoneوتم تعيينtp_plan، فإن القيمة الافتراضية هيWORLD_SIZE // (other_parallel_size). إذا كانNoneولم يتم تعيينtp_plan، فإن القيمة الافتراضية هي 1. - tp_plan (
dict[str, str]أو"auto"، اختياري) — خطة تقسيم التوازي على مستوى المصفوفات. مرّر"auto"، أو اتركهNoneعند ضبطtp_size، لاستخدامbase_model_tp_planالمُعرّف مسبقًا للنموذج. مرّر قاموسًا لتجاوز قواعد محددة في تلك الخطة؛ تُحفظ القواعد غير المحددة. تطبيق قاموس فارغ يعني عدم تطبيق أي قاعدة لتوازي المصفوفات. - enable_sequence_parallel (
bool، اختياري، القيمة الافتراضيةFalse) — مخصص للتوازي التسلسلي. لم يتم ربطه بعد. - enable_expert_parallel (
bool، اختياري، القيمة الافتراضيةFalse) — مُتقادم، أُزيل في الإصدار v5.21. بدونep_size، يكون مطابقًا لـep_size=tp_size, tp_plan={}: خطة التوازي بين الخبراء وحدها عبرtp_sizeمن الرتب. القيمة الصريحة لـep_sizeلها الأولوية. لا يغيّر هذا العلم قيمةtp_sizeأوfsdp_size. - fsdp_size (
int، اختياري) — عدد الأجهزة الخاصة بـ FSDP (التوازي في البيانات). إذا كانتNoneوتم تعيينtp_size، فإن القيمة الافتراضية هي 1. - fsdp_plan (
dict[str, str], اختياري) — خطة تجزئة FSDP2. اتركهNoneلاستخدامbase_model_fsdp_planالمحدد مسبقًا في النموذج و_fsdp_planعلى مستوى الفئة. مرر قاموسًا لتجاوز قواعد فردية؛ وتُحفظ القواعد غير المحددة. يُطبَّق فقط عندماfsdp_size > 1. - fsdp_cpu_offload (
bool، اختياري، القيمة الافتراضيةFalse) — ما إذا كان سيتم تفعيل نقل المعالجة إلى وحدة المعالجة المركزية (CPU) لـ FSDP2. - fsdp_mixed_precision (
bool، اختياري، القيمة الافتراضيةFalse) — ما إذا كان سيتم تفعيل الدقة المختلطة لـ FSDP2. - pp_size (
int، اختياري) — عدد الأجهزة للتوازي في خط الأنابيب. إذا كانNoneوتم ضبط وضع توازي آخر، يكون الافتراضي 1. - ep_size (
int، اختياري) — عدد الأجهزة التي تمتلك شرائح خبراء مميزة. القيمة الافتراضية هي 1. اضبطه صراحةً لتفعيل EP. يجب أن يكون مضاعفًا لـtp_sizeوقاسمًا لـfsdp_size * tp_size. تتطلب خطط تقليل الخبراء الكلّيةep_size=tp_size؛ كما يسمح توزيع الرموز ("ep_dispatch_experts") أيضًا بـep_size > tp_size. - ep_plan (
dict[str, str]، اختياري) — خطة تجزئة التوازي بين الخبراء. اتركهNoneلاستخدامbase_model_ep_planالمُعرَّفة مسبقًا في النموذج. مرِّر قاموسًا لتجاوز قواعد فردية في تلك الخطة؛ وتُحفظ القواعد غير المحددة. تُطبَّق فقط عندما يكونep_size > 1، وتأخذ قواعدها الأولوية على قواعدtp_planلنفس الوحدات. قاعدة"ep_dispatch_experts"تختار إرسال الرموز من الكل إلى الكل بدلاً من إخفاء الموجِّه والجمع الشامل.
إعدادات الاستدلال والتدريب الموزعين الأصليين باستخدام التوازي على مستوى الموترات أو خط الأنابيب أو FSDP2.