نظرة تفصيلية على SparseCore للنماذج الكبيرة المضمّنة (LEM)

‫SparseCore هو معالج مخصص بتقسيم البيانات إلى مربعات مصمّم لتسريع أداء أحمال العمل التي تتضمّن عمليات وصول إلى الذاكرة وعمليات حسابية غير منتظمة ومتفرقة، لا سيما على مجموعات البيانات الكبيرة المخزّنة في ذاكرة النطاق الترددي العالي (HBM). وعلى الرغم من أنّها تتفوّق في مهام مثل عمليات البحث المضمّنة، إلا أنّ إمكاناتها تتجاوز ذلك لتشمل تسريع مجموعة متنوّعة من أحمال العمل الديناميكية والمتفرقة الأخرى.

1. مقدمة حول SparseCore

الميزات المعمارية الرئيسية:

  • البنية المستندة إلى مربّعات: تتألف من مربّعات حوسبة متعددة (كل مربّع هو وحدة كاملة لتدفّق البيانات تتضمّن ذاكرة محلية ووحدة معالجة خاصة بها) ما يتيح المعالجة المتوازية.
  • التنفيذ الديناميكي: يتيح بشكلٍ أصلي التحكّم في تدفّق البيانات والوصول إلى الذاكرة حسب البيانات، وهو أمر بالغ الأهمية للبيانات المتفرّقة.
  • معالجة المتجهات: تستخدم مهام المتجهات الصغيرة (8 عناصر أو 16 عنصرًا، حسب إصدار الجهاز) لإجراء العمليات الحسابية بكفاءة.
  • التحكّم المركزي: ينسّق مسلسِل SparseCore واحد المهام على مستوى جميع المربّعات، ما يضمن تنفيذ العمليات بشكل متزامن.
  • إتاحة تلخيص البيانات: تتضمّن عمليات متخصّصة على مستوى جميع المسارات مفيدة لمهام مثل الترتيب والفلترة ومجموعات البادئات.
  • التسلسل الهرمي للذاكرة: تستفيد هذه التقنية بشكل استراتيجي من ذاكرة النطاق الترددي العالي (HBM) لتخزين مجموعات البيانات الكبيرة وذاكرة لوحة الخدش المحلية (SPMEM) لتنظيم البيانات التي يتم الوصول إليها بشكل متكرر، ما يقلّل بشكل كبير من وقت استجابة ذاكرة النطاق الترددي العالي (HBM).

المواصفات في لمحة:

السمة TPU v4 TPU v5p Trillium
SparseCores/Chip 4 4 2
Tiles/SparseCore 16 16 16
عرض SIMD 8 8 ‫8 (F32) 16 (BF16)
سعة ذاكرة النطاق الترددي العالي (HBM) ‫32 غيبيبايت ‫96 غيبيبايت ‫32 غيبيبايت

2. المعالجة المُسبقة لمضيف SparseCore

يُعدّ إعداد البيانات بشكل فعّال أمرًا بالغ الأهمية لتحقيق أداء جيد في SparseCore، وهنا يأتي دور المعالجة المسبقة على مستوى المضيف. ويشمل هذا الإطار عدة وظائف أساسية:

  • تحويل البيانات:
    • طبِّق عمليات التحويل اللازمة على بيانات الإدخال الأولية.
    • إدارة عمليات تحويل المعرّفات، وهو أمر مهم بشكل خاص عند التعامل مع ميزة أو تجميع الجداول
    • حوِّل بيانات الإدخال إلى تنسيق مصفوفة COO المتفرقة، كما هو موضّح بالتفصيل في القسم التالي.
    • قسِّم البيانات لتوزيعها بكفاءة على مختلف نوى SparseCore المتاحة على الشريحة.
  • التحقّق من الحدّ الأقصى:
    • تأكَّد من أنّ خصائص البيانات المُدخَلة (مثل عدد المعرّفات) تتوافق مع الحدود التشغيلية المحدّدة مسبقًا في SparseCore، مثل max_ids_per_partition وmax_unique_ids_per_partition.
    • إذا تجاوزت البيانات المدخلة هذه الحدود، يمكن أن تحاول طبقة المعالجة المسبقة للمضيف تقسيم البيانات إلى دفعات صغيرة أصغر تتناسب مع القيود.
  • نقل البيانات:
    • نسخ البيانات التي تمت معالجتها والتحقّق من صحتها بكفاءة إلى ذاكرة النطاق الترددي العالي (HBM) في وحدة معالجة Tensor، ما يجعلها جاهزة للتنفيذ في SparseCore

فهم ترتيب الجداول:

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

  • تداخل الميزات: يحدث ذلك عندما تتشارك ميزات متعدّدة ومختلفة جدول التضمين الأساسي نفسه. ومن الأمثلة الشائعة على ذلك استخدام قاموس تضمين واحد لميزات فئوية مختلفة، مثل الرموز البريدية من سياقات مختلفة.
  • تجميع الجداول: في هذا السيناريو، يتم تجميع جداول تضمين متعدّدة ومختلفة معًا. يتم غالبًا تجميع الجداول التي تشترك في أبعاد التضمين نفسها وإعدادات المحسِّن نفسها.

تتمثّل الميزة الأساسية لدمج الجداول في إنشاء حجم دفعة فعّال أكبر للعمليات التي يتم إجراؤها على هذه الجداول المدمجة. يؤدي ذلك إلى تقليل الحمل الزائد الناتج عن العمليات الحسابية ويمكن أن يكون فعالاً في إخفاء حالات التأخير في الاتصال بين الشرائح (ICI). لتحقيق الأداء الأمثل، يُنصح باستخدام عدد معتدل من الجداول المكدّسة (عادةً ما يتراوح بين 5 و100).

3- التحويل إلى موترات COO

قبل أن تتمكّن SparseCore من معالجة البيانات، يتم عادةً تحويلها إلى تنسيق موتر متفرّق من نوع Coordinate (COO). تنسيق COO هو طريقة لتمثيل المصفوفات المتفرقة بكفاءة باستخدام ثلاث مصفوفات عادةً:

  • row_ids: مصفوفة تحتوي على فهارس الصفوف لكل عنصر غير صفري. في سياق المعالجة المجمّعة، يرتبط ذلك غالبًا بسمة الدفعة.
  • col_ids: مصفوفة تحتوي على فهارس الأعمدة لكل عنصر غير صفري. بالنسبة إلى عمليات التضمين، تكون هذه القيم غالبًا هي قيم الميزات أو المعرّفات.
  • values (اختياري): مصفوفة تحتوي على القيم الفعلية للعناصر غير الصفرية في الإحداثيات المقابلة (row، col). بالنسبة إلى العمليات الحسابية المتعلقة بالحدود (التي سيتم تناولها لاحقًا) والمرتبطة بعدد المعرّفات، لا يتم غالبًا أخذ هذه القيم (المكاسب) في الاعتبار.

مثال توضيحي:

ضَع في اعتبارك مصفوفة متفرقة للإدخال تمثّل مجموعات من المعرّفات:

[
    [id_A],                 // Sample 0
    [id_A, id_B, id_C],     // Sample 1
    [id_B, id_B, id_D],     // Sample 2 (note duplicate id_B)
]

بعد التحويل إلى تنسيق COO (وربما بعد إزالة تكرار المعرّفات ضمن العيّنة نفسها):

row_ids = [0, 1, 1, 1, 2, 2]
col_ids = [id_A, id_A, id_B, id_C, id_B, id_D]

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

