FLOPs
تحصي FLOPs عمليات الفاصلة العائمة التي يحتاج إليها النموذج لتمريرة أمامية واحدة، وهي مقياس معياري لتكلفة الحوسبة. تعرّف على كيفية إحصائها ومقارنتها وتقليلها.
يمثل عدد FLOPs (عمليات الفاصلة العائمة) العمليات الحسابية التي تنفذها شبكة عصبية لمعالجة مدخل واحد، مثل صورة واحدة أو رمز واحد، وتتمثل هذه العمليات في معظمها في عمليات الضرب والجمع داخل طبقات الشبكة العصبية. ويقيس هذا العدد التكلفة الحاسوبية للنموذج بصرف النظر عن العتاد الذي يعمل عليه، لذا فهو الطريقة القياسية لمقارنة العبء الحاسوبي لمختلف البنى. وعادةً ما يُعبَّر عن تكلفة نماذج الرؤية بوحدة GFLOPs (مليارات العمليات) عند حجم إدخال محدد، كما يُعبَّر عن إجمالي الحوسبة المستخدمة لتدريب نموذج كبير بوحدة FLOPs.
الفرق بين FLOPs وFLOPS وMACs#
من السهل الخلط بين ثلاثة مصطلحات متشابهة:
- FLOPs (بحرف s صغير): عدد عمليات الفاصلة العائمة، وهي خاصية للنموذج وحجم الإدخال. ويقيس مقدار العمل المطلوب إنجازه.
- FLOPS (بحرف S كبير): عمليات الفاصلة العائمة في الثانية، وهي خاصية للعتاد مثل GPU. وتقيس سرعة إنجاز العمل؛ ويعطي تقسيم FLOPs للنموذج على ذروة FLOPS للجهاز أقصر زمن تشغيل ممكن.
- MACs: عمليات الضرب والتراكم. تتألف عملية MAC واحدة من عملية ضرب وعملية جمع، لذا تعادل MAC واحدة عمليتي FLOPs. وتورد بعض الأوراق والأدوات MACs تحت اسم FLOPs، ما يجعل أرقامها نصف القيم الفعلية.
كيفية احتساب FLOPs#
يأتي معظم FLOPs في الشبكة من ضرب المصفوفات والالتفافات. وتبلغ تكلفة الطبقة كاملة الاتصال ذات n من المدخلات وm من المخرجات نحو 2 × n × m FLOPs لكل إدخال. وتحسب طبقة الالتفاف جداءً نقطيًا واحدًا لكل قيمة إخراج، لذا تبلغ تكلفتها 2 × C_in × k × k × C_out × H_out × W_out، حيث تمثل k حجم النواة وH_out × W_out دقة الإخراج. وتضيف دوال التنشيط والتطبيع وعمليات الجمع مقدارًا ضئيلًا نسبيًا. يحسب المثال التالي تكلفة طبقة التفاف باستخدام معادلة، ثم يتحقق منها باستخدام عداد FLOPs المدمج في PyTorch:
import torch
from torch.utils.flop_counter import FlopCounterMode
# A 3x3 convolution mapping 64 channels to 128 on an 80x80 feature map
conv = torch.nn.Conv2d(64, 128, kernel_size=3, padding=1, bias=False)
x = torch.randn(1, 64, 80, 80)
# Each output value needs 64*3*3 multiply-accumulates (MACs); 1 MAC = 2 FLOPs
macs = 128 * 80 * 80 * 64 * 3 * 3
print(f"By formula: {2 * macs / 1e9:.3f} GFLOPs ({macs / 1e9:.3f} GMACs)")
# PyTorch's FLOP counter traces the real forward pass
with FlopCounterMode(display=False) as counter:
conv(x)
print(f"Counted: {counter.get_total_flops() / 1e9:.3f} GFLOPs")يعرض السطران 0.944 GFLOPs، ويبيّن سطر المعادلة أن كلفة الطبقة نفسها تبلغ 0.472 GMACs، أي نصف قيمة FLOPs. وبالنسبة إلى المحوّلات، تبلغ كلفة المرور الأمامي نحو 2 FLOPs لكل معلمة ولكل رمز، بينما تبلغ كلفة التدريب نحو 6؛ وهذه قاعدة تقريبية مستمدة من أبحاث قوانين التوسع، تقدّر إجمالي الحوسبة اللازمة لعملية تدريب واحدة وفقًا للعلاقة 6 × عدد المعلمات × عدد رموز التدريب.
FLOPs والسرعة الفعلية#
تتنبأ FLOPs بالسرعة على نحو تقريبي فحسب. يعتمد زمن الاستجابة أيضًا على حركة الذاكرة، ومدى قابلية كل عملية للتوازي، وما إذا كان العتاد يضم نوى محسّنة لها. أظهرت ورقة ShuffleNet V2 أن الشبكات ذات قيم FLOPs المتشابهة قد تعمل بسرعات مختلفة بوضوح على الجهاز نفسه، وأن الالتفافات العمقية، رغم انخفاض FLOPs فيها، غالبًا ما تحدّها سعة نطاق الذاكرة بدلًا من الحسابات. وتؤثر التحسينات في عوامل مختلفة أيضًا. يزيل تقليم النماذج وتصغير أحجام الإدخال العمليات، بينما يُبقي تكميم النماذج عدد العمليات كما هو ويجعل كل عملية أقل كلفة بالحساب باستخدام أعداد صحيحة من 8 بت. لذا تكون FLOPs أكثر فائدة كمرشح أولي قبل قياس زمن استجابة الاستدلال على الجهاز المستهدف، مثلًا باستخدام وضع قياس الأداء في Ultralytics:
FLOPs واختيار النموذج#
تُطرح عائلات النماذج بأحجام متعددة كي تتمكن الفرق من الموازنة بين الدقة والحوسبة، ويتناول درس حجم النموذج في Ultralytics Academy كيفية إجراء هذا الاختيار. يتراوح عدد FLOPs في Ultralytics YOLO26 من 5.5 GFLOPs لنموذج YOLO26n إلى 194.4 GFLOPs لنموذج YOLO26x عند إدخال بحجم 640×640، وتطبع model.info() عدد GFLOPs لأي نموذج محمّل. تستخدم المسيّرات والهواتف العاملة بالبطارية النسخ الأصغر، بينما تستطيع الخوادم السحابية تشغيل أكبرها. وبما أن كلفة الشبكة الالتفافية تتناسب مع عدد البكسلات، فإن حجم الإدخال يغيّر FLOPs بقدر ما يفعل حجم النموذج:
from ultralytics import YOLO
from ultralytics.utils.torch_utils import get_flops
# Load the smallest YOLO26 detection model and fuse its layers, as for inference
model = YOLO("yolo26n.pt")
model.fuse()
# Count GFLOPs for the same model at three input resolutions
for imgsz in [320, 640, 1280]:
print(f"{imgsz}px: {get_flops(model.model, imgsz):.1f} GFLOPs")تطبع الحلقة 1.3 و5.5 و23.4 GFLOPs: إذ تؤدي مضاعفة طول ضلع الإدخال إلى زيادة العدد بنحو أربعة أضعاف، ولذلك فإن تشغيل YOLO26n بدقة 1,280 بكسل يكلف أكثر من 20.9 GFLOPs التي يحتاج إليها YOLO26s، وهو نموذج يزيد عدد معلماته أربعة أضعاف، عند دقة 640.










