BFloat16 (BF16)
الفاصلة العائمة ذات 16 بت (BF16) هي تنسيق من 16 بتًا، له أسّ من 8 بتات مثل FP32 وكسر من 7 بتات، ويحافظ على نطاق FP32 بنصف الذاكرة. اختلافه عن FP16.
BFloat16 (الفاصلة العائمة الدماغية، BF16) تنسيق فاصلة عائمة من 16 بت، يتكون من بت إشارة واحد و8 بتات للأسّ و7 بتات للكسر. ويحافظ على عرض الأسّ نفسه المستخدم في تنسيق الفاصلة العائمة القياسي ذي 32 بت (FP32)، لذا يغطي النطاق نفسه من القيم، من نحو 1.2 × 10⁻³⁸ إلى 3.4 × 10³⁸، مع تخزين كل عدد في نصف الذاكرة. أما المقابل فهو الدقة: إذ لا توفر 7 بتات للكسر سوى رقمين إلى ثلاثة أرقام عشرية معنوية. ويتحمل التعلم العميق هذا التقريب جيدًا، وأصبح التنسيق، الذي ابتكره Google Brain من أجل TPUs التابعة إلى Google، التنسيق الافتراضي ذي 16 بت لتدريب النماذج الكبيرة على وحدات GPU الحديثة والمسرّعات.
كيفية تمثيل BF16 للأعداد#
قيمة BF16 هي النصف الأعلى تمامًا من قيمة FP32: الإشارة والأسّ نفسيهما، مع تقليص الكسر من 23 بتًا إلى 7. لذا لا يتطلب تحويل FP32 إلى BF16 سوى تقريب البتات الـ16 الدنيا، بينما يضيف التحويل العكسي أصفارًا، ما يجعل تنفيذ التنسيق في العتاد قليل التكلفة. أما التنسيق الشائع الآخر ذي 16 بت، وهو IEEE FP16 أو الدقة النصفية، فيوزع بتاته بطريقة مختلفة، مع 5 بتات للأسّ و10 للكسر، ما يوفر دقة أكبر على حساب النطاق. وتوضح مقارنة التنسيقات الثلاثة على القيم نفسها هذا التنازل:
import torch
# Largest value, smallest normal value, and spacing just above 1.0 for each format
for dtype in [torch.float32, torch.float16, torch.bfloat16]:
info = torch.finfo(dtype)
print(f"{dtype!s:15} max={info.max:.3g} tiny={info.tiny:.3g} eps={info.eps:.3g}")
# A large activation, a tiny gradient, and a value that needs fine precision
x = torch.tensor([70000.0, 1e-8, 1.001953125])
print("FP16:", x.half().tolist())
print("BF16:", x.bfloat16().tolist())يبلغ الحد الأقصى لـBF16 مقدار 3.39e38، مقابل 65,504 لـFP16، كما تطابق أصغر قيمة طبيعية له، 1.18e-38، قيمة FP32. يحوّل FP16 القيمة 70,000 إلى ما لا نهاية والقيمة 1e-8 إلى صفر، بينما يحتفظ BF16 بهما على شكل 70,144 ونحو 1.0e-8. ويحافظ التباعد الأدق لقيم FP16 (eps 0.000977 مقابل 0.00781 لـBF16) على 1.001953125 تمامًا، بينما يقرّبها BF16 إلى 1.0.
مقارنة BF16 وFP16 في التدريب#
يكون النطاق أهم من الدقة أثناء التدريب. فكثيرًا ما تقل التدرجات عن أصغر القيم التي يستطيع FP16 تمثيلها فتختفي؛ لذا يضرب تدريب الدقة المختلطة باستخدام FP16 الخسارة في عامل قياس قبل الانتشار العكسي، ويخفض هذا العامل كلما فاضت التدرجات، في تقنية تُسمى تحجيم الخسارة. ولا يحتاج BF16 إلى تحجيم الخسارة لأن نطاقه يساوي نطاق FP32، كما أن تدريب BF16 يطابق نتائج FP32 في نماذج الرؤية والكلام واللغة والتوصية بالعدد نفسه من التكرارات ومن دون تغيير المعلمات الفائقة. يحتفظ التدريب بالدقة المختلطة بنسخة رئيسية من الأوزان بتنسيق FP32، وينفذ عمليات ضرب المصفوفات بتنسيق BF16 مع التجميع بتنسيق FP32، لأن جمع كثير من النواتج ذات كسر من 7 بتات بتنسيق BF16 سيؤدي إلى فقدان دقة أكبر من اللازم. يعتمد الاختيار بين التنسيقين ذوي 16 بت إلى حد كبير على العتاد:
يطبّق PyTorch تنسيق BF16 عبر الدقة المختلطة التلقائية باستخدام torch.autocast(device_type="cuda", dtype=torch.bfloat16). ويتيح Ultralytics YOLO الخيار نفسه لـالتدريب باستخدام amp="bf16"، الذي ينفذ المرور الأمامي ضمن autocast بصيغة BF16 ويعطّل مقياس التدرج الذي يستخدمه الوضع الافتراضي FP16، على وحدات GPU التي تعمل بـCUDA وتدعم BF16 أصليًا.
دعم العتاد#
تجري عمليات الضرب في وحدات المصفوفات في الجيلين الثاني والثالث من Cloud TPU التابعة إلى Google بصيغة BF16، مع التجميع بصيغة FP32، وقد حافظت أجيال TPU اللاحقة على هذا التنسيق. وتشغّل وحدات GPU من NVIDIA تنسيق BF16 على Tensor Cores بدءًا من جيل Ampere، بما في ذلك وحدات GPU من طراز A100 وH100 وBlackwell، كما تسرّع معالجات Intel Xeon المزودة بامتدادات المصفوفات المتقدمة (AMX) هذا التنسيق على CPU. وعلى NVIDIA A100، يصل الأداء الأقصى لعمليات Tensor Core بصيغتي BF16 وFP16 إلى 312 تيرافلوب، أي 16 ضعف أداء عمليات FP32 القياسية على وحدة GPU البالغ 19.5 تيرافلوب.
BF16 والتنسيقات ذات الصلة#
- الدقة النصفية (FP16): تنسيق IEEE ذي 16 بت، يوفر دقة أكبر ونطاقًا أضيق بكثير. ولا يزال شائعًا للاستدلال، إذ تبقى التنشيطات ضمن نطاقه وتفيد دقته الإضافية.
- TF32: نمط حسابي في NVIDIA Tensor Core، يجمع بين أسّ BF16 ذي 8 بتات وكسر FP16 ذي 10 بتات، ويمكن للمكتبات استخدامه لضرب المصفوفات بصيغة FP32 على وحدات GPU من Ampere والأجيال الأحدث، مع بقاء الموترات مخزنة بصيغة 32 بت.
- FP8: تنسيقات النقطة العائمة ذات 8 بتات مثل E4M3 وE5M2، التي تدعمها وحدات GPU من جيل Hopper وBlackwell، وتخفض استهلاك الذاكرة إلى النصف مرة أخرى عند تدريب أكبر النماذج واستدلالها.
- تكميم النماذج: يحوّل الأوزان المدربة إلى تنسيقات الأعداد الصحيحة مثل INT8 أو INT4 لنشرها.
BF16 في نماذج اللغة الكبيرة#
تُدرّب معظم نماذج اللغة الكبيرة ذات الأوزان المفتوحة (LLMs) باستخدام الدقة المختلطة بصيغة BF16، وتُنشر بأوزان BF16، التي تُستخدم مرجعًا لمقارنة إصدارات FP8 وINT4 المكمّمة. وبواقع بايتين لكل معلمة، تستهلك أوزان نموذج ذي 70 مليار معلمة 140 GB بصيغة BF16، وهو ما يتجاوز سعة NVIDIA H100 واحدة البالغة 80 GB، لذا يتطلب تقديم مثل هذا النموذج بصيغة BF16 توزيعه على وحدتي GPU على الأقل.