4. SparsecoreConfig: واجهة برمجة التطبيقات ذات المستوى الأعلى

واجهات برمجة التطبيقات المضمّنة الخاصة بإطار العمل:

تعمل السمة SparsecoreConfig أو الآليات المشابهة، مثل علامات XLA، كواجهة عالية المستوى للتحكّم في مجموعة كبيرة من سلوكيات SparseCore. يُعدّ الفهم الشامل لهذه المَعلمات أمرًا حيويًا لتحسين الأداء بفعالية وضمان التشغيل الصحيح لنماذجك.

  • disable_table_stacking: bool = False
    • التفسير: يتحكّم هذا الخيار في ما إذا كان سيتم منع إطار العمل من ترتيب الجداول تلقائيًا، ما قد يؤدي إلى انخفاض الأداء بسبب زيادة النفقات العامة وانخفاض القدرة على إخفاء وقت الاستجابة بين الشرائح.
    • تلقائي: False (ما يعني أنّ ميزة ترتيب الجداول مفعّلة تلقائيًا بشكل عام في حال توفّرها في إطار العمل).
  • max_ids_per_chip_per_sample: int = 64
    • التفسير: تحدّد هذه المَعلمة حدًا أقصى عالميًا لعدد معرّفات التضمين التي يمكن لشريحة واحدة معالجتها من عيّنة واحدة في مجموعة الإدخال، ويتم تجميعها على مستوى جميع الجداول. وهي آلية لإدارة الموارد على مستوى الشريحة، قبل أخذ الحدود الأكثر تفصيلاً على مستوى الجدول أو القسم في الاعتبار. يعتمد ضبط هذه القيمة عادةً على خصائص الطراز المحدَّد والسعة الإجمالية للنظام.
    • تلقائي: 64
  • max_ids_per_table: Optional[Dict[str, int]] = None
    • التفسير: تحدّد هذه المَعلمة الحد الأقصى لعدد معرّفات التضمين (التي يمكن أن تتضمّن تكرارات) التي يمكن معالجتها لكل جدول منطقي، مع الأخذ في الاعتبار جميع أقسامه على مستوى جميع SparseCores. هذا الحدّ أوسع من max_ids_per_partition. إذا تم تقسيم جدول T إلى P أقسام، ينطبق هذا الحدّ على مجموع المعرّفات الموجهة إلى جميع الأقسام P. ويرتبط ذلك غالبًا بـ max_ids_per_partition_per_sample وحجم الدفعة الإجمالي.
    • الإعداد: يتم ضبطه عادةً باستخدام ملف حدود (على سبيل المثال، باستخدام العلامة xla_sparse_core_max_ids_file)، حيث يتم تحديد max_ids_per_partition. هذا المفهوم على مستوى الجدول هو طريقة لضبط الحدود على مستوى القسم (max_ids وmax_uniques).
    • القيمة التلقائية: None (يمكن استنتاج القيمة من الحدود المحدّدة لكل قسم أو من الإعدادات الأخرى إذا لم يتم توفيرها بشكل صريح).
  • max_unique_ids_per_table: Optional[Dict[str, int]] = None
    • التفسير: يشبه هذا المعلمة max_ids_per_table، ولكنّه يحدّد الحد الأقصى لعدد المعرّفات الفريدة لكل جدول منطقي. هذا الإعداد مهم لتحديد حجم المخازن المؤقتة على الجهاز بشكل مناسب، والتي تُستخدم في معالجة المعرّف الفريد وعمليات المتجهات اللاحقة.
    • الإعداد: يتم أيضًا تحديد هذا الحقل بشكل شائع في ملف حدود أو يتم استخراجه من max_unique_ids_per_partition_per_sample.
    • تلقائي: None
  • allow_id_dropping: bool = False
    • التفسير: يتحكّم هذا الخيار المنطقي في إزالة المعرّف عندما يتجاوز عدد المعرّفات التي تمّت مواجهتها في بيانات الإدخال (الحدود المرصودة) الحدود التي تمّ ضبطها أثناء التجميع (على سبيل المثال، max_ids_per_partition).
      • في حال True: يتم تجاهل المعرّفات التي ستؤدي إلى تجاوز الحدود القصوى بدون إشعار. عادةً، تتم معالجة المعرّفات ضمن قسم بترتيب مرتّب، ويتم تجاهل أي معرّف يؤدي إلى تجاوز العدد الحالي الحدّ الأقصى للدُفعة المصغّرة المخصّصة له. يسمح ذلك للبرنامج بمواصلة التنفيذ، ولكن قد يكون له تأثير سلبي على دقة النموذج.
      • في حال False: يتم تشغيل خطأ، ومن المرجّح أن تتوقف العملية إذا تجاوزت الحدود المرصودة الحدود المجمّعة. يضمن هذا النهج معالجة جميع البيانات، ولكنّه يتطلّب ضبط الحدود بشكل أكثر تحفظًا.
    • تلقائي: False (ما يؤدي إلى حدوث خطأ عند تجاوز الحد الأقصى بدلاً من حذف البيانات بدون إشعار).
  • initialize_tables_on_host: bool = True

    • التفسير: تحدّد هذه العلامة ما إذا كان يتم تهيئة جداول التضمين على وحدة المعالجة المركزية المضيفة قبل نقلها لاحقًا إلى ذاكرة النطاق الترددي العالي (HBM) في وحدة معالجة Tensor. تتمثل الممارسة المعتادة في تهيئة الجداول على الجهاز المضيف. يؤدي ضبط هذا الخيار على True إلى اتّباع هذه القاعدة. إذا تم ضبطها على False، سيعني ذلك توفّر آلية إعداد على الجهاز، ما قد يؤدي إلى آثار مختلفة على الأداء أو متطلبات أساسية معيّنة للإعداد.
  • enable_fast_table_initialization: bool = False

    • التفسير: يتم تهيئة الجداول مباشرةً على وحدة معالجة Tensor. يمكن أن يساعد ذلك في تقليل أوقات بدء تشغيل النموذج.

5- تقسيم التعليمات البرمجية إلى مراحل لتحسين الأداء

إنّ تقنية Pipelining هي أسلوب لتحسين الأداء يتيح تنفيذ العمليات بشكل متزامن على TensorCore (TC) وSparseCore (SC). ومن خلال تداخل هذه العمليات الحسابية، يمكن تحسين معدل النقل الإجمالي بشكل كبير.

  • آلية العمل: في خطوة التدريب العادية التي تتضمّن عمليات بحث عن تضمين متفرّق (تتولّاها SC) وعمليات حسابية للطبقة الكثيفة (تتولّاها TC)، تتيح عملية تقسيم المهام إلى مراحل لـ SC العمل على الجزء الخاص بها من الخطوة i (على سبيل المثال، عملية المرور للأمام أو للخلف) بينما تعالج TC في الوقت نفسه جزءًا مختلفًا من الخطوة i نفسها، أو حتى أجزاء من الخطوات المجاورة مثل i-1 أو i+1.
  • التأثير في التدرجات: قد تعمل SparseCore على تدرجات "قديمة". على سبيل المثال، قد لا يتم تعديل التدرجات التي يتم احتسابها خلال مرحلة الانتشار العكسي للخطوة i بالكامل ولا تظهر لوحدة التحكّم الذكي إلا في الخطوة i+2.
  • المفاضلة بين الأداء والأرقام: يمكن أن يؤدي التنفيذ المتداخل إلى تسريع العمليات بشكل كبير، وقد يصل التحسين إلى ضعفَي وقت تنفيذ الخطوة على الجهاز. ومع ذلك، قد تؤثر التغييرات الطفيفة في الأرقام (embedding_weights) الناتجة عن استخدام التدرجات القديمة في سلوك تقارب النموذج أو الدقة النهائية التي تم تحقيقها. ويعتمد مدى قبول هذا التنازل بشكل كبير على النموذج، وغالبًا ما يتطلّب التحقّق من صحته تجريبيًا.
  • علامة التحكّم: يمكن التحكّم في ميزة "تداخل الأوامر" من خلال tf_xla_disable_full_embedding_pipelining. يؤدي ضبط هذا الخيار على true إلى إيقاف ميزة "التنفيذ المتزامن الكامل" (التداخل بين عمليات حساب TensorCore وSparseCore)، بينما يؤدي ضبطه على false (أو إذا كانت دلالات الخيار تشير إلى التفعيل عند الضبط على "خطأ") إلى تفعيله.

