هناك تطبيقان شائعان لخوارزمية ZeRO Redundancy Optimizer (Zero) في المجتمع، أحدهما من DeepSpeed والآخر من PyTorch. يعرض Hugging Face Accelerate هذين الإطارين للمستخدمين النهائيين لتدريب/ضبط نماذجهم. تسلط هذه المدونة الضوء على الاختلافات بين كيفية عرض هذه الواجهات الخلفية من خلال برنامج Accelerate. لتمكين المستخدمين من التبديل بسلاسة بين هذه الواجهات الخلفية، قمنا بتوفير تغيير متعلق بالدقة ودليل مفاهيمي.
هل FSDP و DeepSpeed قابلان للتبادل؟
لقد حاولنا مؤخرًا تشغيل مسار تدريب باستخدام DeepSpeed وPyTorch FSDP. لاحظنا أن النتائج التي تم الحصول عليها اختلفت. كان النموذج المحدد هو قاعدة Mistral-7B وتم تحميله بنصف الدقة (bfloat16). في حين أن خسارة DeepSpeed (الأزرق) قد تقاربت بشكل جيد، فإن خسارة FSDP (البرتقالي) لم تتناقص، كما هو موضح في الشكل 1.
لقد افترضنا أن معدل التعلم قد يحتاج إلى التوسع من خلال عدد وحدات معالجة الرسومات وقمنا بزيادة معدل التعلم بمقدار 4x نظرًا لأننا كنا نستخدم 4 وحدات معالجة رسوميات. ثم رأينا سلوك الخسارة التالي، كما هو موضح في الشكل 2.

يبدو أن السلوك المطلوب قد تم تحقيقه من خلال زيادة معدل تعلم FSDP بعدد وحدات معالجة الرسومات! ومع ذلك، عندما جربنا معدل تعلم مختلف (1e-5) بدون القياس، لاحظنا خسارة مماثلة وخصائص معيارية متدرجة لكلا الإطارين، كما هو موضح في الشكل 3.

مسائل الدقة
داخل DeepSpeed قاعدة التعليمات البرمجية، وتحديدا في تنفيذ
DeepSpeedZeroOptimizer_Stage3 (كما يوحي الاسم، ما الذي يتعامل مع تقسيم المُحسِّن للمرحلة الثالثة)، لاحظنا أن trainable_param_groups، تمر مجموعات المعلمات التي يتم التدريب عليها عبر ملف داخلي _setup_for_real_optimizer استدعاء دالة، الذي يستدعي دالة أخرى تسمى _create_fp32_partitions. كما fp32 في الاسم يوحي، DeepSpeed كان يقوم بالترقية داخليًا، ويحتفظ دائمًا بأوزانه الرئيسية fp32 حسب التصميم. ويعني هذا النقل إلى الدقة الكاملة أن المُحسِّن يمكن أن يتقارب بمعدلات تعلم لا يتقارب بها بدقة أقل. وكانت الملاحظات السابقة نتيجة لهذا الاختلاف في الدقة.
في FSDP، قبل توزيع معلمات النموذج والمحسن عبر وحدات معالجة الرسومات، يتم “تسويتها” أولاً إلى موتر أحادي البعد. يستخدم FSDP وDeepSpeed طرقًا مختلفة dtypes لهذه المعلمات “المسطحة” التي لها تداعيات على مُحسّنات PyTorch. ويبين الجدول 1 العمليات الخاصة بكلا الإطارين؛ يشير العمود “المحلي” إلى العملية التي تحدث لكل وحدة معالجة رسومات، وبالتالي يتم استهلاك مقدار الذاكرة الناتجة عن البث التصاعدي بعدد وحدات معالجة الرسومات.
| عملية | محلي؟ | نطاق | تفاصيل |
|---|---|---|---|
تحميل النموذج في (مثل AutoModel.from_pretrained(..., torch_dtype=torch_dtype)) |
❌ | ||
| التحضير، مثل إنشاء “المعلمات المسطحة” | ✅ | FSDP السرعة العميقة |
يستخدم torch_dtypeيتجاهل torch_dtype ويتم إنشاؤه في float32 |
| تهيئة المُحسِّن | ✅ | FSDP السرعة العميقة |
يخلق المعلمات في torch_dtypeيخلق المعلمات في float32 |
| خطوة التدريب (الأمام، الخلف، التخفيض) | ❌ | FSDP السرعة العميقة |
يتبع fsdp.MixedPrecision يتبع deepspeed_config_file إعدادات الدقة المختلطة |
| محسن (ما قبل الخطوة) | ✅ | FSDP السرعة العميقة |
upcasting (إن وجدت) ل torch_dtypeرفع كل شيء ل float32 |
| محسن (الخطوة الفعلية) | ✅ | FSDP السرعة العميقة |
يحدث في torch_dtypeيحدث في float32 |
الجدول 1: ملخص لكيفية تعامل FSDP وDeepSpeed مع الدقة المختلطة
بعض النقاط الوجبات الجاهزة:
- كما تمت الإشارة إلى 🤗 مشكلة التسريع، فإن القاعدة الأساسية عند تنفيذ الدقة المختلطة هي الاحتفاظ بالمعلمات القابلة للتدريب
float32. - الرفع، كما هو الحال في
DeepSpeed، قد يكون له تأثير ضئيل على استهلاك الذاكرة عند التقسيم على عدد كبير من وحدات معالجة الرسومات. ومع ذلك، عند استخدامDeepSpeedعلى عدد صغير من وحدات معالجة الرسومات، يمكن أن تكون الزيادة في استهلاك الذاكرة بمقدار الضعف كبيرة. - لا يفرض التنفيذ الأصلي لـ FSDP البث، مما يسمح للمستخدم بتشغيل مُحسِّنات PyTorch بدقة منخفضة. وهذا يوفر مرونة أكبر من البث الأصلي لـ
DeepSpeed.
مواءمة DeepSpeed وFSDP في 🤗 التسريع
لمحاذاة DeepSpeed وFSDP بشكل أفضل في 🤗 التسريع، يمكننا إجراء البث تلقائيًا لـ FSDP عند تمكين الدقة المختلطة. لقد أنشأنا طلب سحب بهذا التغيير الذي تم تضمينه في الإصدار 0.30.0.