مسار المعالجة المتوازية التصوّري:

  • بدون تقسيم التعليمات البرمجية (سير عمل تسلسلي مبسط):

    Loop: SC/F_i -> TC/F_i -> TC/B_i -> SC/B_i

  • مع استخدام أسلوب التوازي (سير العمل المتداخل المبسّط):

    Time ->
    Step i:   SC/F_i | TC/F_i | TC/B_i | SC/B_i
    Step i+1:          SC/F_i+1| TC/F_i+1| TC/B_i+1| SC/B_i+1
    

    ملاحظة: يمكن أن تكون مراحل تنفيذ التوازي المتسلسل الفعلية في الأجهزة والبرامج المترجمة أكثر تعقيدًا، وغالبًا ما تتضمّن حلقات ما قبل التوازي المتسلسل وحلقات التنفيذ الرئيسية وحلقات ما بعد التوازي المتسلسل لإدارة تبعيات البيانات وضمان صحتها.

6. دور XLA

‫XLA (الجبر الخطي المسرَّع) هو برنامج التجميع الخاص بالمجال الذي يترجم الرسوم البيانية الحسابية العالية المستوى، عادةً من أُطر عمل مثل TensorFlow، إلى رمز آلة محسَّن للغاية ومصمَّم خصيصًا لوحدات معالجة الموتّرات. ويشمل ذلك إنشاء التعليمات الخاصة بالعمليات المتّجهة إلى SparseCore.

الوظائف الرئيسية في سياق SparseCore:

  • تجميع العمليات المتفرقة: تتولى XLA تجميع عمليات البحث عن التضمين (مثل SparseDenseMatmulOp) وغيرها من العمليات الحسابية المتفرقة في برامج SparseCore قابلة للتنفيذ ومنخفضة المستوى.
  • دمج الحدود: تستخدم هذه الميزة الحدود التشغيلية التي تم ضبطها (على سبيل المثال، max_ids_per_partition وmax_unique_ids_per_partition، والتي يتم توفيرها غالبًا من خلال ملف حدود تحدّده علامات مثل xla_sparse_core_max_ids_file) لتحديد أحجام مخازن الذاكرة الثابتة وتخصيصها على الجهاز، لا سيما داخل SPMEM.
  • عمليات التحسين المستهدَفة: تنفّذ XLA مجموعة من عمليات التحسين المصمّمة خصيصًا لبنية SparseCore. ويمكن أن تشمل هذه العمليات جدولة التعليمات وتحويلات تنسيق الذاكرة ودمج العمليات لزيادة الكفاءة إلى أقصى حد.
  • التحكّم باستخدام العلامات: يتم عرض العديد من جوانب سلوك SparseCore ومعلَمات الضبط واستراتيجيات التحسين والتحكّم فيها من خلال علامات XLA (على سبيل المثال، xla_sparse_core_estimate_max_ids للحد من التقدير أو xla_sc_detect_nan لتصحيح الأخطاء).

حالة البرامج المفتوحة المصدر:

في الوقت الحالي، يتم تنفيذ Sparsecore داخليًا ويتم عرضه باستخدام libtpu.so.

الإبلاغ عن الأخطاء وبيانات التشخيص:

تظهر حالات تعذُّر الترجمة البرمجية المرتبطة بإعدادات SparseCore أو قيود الموارد غالبًا على شكل XLA:TPU أخطاء في وقت الترجمة البرمجية. يمكن أن تقدّم رسائل الخطأ هذه إحصاءات قيّمة حول مشاكل مثل ضبط الحدود على قيمة مرتفعة جدًا بالنسبة إلى SPMEM المتاح، أو استخدام إعدادات غير متوافقة.

7. كيفية تطبيق الحدود القصوى على الجداول في SparseCore

في SparseCore، تشكّل "الحدود" مَعلمات ضبط أساسية تشير بشكل أساسي إلى إعدادَين لكل قسم لكل جدول مقسّم (موزّع) على جميع SparseCore المتاحة:

  • max_ids_per_partition: يحدّد هذا الحد الأقصى لعدد المعرّفات الإجمالية (بما في ذلك المعرّفات المكرّرة) التي من المتوقّع أن يرسلها أي SparseCore فردي إلى قسم معيّن من جدول محدّد أو أن يعالجه، وذلك خلال خطوة حسابية واحدة.
  • max_unique_ids_per_partition: تحدّد هذه السمة الحد الأقصى لعدد المعرّفات الفريدة التي من المتوقّع أن يرسلها أو يعالجها أي SparseCore واحد لـ

الترجمة إلى تنسيق الجدول المادي والمعالجة:

  • استراتيجية تقسيم الجداول: يتم عادةً "تقسيم" جداول التضمين باستخدام عملية حسابية رياضية (mod-sharded) على مستوى جميع SparseCore في النظام. وهذا يعني أنّ كل SparseCore يصبح مسؤولاً عن مجموعة فرعية مميزة من المفردات (الصفوف) لكل جدول. سيتم بشكل عام تعيين معرّف j إلى SparseCore_k استنادًا إلى صيغة مثل k = j % num_total_sparse_cores.
  • تعريف "القسم": في هذا السياق، يشير "القسم" إلى الجزء المحدّد من جدول التضمين الذي يتعامل معه SparseCore واحد في عمليات البحث.
  • تخصيص المخزن المؤقت SPMEM: يستخدم برنامج XLA المترجم هذه الحدود لتحديد حجم المخازن المؤقتة وتخصيصها بشكل ثابت ضمن ذاكرة SPMEM المؤقتة على الجهاز. يتم تحديد أبعاد المخازن المؤقتة بحيث يمكن تحميل جميع البيانات اللازمة المرتبطة بمعرّفات قسم معيّن (حتى حدود max_ids وmax_unique_ids المحدّدة) إلى SPMEM للمعالجة. ويُعدّ ذلك مهمًا بشكل خاص في العمليات الحسابية غير القائمة على العناصر، مثل تقليل المعرّفات المكرّرة ضمن قسم (على سبيل المثال، عند إنشاء تمثيل Compressed Sparse Row (CSR))، حيث يجب أن تكون مجموعة البيانات ذات الصلة الكاملة بمعرّفات هذا القسم متاحة بسهولة في الذاكرة السريعة.
  • الحدود القصوى المجمَّعة مقابل الحدود القصوى المرصودة:

    • الحدود المرصودة: هي العدد الفعلي لمعرّفات المستخدمين التي تمت مواجهتها لكل قسم أثناء وقت التشغيل، استنادًا إلى بيانات الإدخال التي تتم معالجتها.
    • في حال تجاوز الحدود المرصودة الحدود المجمّعة، قد يؤدي ذلك إلى حذف المعرّف (في حال تفعيل allow_id_dropping) أو حدوث أخطاء.
  • احتساب الحدود: تتضمّن عملية تحديد الحدود المناسبة إجراء تحليل دقيق لتوزيع البيانات المُدخَلة. بالنسبة إلى أي جدول معيّن (لنسمّه T1، والذي قد يكون جزءًا من جدول مكدّس أكبر T):

    1. يتم تقسيم مجموعة الإدخال (على سبيل المثال، SparseTensor ثنائي الأبعاد بالشكل [BatchSize, MaxSequenceLength]) في البداية على مستوى SparseCore المتاحة. على سبيل المثال، إذا تم إقران TensorCore بـ 2 SparseCore، قد تتلقّى كل SparseCore مجموعة فرعية من الشكل [BatchSize/2, MaxSequenceLength].
    2. يتم بعد ذلك تحويل هذه الدفعة الفرعية إلى تنسيق COO، ما يؤدي إلى إنشاء row_ids وcol_ids.
    3. تتم إزالة المعرّفات المكرّرة ضمن العيّنة نفسها (أي الإدخالات التي تتضمّن row_id وcol_id نفسيهما).
    4. بالنسبة إلى كل col_id فريد متبقٍ (ضمن عيّنة)، يتم تحديد SparseCore المستهدَف المسؤول عن هذا المعرّف باستخدام قاعدة التقسيم إلى أجزاء المعدّلة: target_sc_id = col_id % num_total_sparse_cores.
    5. يتم الاحتفاظ بعدد إجمالي المعرّفات (ids_per_sparse_core[target_sc_id]++) وعدد المعرّفات الفريدة (unique_ids_per_sparse_core[target_sc_id]++، بعد التأكّد من تفردها بالنسبة إلى target_sc_id المحدّد) التي يتم توجيهها إلى كل target_sc_id.
    6. بعد ذلك، يتم ضبط max_ids_per_partition للجدول T1 على max(ids_per_sparse_core_array).
    7. وبالمثل، تم ضبط max_unique_ids_per_partition للجدول T1 على max(unique_ids_per_sparse_core_array).
    8. إذا كان الجدول T1 أحد مكوّنات جدول مكدّس، قد يتم تطبيق عمليات تحويل إضافية، مثل عمليات التدوير أو النقل، على توزيعات المعرّفات قبل جمع الإحصاءات من جميع الجداول المكوّنة. يساعد ذلك في موازنة الحمل على مستوى الشرائح.

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

8. طريقة تواصل كل SparseCore

يعتمد التواصل في SparseCore، لا سيما في سياق معالجة قائمة أرقام تعريف لعمليات البحث عن التضمين، على عدة آليات منسَّقة:

  • تقسيم الوحدات النمطية والتوجيه الضمني:
    • يتم تقسيم الجداول المضمّنة إلى أجزاء باستخدام التجزئة المعيارية على مستوى جميع SparseCore في النظام.
    • عندما يقدّم المضيف مجموعة من بيانات الإدخال (التي تتم معالجتها مسبقًا لاحقًا بتنسيق COO، بما في ذلك col_ids)، يتم استخدام قيمة col_id لتحديد SparseCore المسؤول عن هذا المعرّف المحدّد: target_sc_id = col_id % num_total_sparse_cores.
    • يتلقّى كل SparseCore ويعالج بشكل فعّال فقط المجموعة الفرعية من المعرّفات التي تتوافق مع أقسام المفردات المخصّصة له. تُعدّ مرحلة المعالجة المسبقة على مستوى المضيف ضرورية لإعداد البيانات بطريقة تتيح لكل SparseCore تحديد المعرّفات ذات الصلة والتعامل معها بسهولة.
  • توزيع البيانات حسب المضيف:
    • تقسّم منطق المعالجة المسبقة للمضيف مجموعة الإدخال الإجمالية وتوزّع الأجزاء ذات الصلة من row_ids وcol_ids (بالإضافة إلى أي ميزات أو أوزان مرتبطة إذا كان ذلك منطبقًا) إما إلى الذاكرة (HBM) التي يمكن لكل SparseCore الوصول إليها مباشرةً أو إلى HBM مشتركة تسترد منها SparseCores البيانات المطلوبة.
  • معالجة Intra-SparseCore:
    • بعد أن تتلقّى SparseCore مجموعة المعرّفات المحدّدة لقسم جدول معيّن، تنفّذ عمليات مثل إزالة تكرار هذه المعرّفات وجمع متّجهات التضمين المقابلة. وهي عمليات حسابية محلية بشكل أساسي يتم تنفيذها داخل مربّعات SparseCore الخاصة واستخدام ذاكرة SPMEM المحلية.
  • الاتصال بين SparseCore (الكل بالكل):
    • بعد مرحلة المعالجة الأولية (مثل عمليات البحث عن التضمين)، يمكن استخدام نمط اتصال "من الكل إلى الكل" لدمج النتائج أو إعادة توزيعها على مستوى SparseCores (على سبيل المثال، قبل إدخال عمليات التنشيط في طبقة TensorCore تتوقّع إدخالاً يتوافق مع جميع مواضع العيّنات الأصلية). وهذا أمر بالغ الأهمية لإعادة إنشاء المجموعة الكاملة من عمليات التفعيل إذا تم توزيع مجموعة الإدخال الأصلية للمعالجة المتوازية.
  • التواصل مع TensorCores:
    • تتواصل SparseCores مع TensorCores لإرسال عمليات تنشيط التضمين (أثناء التمرير الأمامي) وتلقّي التدرجات (أثناء التمرير الخلفي). يتم تنسيق هذا التفاعل من خلال البرنامج الذي تم تجميعه باستخدام XLA، ويتضمّن في كثير من الأحيان استخدام HBM كذاكرة وسيطة. تؤثّر استراتيجية التوازي والتسلسل (التي تمّت مناقشتها سابقًا) بشكل كبير في توقيت ومزامنة عملية التواصل بين SC وTC.

في الأساس، يتم التعامل مع عملية "التوزيع" الأولي للمعرفات على SparseCores المناسبة إلى حد كبير من خلال نظام التقسيم وخطوات المعالجة المسبقة للمضيف. تتضمّن عمليات التواصل اللاحقة SparseCores التي تعمل على بياناتها المحلية، وقد يليها عمليات تواصل جماعية مثل "الكل إلى الكل" إذا كانت البيانات بحاجة إلى تبادلها أو إعادة ترتيبها على مستوى جميع SparseCores قبل أن تتم معالجتها بشكل أكبر من خلال TensorCores.

9- إدارة الذاكرة في SparseCore