نتيجة هذا العلاقات العامة هي السماح لـ FSDP بالعمل في وضعين:
- وضع “مختلط الدقة” مثل نظير DeepSpeed
- وضع الدقة المنخفضة لسيناريوهات الذاكرة المقيدة، كما هو موضح في الشكل 4.
تم تلخيص وضعي FSDP الجديدين في الجدول 2 ومقارنتهما مع DeepSpeed.
| نطاق | تحميل النموذج (torch_dtype) |
الدقة المختلطة | التحضير (محلي) | تمرين | محسن (محلي) |
|---|---|---|---|---|---|
| FSDP (مقيد بالذاكرة) | bf16 |
الافتراضي (لا شيء) | bf16 |
bf16 |
bf16 |
| FSDP (وضع الدقة المختلط) | bf16 |
bf16 |
fp32 |
bf16 |
fp32 |
| السرعة العميقة | bf16 |
bf16 |
fp32 |
bf16 |
fp32 |
الجدول 2: ملخص لوضعي FSDP الجديدين ومقارناتهما مع DeepSpeed
نتائج الإنتاجية
نحن نستخدم نموذج IBM Granite 7B (الذي يتبع بنية Meta Llama2) لمقارنات الإنتاجية. نقوم بمقارنة استخدام نموذج Flops (MFU) ومقاييس الرموز المميزة/الثانية/وحدة معالجة الرسومات ونعرضها لـ FSDP (التقسيم الكامل) وDeepSpeed (Zero3).
استخدمنا أربع وحدات معالجة رسوميات A100 كما كان من قبل مع المعلمات الفائقة التالية:
- حجم الدفعة 8
- تم تحميل النموذج
torch.bfloat16 - الدقة المختلطة هي نفس dtype.
يوضح الجدول 3 أنه من المتوقع أن يعمل كل من FSDP وDeepSpeed بشكل مماثل.
نعتزم المتابعة من خلال مقارنة شاملة للإنتاجية وأساليب لتحسين الإنتاجية (على سبيل المثال، الأقنعة رباعية الأبعاد مع التعبئة، وtorch.compile، وفحص التنشيط الانتقائي) حيث أصبحت تقنيات المحاذاة واسعة النطاق مثل InstructLab وGLAN شائعة.
| نطاق | الرموز / ثانية / الجهاز | وقت الخطوة (ق) | استخدام النموذج المتخبط (MFU) |
|---|---|---|---|
| FSDP (الوضع المحاذي) | 3158.7 | 10.4 | 0.41 |
| السرعة العميقة | 3094.5 | 10.6 | 0.40 |
الجدول 3: مقارنات إنتاجية الملعب بين FSDP وDeepSpeed على أربع وحدات معالجة رسوميات A100.
إغلاق الأفكار
لقد قدمنا دليلاً مفاهيميًا جديدًا لمساعدة المستخدمين على الانتقال بين الإطارين. يساعد الدليل المستخدمين على الإجابة على أسئلة مثل:
- كيف نحقق استراتيجيات المشاركة المكافئة؟
- كيف نقوم بتحميل النموذج بكفاءة؟
- كيف تتم إدارة الجلب المسبق للوزن في FSDP وDeepSpeed؟
- ما هو المعادل لتغليف FSDP في DeepSpeed؟
نحن نفكر في طرق مختلفة لتكوين هذه الأطر في 🤗 تسريع،
🤗 تسريع يجعلها تقريبا تافه للتبديل بين FSDP وDeepSpeed، مع كون معظمها عبارة عن تغيير في ملف التكوين Accelerate (راجع دليل المفهوم الجديد للحصول على إرشادات حول هذا).
إلى جانب تغيير التكوين، هناك بعض الاعتبارات الأخرى (الموضحة أيضًا في الدليل) وهي الاختلافات في كيفية التعامل مع نقاط التفتيش، وما إلى ذلك.
يمكن إعادة إنتاج جميع التجارب في هذه المدونة باستخدام الكود الأصلي 🤗 تسريع المشكلة.
نعتزم المتابعة من خلال مقارنات الإنتاجية على نطاق واسع وتقنيات للاستفادة بشكل أفضل من وحدات معالجة الرسومات هذه لضبط المهام والمحاذاة مع الحفاظ على جودة النموذج.
شكر وتقدير
هذا جهد شارك فيه عدة فرق عبر مؤسسات متعددة للالتقاء معًا. بدأ الأمر في IBM Research، وبالتحديد ألدو باريجا، الذي اكتشف المشكلة، وفابيان ليم، الذي حدد فجوات الدقة وأصلح هذه المشكلة. لقد كان زاك مولر وستاس بيكمان استثنائيين في تقديم التعليقات والإصلاحات لتسريعها. كان Less Wright من فريق PyTorch في Meta مفيدًا جدًا في الإجابة على الأسئلة المتعلقة بمعلمات FSDP. أخيرًا، نود أيضًا أن نشكر فريق DeepSpeed لتقديم تعليقاته على هذه المدونة.