يدير كل SparseCore عدة أنواع مختلفة من الذاكرة بكفاءة لإجراء العمليات الحسابية:

  • ذاكرة لوحة الخدش (SPMEM):
    • الطبيعة: ذاكرة SRAM محلية صغيرة نسبيًا ولكنها سريعة جدًا، وتتوفّر حصريًا لكل SparseCore. من المهم ملاحظة أنّ SPMEM ليس ذاكرة تخزين مؤقت، بل تتم إدارة استخدامه وتنظيمه بشكل صريح من خلال برنامج التجميع XLA.
    • الغرض: يتم استخدام SPMEM من أجل "تخزين البيانات بشكل انتهازي". ويشمل ذلك المدخلات والمخرجات والنتائج الوسيطة المطلوبة لإجراء عمليات حسابية مستمرة في "البحث الذكي". يؤدي تخزين البيانات المؤقتة في SPMEM إلى تقليل وقت الاستجابة الطويل المرتبط عادةً بالوصول إلى HBM بشكل كبير.
    • تحديد الحجم: كما هو موضّح في القسم "الحدود"، يتم تحديد حجم مخازن SPMEM مؤقتًا بشكل ثابت في وقت الترجمة. تستند هذه الأحجام إلى مَعلمات، مثل max_ids_per_partition وmax_unique_ids_per_partition. يضمن هذا التخصيص الثابت أنّه بالنسبة إلى أي عملية معيّنة على قسم جدول (مثل تقليل نسبة استخدام وحدة المعالجة المركزية)، يمكن أن تتناسب جميع البيانات اللازمة لمعرّفات هذا القسم (حتى الحدود المحدّدة) مع SPMEM.
    • تحسينات المترجم: يشتمل مترجم XLA على تحسينات متطورة لتحديد مقدار البيانات التي يجب تخزينها في SPMEM وعناصر البيانات المحدّدة التي يجب تخزينها فيها لإخفاء وقت استجابة HBM وتعزيز الأداء إلى أقصى حدّ.
    • قيد التخصيص الديناميكي: لا يتيح برنامج SparseCore المجمّع حاليًا التخصيص الديناميكي لمساحة التخزين المؤقت. ويؤكّد ذلك على الأهمية البالغة لتحديد الحجم الثابت من خلال الإعداد الدقيق للحدود.
  • الذاكرة ذات النطاق الترددي العالي (HBM):
    • الطبيعة: مورد كبير للذاكرة المشتركة يمكن لجميع SparseCores وTensorCores ونظام المضيف الوصول إليه. يتم تخزين جداول التضمين الأساسية في HBM.
    • استخدام الحزمة: تتطلّب عمليات SparseCore غالبًا مساحة تخزين مؤقتة في ذاكرة النطاق الترددي العالي (HBM) للنتائج الوسيطة التي لا تتناسب مع ذاكرة SPMEM المحدودة أو التي يجب نقلها بين مراحل أكبر من مسار المعالجة. يمكن تقدير استخدام حزمة HBM أثناء كل من التمرير الأمامي والخلفي على النحو التالي:
      • Forward Pass HBM Stack (جدول واحد) ≈ (2 * feature_width + 1) * max_unique_nz_per_row * logical_replica_count * 4 بايت
      • Backward Pass HBM Stack (single table) ≈ 3 * feature_width * max_unique_nz_per_row * logical_replica_count * 4 bytes
    • استخدام الذاكرة لأخذ لقطات لعناصر متعدّدة: تستوعب HBM أيضًا الذاكرة لأخذ لقطات لعناصر متعدّدة التي يديرها المضيف. يخزّن الكومة بيانات مثل أوزان الطبقة الكثيفة والثوابت التي يستخدمها النموذج وبيانات الإدخال التي تم جلبها مسبقًا. يزداد استخدام الذاكرة المؤقتة عادةً مع عدد الخطوات التي يجلب المضيف بياناتها مسبقًا (يتم التحكّم في ذلك من خلال العلامة maximum_parallel_iterations). في حين أنّ الجلب المسبق للمزيد من البيانات يمكن أن يحسّن الأداء من خلال تداخل عمليات نقل البيانات من المضيف إلى الجهاز مع عمليات الحساب على الجهاز، إلا أنّه يستهلك أيضًا المزيد من ذاكرة النطاق الترددي العالي (HBM).
    • التسلسل لتحسين HBM: يوفّر الخيار xla_sc_num_serialized_tables_to_optimize_hbm آلية للتحكّم في عدد جداول البيانات التي يتم الاحتفاظ بها "مباشرة" في ذاكرة حزمة HBM في أي وقت. تؤدي زيادة هذا العدد إلى تسلسل معالجة المزيد من الجداول، ما يمكن أن يقلّل من الحد الأقصى لاستخدام حزمة HBM، ولكن قد يؤثر ذلك سلبًا في الأداء بسبب انخفاض التوازي.
  • ذاكرة المتجهات (VMEM):
    • ‫VMEM هي ذاكرة محلية مؤقتة تستخدمها وحدة TensorCore حصريًا. على الرغم من أنّ VMEM لا تتم إدارتها مباشرةً من خلال SparseCore، إلا أنّها جزء لا يتجزأ من نظام الذاكرة الذي تتفاعل معه SC، وذلك بشكل أساسي من خلال TensorCore.

استراتيجية إدارة الذاكرة بشكل عام:

تتمحور استراتيجية إدارة الذاكرة الأساسية في SparseCore حول استخدام SPMEM الصغيرة والسريعة للبيانات "النشطة" التي تتم معالجتها بشكل نشط بواسطة لوحة SparseCore، ما يقلل من عمليات الوصول إلى HBM الأبطأ. الحدود التي تم ضبطها هي الآلية الأساسية لضمان عدم تجاوز SPMEM الحدّ الأقصى. يتم استخدام HBM لتخزين جداول التضمين الكبيرة والبيانات المؤقتة التي تتجاوز سعة SPMEM أو التي يجب مشاركتها بين وحدات معالجة أو مراحل مختلفة من خطوط الإنتاج. يكون برنامج التجميع XLA مسؤولاً عن تنسيق جميع عمليات نقل البيانات وتخصيص المخزن المؤقت استنادًا إلى هذه المبادئ المعمارية والحدود التي يضبطها المستخدم.

10. المؤثِّرات السلبية على الأداء والذاكرة

لتحقيق أفضل أداء باستخدام SparseCore، يجب فهم المشاكل المحتملة وكيفية حلّها. يمكن أن تنشأ هذه المشاكل على المضيف أو داخل SparseCore نفسه أو في تفاعله مع TensorCores.

المؤثِّرات السلبية الشائعة على الأداء:

  • عنق الزجاجة في المضيف:
    • المشكلة: قد يتعذّر على وحدة المعالجة المركزية للمضيف معالجة البيانات مسبقًا وإرسالها إلى وحدة معالجة Tensor بسرعة كافية، ما يؤدي إلى عدم الاستفادة من SparseCores وTensorCores بشكل كافٍ. وهذا عامل محدودية أداء متكرّر.
    • التخفيف: راقِب استخدام وحدة المعالجة المركزية (CPU) للمضيف ومقاييس مسار الإدخال. حسِّن إجراءات تحميل البيانات ومعالجتها المُسبقة من جهة المضيف (راجِع نصائح تحويل COO). اضبط العلامة maximum_parallel_iterations لضبط عملية الجلب المُسبَق للبيانات بدقة.
  • عدم مزامنة TC/SC على النحو الأمثل (عدم توفّر ميزة "المعالجة المتوازية"):
    • المشكلة: إذا تم إيقاف خطوط نقل البيانات بين TensorCore وSparseCore أو لم تعمل بكفاءة، قد تستغرق إحدى الوحدتين وقتًا طويلاً في انتظار الأخرى، ما يؤدي إلى انخفاض معدل نقل البيانات الإجمالي للنظام.
    • التخفيف: تأكَّد من تفعيل ميزة "تداخل الطلبات" (على سبيل المثال، tf_xla_disable_full_embedding_pipelining = false أو ما يعادله).
  • الاختناقات الناتجة عن القيود:
    • المشكلة:
      • الحدود منخفضة جدًا: يمكن أن يؤدي ذلك إلى تقسيم الدُفعات الصغيرة بشكل مفرط (تقسيم دُفعات الإدخال إلى العديد من الدُفعات الفرعية الأصغر حجمًا للالتزام بالحدود الصارمة). على الرغم من أنّ ذلك يحافظ على صحة النتائج، إلا أنّ كل دفعة صغيرة تؤدي إلى بعض تكاليف المعالجة الإضافية، ما قد يؤدي إلى إبطاء التنفيذ العام. إذا كانت قيمة allow_id_dropping صحيحة، يمكن أن تؤدي الحدود المنخفضة جدًا أيضًا إلى حذف المعرّف، ما يؤثر في دقة النموذج.
      • الحدود القصوى مرتفعة جدًا (ولكنها لا تزال مناسبة): على الرغم من أنّ الحدود القصوى المرتفعة جدًا قد تمنع تقسيم البيانات إلى دفعات صغيرة، إلا أنّها قد تزيد من ضغط SPMEM بلا داعٍ إذا كانت خصائص البيانات الفعلية نادرًا ما تقترب من هذه القيم القصوى. وقد تؤدي أيضًا إلى استخدام أكبر من اللازم لمجموعة شرائح HBM.
      • أخطاء التجميع: إذا كانت الحدود التي تم ضبطها تتطلّب المزيد من حزمة SPMEM أو HBM مقارنةً بالذاكرة الفعلية المتاحة، سيتعذّر التجميع.
    • التخفيف من المشكلة: تأكَّد من ضبط الحدود بشكلٍ صحيح.
  • انحراف توزيع البيانات:
    • المشكلة: إذا كانت بعض أقسام SparseCore تتلقّى باستمرار عددًا أكبر بكثير من أرقام التعريف مقارنةً بغيرها (ما يشير إلى سوء توزيع أرقام التعريف)، ستصبح هذه الأقسام التي تمّت زيادة تحميلها عن طاقتها نقاط اختناق في الأداء.
    • التخفيف من المشكلة: يمكن أن يساعد خلط المعرّفات أثناء عملية تقسيم البيانات إلى دفعات صغيرة في التخفيف من هذه المشكلة في الجداول المكدّسة، خاصةً تلك التي تتضمّن جداول مستخدمين "نشطة". حلِّل توزيعات أرقام التعريف بعناية لضبط حدود مناسبة ومتوازنة لكل جدول.
  • مشاكل ترتيب الجداول:
    • المشكلة:
      • عدد قليل جدًا من الجداول المكدّسة: قد لا يكون ذلك كافيًا لإخفاء وقت استجابة ICI بفعالية أو تقليل النفقات العامة للمعالجة بشكلٍ كافٍ.
      • تداخل عدد كبير جدًا من الجداول: قد يؤدي ذلك إلى إنشاء جداول منطقية كبيرة جدًا يصعب إدارتها أو قد تتجاوز حدود الموارد المتاحة.
    • التخفيف من حدة المشكلة:
      • تأكَّد من توفّر العدد الأمثل من الجداول لتجميعها. تشير إرشادات عامة إلى أنّ "الموضع الأمثل" هو 5 إلى 100 جدول للتجميع.
  • الأرقام/التقسيم غير الفعّال:
    • المشكلة: يمكن أن يكون استخدام دقة FP32 الكاملة عندما تكون تنسيقات الدقة الأقل، مثل BF16 أو الأعداد الصحيحة الكمية، كافية (وتوفّر حسابًا أسرع) سببًا في حدوث اختناق في الأداء.
    • تخفيف المشكلة: استكشاف خيارات دقة أقل ومع ذلك، يجب الانتباه إلى أنّ التكميم نفسه يتضمّن بعض النفقات العامة وقد يتطلّب ضبطًا دقيقًا لمعلَمات التكميم للحفاظ على دقة النموذج.
  • تشبّع نطاق ترددي HBM:
    • المشكلة: يمكن أن يؤدي نقل البيانات بشكل مفرط من وإلى الذاكرة ذات النطاق الترددي العالي (HBM)، والذي قد يكون سببه عرض الميزات الصغير جدًا (ما يؤدي إلى زيادة كبيرة في مساحة التعبئة)، أو أنماط الوصول غير الفعّالة إلى الذاكرة، أو العدد الكبير جدًا من عمليات البحث، إلى استنفاد النطاق الترددي المتاح للذاكرة ذات النطاق الترددي العالي.
    • تخفيف المشكلة: يمكن أن يساعد توسيع نطاق عدد وحدات TPU في حلّ مشكلة التشبع في معدل نقل البيانات في HBM.

المشاكل الشائعة المتعلقة بالذاكرة:

  • خطأ في تجاوز سعة SPMEM (تعذُّر التجميع):
    • المشكلة: إذا تم ضبط قيمتَي max_ids_per_partition وmax_unique_ids_per_partition على مستوى مرتفع جدًا، قد يتعذّر على برنامج تجميع XLA تخصيص مساحة كافية من SPMEM، ما يؤدي إلى حدوث أخطاء في التجميع مثل: "Fixed size allocations (...) do not fit in TileSpmem (...)". بالإضافة إلى ذلك، إذا كان المصطلح (sample_count * feature_width) / kNumTiles (حيث kNumTiles هو عدد المربّعات لكل SC) كبيرًا جدًا بالنسبة إلى تجميع عناصر التشغيل المؤقتة داخل مربّع SPMEM، يمكن أن تحدث أخطاء مثل "Gather operand too large...".
    • تخفيف المشكلة: قلِّل حجم الدفعة أو زِد عدد الشرائح المستخدَمة للمعالجة.
  • خطأ تجاوز سعة مكدس HBM (وقت التشغيل أو التجميع):
    • المشكلة: إذا أدت مجموعة feature_width وmax_unique_nz_per_row وlogical_replica_count إلى متطلبات ذاكرة مكدّسة HBM تتجاوز ذاكرة HBM المتاحة، قد يؤدي ذلك إلى حدوث أخطاء نفاد الذاكرة (OOM) إما في وقت التشغيل أو أثناء التجميع.
    • تخفيف المشكلة: اضبط العلامة xla_sc_num_serialized_tables_to_optimize_hbm لتقليل استخدام حزمة HBM من خلال تسلسل معالجة الجداول (يؤدي ذلك عادةً إلى انخفاض الأداء).
  • استنفاد مساحة التخزين المؤقت في الذاكرة ذات النطاق الترددي العالي:
    • المشكلة: تحدث بشكل أساسي بسبب أوزان الطبقة الكثيفة الكبيرة جدًا، أو الثوابت العديدة المخزّنة في الذاكرة، أو جلب البيانات المسبق بشكل مفرط (قيمة maximum_parallel_iterations عالية).
    • التخفيف: راقِب استخدام الذاكرة لأخذ لقطات لعناصر متعدّدة باستخدام أدوات مثل XProf Memory Viewer.
  • تكلفة المساحة المتروكة:
    • المشكلة: يتمّ توسيع جداول التضمين لتكون متوافقة مع 32 بايت (أي ما يعادل 8 أرقام عشرية) في سمة الميزة. نتيجةً لذلك، تؤدي عروض الميزات الصغيرة (مثل، 1 قيمة عائمة) إلى زيادة كبيرة في مساحة التعبئة (على سبيل المثال، 7/8 من مساحة التخزين المؤقت المخصّصة هي مساحة تعبئة)، ما يؤدي إلى إهدار ذاكرة النطاق الترددي العالي. يتم أيضًا توسيع بُعد المفردات في الجداول ليكون مضاعفًا لعدد SparseCores في النظام، ولكن عادةً ما يكون هذا التأثير ضئيلاً بالنسبة إلى الجداول التي تحتوي على حجم مفردات كبير بما يكفي.

العوامل العامة التي تؤثّر في الأداء والذاكرة:

  • البنية: عدد الشرائح المتاحة وبنية الربط البيني بينها
  • حجم الدفعة: يؤثر بشكل مباشر في sample_count لكل SparseCore، ما يؤثر بدوره في استهلاك الذاكرة وحِمل الحوسبة.
  • تنسيق البيانات: من الضروري التأكّد من أنّ تنسيق البيانات على الجهاز فعّال لتحقيق الأداء الأمثل.

11. تحليل ملف SparseCore

يُعدّ تحليل ملف الأداء خطوة أساسية في تحديد المشاكل التي تؤثر سلبًا في الأداء والكشف عن فرص التحسين في أحمال عمل SparseCore.

  1. الحصول على تتبُّع:
    • استخدِم أدوات إنشاء الملفات الشخصية، مثل XProf، لتسجيل عملية تنفيذ مفصّلة أثناء تدريب النموذج أو تشغيل الاستدلال. سيوفّر هذا التتبُّع مخططًا زمنيًا للعمليات التي تحدث على الجهاز المضيف وTensorCores وSparseCores.
  2. فحص "أداة عرض سجلّ التتبُّع" (على سبيل المثال، في XProf أو TensorBoard):
    • نشاط المضيف: تدقيق نشاط المضيف هل هناك فجوات كبيرة في نشاط وحدة معالجة Tensor؟ قد تشير هذه الفجوات إلى أنّ المضيف يمثّل عنق الزجاجة، حيث لا يمكنه نقل البيانات بسرعة كافية. تحليل أداء مسار إدخال البيانات
    • نشاط TensorCore (TC) وSparseCore (SC):
      • اطّلِع على المخططات الزمنية للتنفيذ لكلّ من TC وSC. هل تعمل بشكل متوازٍ، ما يشير إلى فعالية عملية التجهيز؟ أو هل هناك فترات طويلة يكون فيها أحد الوحدات غير نشط وينتظر الوحدة الأخرى؟
      • حدِّد العمليات التي تستغرق أكبر وقت (العمليات الأطول مدة) على كلّ من SC وTC.
      • تُعدّ نواتج التتبُّع المرئية (التي تعرض غالبًا مربّعات ملوّنة تمثّل عمليات مختلفة بمرور الوقت، مثل TPU:0 SparseCore 1 (pid 1005)) قيّمة جدًا لتحديد العمليات السائدة وفترات عدم النشاط بشكل مرئي.
    • تحليل وقت الخطوة: يمكنك الاطّلاع على وقت الخطوة الإجمالي وفهم كيفية توزيعه أو تقسيمه بين معالجة المضيف واحتساب SC واحتساب TC.
  3. تحليل الذاكرة (أداة عرض الذاكرة في XProf):
    • استخدام الذاكرة لأخذ لقطات لعناصر متعدّدة: استخدِم أدوات مثل علامة التبويب "عارض الذاكرة" في XProf لفحص استخدام الذاكرة لأخذ لقطات لعناصر متعدّدة في HBM. يمكن أن يساعد ذلك في تحديد ما إذا كانت أوزان النماذج الكبيرة أو الثوابت أو الجلب المسبق المفرط للبيانات يستهلك مقدارًا كبيرًا من ذاكرة النطاق الترددي العالي. قد يؤدي تفعيل علامات مثل --vmodule=best_fit_allocator=1 إلى توفير سجلّات لأعلى استخدام للذاكرة المكدّسة.
    • استخدام الذاكرة المكدّسة (غير مباشر): على الرغم من أنّ تحديد ملفات تعريف الذاكرة المكدّسة المباشرة ذات النطاق الترددي العالي (HBM) قد يكون معقّدًا، إذا واجهت أخطاء "نفاد الذاكرة" وبدا استخدام الذاكرة المجمّعة معقولاً، فإنّ استنفاد الذاكرة المكدّسة ذات النطاق الترددي العالي (غالبًا بسبب الحدود الكبيرة جدًا أو عروض الميزات) هو السبب المحتمل. يمكن أن تساعد الصيغ المقدَّمة لاستخدام حزمة HBM في تقدير ذلك.
  4. البحث عن أنماط معيّنة:
    • التقسيم إلى دفعات صغيرة: إذا تم تجاوز الحدود بشكل متكرر، قد تلاحظ دليلًا على التقسيم إلى دفعات صغيرة في التتبُّع (على سبيل المثال، عدد أكبر من عمليات SC الصغيرة مقارنةً بما هو متوقع لحجم الدفعة العام). ويمكن غالبًا استنتاج ذلك من السجلات أو من خلال مراقبة عدد مرات استدعاء عمليات معيّنة.
    • إيقاف المعرّف: إذا كان خيار إيقاف المعرّف مفعّلاً ويحدث ذلك، قد تقدّم سجلّات النظام مؤشرات على ذلك. سيكون ذلك أيضًا مؤشرًا واضحًا على أنّ الحدود التي تم ضبطها مقيِّدة جدًا بالنسبة إلى البيانات المُدخَلة.
    • أوقات التجميع: يمكن أن تؤدي أوقات إعادة التجميع المطوّلة، خاصةً إذا كانت ميزة "التحسين المستند إلى الملاحظات" (FDO) مفعّلة ويتم تعديل الحدود بشكل متكرر، إلى إضافة عبء كبير إلى وقت التدريب الإجمالي.
  5. الربط بالعلامات والإعدادات:
    • اربط السلوك المرصود في الملف الشخصي بإعدادات SparseCore (الإعدادات في ملفات الحدود وعلامات XLA). على سبيل المثال، إذا تم ضبط قيمة xla_sc_num_serialized_tables_to_optimize_hbm على قيمة عالية، قد تتوقّع انخفاض أداء SC ولكن انخفاض استهلاك حزمة HBM.
  6. العملية التكرارية:
    • غالبًا ما تكون عملية إنشاء الملفات التعريفية عملية تكرارية لتحسين الأداء. أدخِل تغييرًا محدّدًا (اضبط حدًا أقصى أو أدنى، أو فعِّل ميزة أو أوقِفها)، وسجِّل ملفًا شخصيًا جديدًا، ثم قارِنه بالملف الشخصي السابق لمعرفة تأثير التعديل.

12. علامات تصحيح الأخطاء العامة

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

  • عمليات التحقّق من بطاقة التعريف (خارج النطاق):
    • العلم: xla_sparse_core_enable_id_bound_check = true
    • الغرض: تتيح إجراء عمليات تحقّق على نظام المضيف لرصد ما إذا كانت أيّ معرّفات تضمين في بيانات الإدخال تقع خارج نطاق المفردات الصالح المحدّد لجدول تضمين معيّن. يساعد ذلك في رصد المشاكل المتعلّقة ببيانات الإدخال غير الصحيحة أو التالفة.
  • أداة التحقّق من NaN:
    • العلم: xla_sc_detect_nan = true
    • الغرض: تتيح هذه السمة رصد قيم NaN (ليس رقمًا) ضمن بيانات الفاصلة العائمة التي تتم معالجتها على SparseCore. في حال رصد قيمة NaN في مدخلات أو مخرجات عمليات التجميع المختلفة، سيؤدي هذا الخيار إلى حدوث خطأ. تقدّم هذه الأخطاء عادةً معلومات عن مكان حدوث NaN.
  • أداة التحقّق من الحدود (الوصول إلى الذاكرة):
    • العلم: xla_sc_assert_level=bounds
    • الغرض: يفعّل هذا الخيار أداة على غرار ASAN (AddressSanitizer) تعيد كتابة تعليمات الوصول إلى الذاكرة (مثل عمليات تحميل/تخزين VMEM وعمليات الوصول المباشر إلى الذاكرة) لتضمين عمليات التحقّق الديناميكية. تتحقّق عمليات التحقّق هذه مما إذا كان الوصول إلى الذاكرة ضِمن الحدود المخصّصة لمنطقة الذاكرة المستهدَفة.
    • السلوك: في حال رصد محاولة وصول إلى الذاكرة خارج النطاق المسموح به، سيتعذّر التنفيذ.
    • تنبيه: من المحتمل أن ينتج عن أداة التحقّق هذه نتائج إيجابية خاطئة، على سبيل المثال، بسبب أنماط الوصول المعقّدة ذات الخطوات المتساوية التي لا تفهمها أداة التحقّق بالكامل. يتم تطبيق هذا التحويل في مرحلة متأخرة من عملية التجميع في الخلفية.
  • أداة فحص المخزن المؤقت (تلف الذاكرة):
    • الأعلام:
      • xla_tpu_buffer_contents_sanitizer_config='cores_to_sanitize: [TC, SC_SCS, SC_TILE], sanitizer_mode: LOCAL_ONLY'
      • xla_tpu_verify_launch_id_across_cores=true
    • الغرض: تساعد هذه العلامات في ضمان عدم إتلاف مخازن الذاكرة المؤقتة أو الكتابة فوقها عن غير قصد من خلال عمليات غير ذات صلة. تتحقّق أداة Buffer Sanitizer من محتوى المخازن المؤقتة للتأكّد من عدم تغييره بشكل غير متوقّع.

13. التوافق مع التكميم

تم تصميم SparseDenseMatmulOp في SparseCore لتتيح إجراء عمليات على جداول التضمين باستخدام كل من أنواع البيانات ذات الفاصلة العائمة 32 بت (FP32) والأعداد الصحيحة. على الرغم من أنّ تدريب النموذج يتم عادةً باستخدام دقة FP32 لجداول التضمين، يمكن تطبيق التكميم بعد التدريب (PTQ). تتيح عملية التكميم بعد التدريب استخدام أنواع بيانات أقل دقة (مثل الأعداد الصحيحة ذات 8 بت) للاستدلال، ما قد يؤدي إلى تحسين الأداء وتقليل مساحة الذاكرة المستخدَمة.

التكميم المحاكى:

يمكن ضبط SparseDenseMatmulOp لتنفيذ "تكميم محاكاة". في وضع التشغيل هذا، يتم أولاً تحديد كمية متجهات التضمين بدقة أقل، ثم يتم إلغاء تحديد الكمية بدقة أعلى (على سبيل المثال، FP32) قبل استخدامها في العمليات الحسابية اللاحقة. تسمح هذه التقنية بتدريب النماذج مع مراعاة تأثيرات التشويش الناتج عن التكميم. يمكن أن يؤدي التدريب باستخدام التكميم المحاكى إلى تحسين دقة النموذج النهائي عند تكميمه بالكامل للاستدلال.

سمات الإعدادات الخاصة بـ SparseDenseMatmulOp (للتكميم):

  • quantization_config_num_buckets = 256
    • تحدّد هذه السمة عدد الحِزم أو المستويات المنفصلة التي سيتم تقسيم رقم الفاصلة العائمة 32 بت إليها. على سبيل المثال، عند التكميم إلى أعداد صحيحة ذات 8 بت، يتم عادةً تحديد 2^8 =256 مجموعة.
  • quantization_config_low = -X.X
    • تحدّد هذه السمة الحد الأدنى لقيمة النقطة العائمة في نطاق التكميم. سيتم اقتطاع أي قيم إدخال أقل من الحد الأدنى المحدّد إلى قيمة الحد الأدنى هذه أثناء التكميم.
  • quantization_config_high = Y.Y
    • تحدّد هذه السمة الحد الأقصى لقيمة النقطة العائمة في نطاق التكميم. سيتم اقتطاع أي قيم إدخال أعلى من الحد الأقصى المحدّد إلى هذا الحد الأقصى للقيمة أثناء التكميم.

التفاعل مع الأرقام وعمليات نقل البيانات:

يمكن أن يتغير السلوك العددي للنموذج حسب ما إذا كان تجميع البيانات بين TensorCore وSparseCore مفعّلاً. في حال تفعيل ميزة "التنفيذ المتزامن"، قد تكون التدرّجات التي تتم معالجتها بواسطة SparseCore "قديمة" (من تكرار سابق). يمكن أن يتفاعل ذلك مع عملية التكميم ويؤثر في ديناميكيات تدريب النموذج أو دقته النهائية.

14. الميزات القادمة والتحسينات الأخيرة

يخضع نظام SparseCore الشامل للتطوير والتحسين المستمرَّين.

خارطة الطريق:

  • التقسيم إلى مجموعات صغيرة حسب السمة:
    • من المقرّر أن تكون هذه الميزة مكمّلة لإمكانات التجميع المصغّر الحالية حسب حجم المفردات.
    • سيسمح ذلك بتقسيم إضافي لمدخلات التضمين على طول سمة العيّنة. سيتم تحقيق ذلك من خلال تقديم حلقات على الجهاز يمكنها فلترة عمليات البحث ومعالجتها من مجموعة فرعية من العيّنات في كل مرة. يمكن أن تكون هذه الميزة مفيدة لإدارة أعداد كبيرة جدًا من معرّفات كل عيّنة أو لتحسين موازنة التحميل على مستوى وحدات المعالجة.
  • تحسين إمكانية التضمين مع أقل من 8 أعداد صحيحة في كل صف (عرض الميزات الصغيرة):
    • يستخدم التصميم الحالي غالبًا مساحة متروكة كبيرة لتضمين عروض الميزات التي تقل عن 8 أرقام عشرية (أي 32 بايت). يمكن أن يؤدي هذا التعبئة إلى إهدار ذاكرة النطاق الترددي العالي (HBM) وإمكانية عدم الاستفادة من موارد الحوسبة بشكل كامل. تهدف التحسينات المستقبلية إلى الحدّ من هذا القصور في الجداول التي تتضمّن سمات صغيرة.

التحسينات الأخيرة:

  • مرحلة إعداد عوامل التشغيل الخاصة بعملية التجميع في HBM:
    • يساعد هذا التحسين في تقليل الضغط على ذاكرة لوحة الخدش المشتركة (SPMEM) من خلال السماح بتنظيم بعض مدخلات أو مخرجات عملية التجميع في ذاكرة النطاق الترددي العالي (HBM) الأكبر.
  • انخفاض في استخدام ذاكرة التخزين المؤقت:
    • تمّ تنفيذ تحسينات لتقليل استهلاك ذاكرة حزمة HBM أثناء عمليات SparseCore، وذلك على النحو الأمثل بدون التأثير سلبًا في الأداء العام أو معدّل نقل البيانات.

تركّز هذه التحسينات على تحسين أداء SparseCore وكفاءة الذاكرة ومرونة التشغيل لنطاق أوسع من أحمال العمل المتفرقة.