متى تؤتي وحدة معالجة الرسوميات ثمارها: نموذج roofline لمسح المعلمات، حيث رقم العنوان 167x هو في الحقيقة 27x خوارزمية × 6.2x عتاد
مقال من سلسلة "اختبارات رجعية بلا أوهام".
انتهى سلم السرعة على نغمة غير مُرضية عن قصد. كنا قد أخذنا مسح معلمات من 80 توليفة من 69.9 ثانية بـpandas إلى 0.23 ثانية بـnumba المتوازية على معالج مركزي لحاسوب محمول — 298x مقيسة — ثم جادلنا بأن وحدة معالجة الرسوميات (GPU) ليست الدرجة المفقودة. قسم التعليقات لم يتقبل ذلك بهدوء، وكان محقاً في ألا يفعل. "ليست الدرجة المفقودة" ادعاء عن حمل عمل واحد، بحجم واحد. إنه ليس قانوناً من قوانين الطبيعة. لذا يفعل هذا المقال الشيء الصادق ويضع وحدة معالجة الرسوميات على طاولة الاختبار.
النتيجة ليست حكماً نهائياً، بل منحنى. تقدم وحدة معالجة الرسوميات على المعالج المركزي ليس رقماً واحداً يمكنك طباعته على شريحة عرض؛ إنه دالة في كمية العمل التي تُسلّمها إليها في كل استدعاء. على الحساب المسبق لمؤشراتنا متعددة الأطر الزمنية، يمتد تسريع وحدة معالجة الرسوميات على محرك المعالج المركزي من 54.5x عندما نطلب منها توليفة معلمات واحدة في كل مرة حتى 359.6x عندما نطلب 61 دفعة واحدة. نفس النواة، نفس البيانات، نفس العتاد — الشيء الوحيد الذي تغير هو الدفعة. مقياس أداء يُبلّغ عن أحد هذين الرقمين ويُخفي الآخر لا يقيس وحدة معالجة الرسوميات، بل يختار عنواناً.
وحتى 359.6x ليست ما تبدو عليه. فكّكها وستجد أن رقم عنوان كبيراً متعدد الأطر الزمنية قدره 167x يتحلل إلى 27x من الخوارزمية — إعادة كتابة تجعل المعالج المركزي أيضاً أسرع بـ27x — مضروبة في 6.2x من العتاد الفعلي. وحدة معالجة الرسوميات لم تصنع الـ27x. الرياضيات صنعتها. هذا المقال عن التمييز بين الاثنين، لأن الخلط بينهما هو الطريقة التي تُباع بها بطاقة رسوميات بـ2,000 دولار لحل مشكلة كان git commit سيحلها مجاناً.
المصدر: كل الأرقام أدناه مقيسة على Apple M2 Max، بدقة fp32 على وحدة معالجة رسوميات Metal عبر MLX مقابل fp64 بـnumba على اثني عشر خيطاً من خيوط المعالج المركزي، من سكريبتَي القياس engine_multitf_gpu.py وbench_param_sweep.py لدينا، كل منهما محروس بفحص تكافؤ يؤكد أن مساري وحدة معالجة الرسوميات والمعالج المركزي يُنتجان نفس الصفقات. لا توجد ورقة مرافقة عامة لهذا المقال — السكريبتات هي السجل.
السؤال هو نموذج roofline، وليس مقياس أداء

السبب في أن سؤال "كم هي وحدة معالجة الرسوميات أسرع" ليس له جواب واحد هو نموذج roofline (Williams وWaterman وPatterson، 2009). الأداء القابل للتحقيق لأي معالج مُقيَّد بسقفين في آن واحد: سقف مسطح تُحدده ذروة الحساب (FLOP/s)، وسقف مائل يُحدده عرض النطاق الترددي للذاكرة مضروباً في الكثافة الحسابية (arithmetic intensity) — عدد العمليات المفيدة التي تُجريها لكل بايت تنقله. العمل الرخيص لكل بايت يعيش تحت السقف المائل وهو محدود بعرض النطاق الترددي (bandwidth-bound)؛ والعمل الغني لكل بايت يصل إلى السقف المسطح وهو مُقيَّد بالحساب (compute-bound). السقف المسطح لوحدة معالجة الرسوميات يشمخ فوق سقف المعالج المركزي، لكن سقفها المائل — والأهم من ذلك، تكلفتها الثابتة لكل استدعاء — لا يتقلصان بنفس الرشاقة.
بالنسبة لمسح المعلمات، يهيمن حد ثالث على الجانب الأيسر من المخطط: نفقات الإطلاق والنقل. كل استدعاء لوحدة معالجة الرسوميات يدفع ثمناً شبه ثابت — إرسال النواة، نقل المُدخلات عبر حد الذاكرة (الموحدة على Apple Silicon، لكنها ليست مجانية)، ونقل النتائج للخلف. لنُنمذج الوقت الفعلي لدفعة من توليفة كالتالي
حيث هي تلك النفقات الثابتة، و هي التكلفة الحدية لوحدة معالجة الرسوميات لكل توليفة، و هي تكلفة المعالج المركزي. ويكون التسريع عندئذ
هذا الكسر الواحد يشرح المقال بأكمله. عند صغيرة، تسحق في المقام النسبة — دفعت ثمن إيقاظ وحدة معالجة الرسوميات وبالكاد استخدمتها. مع نمو تستهلك عبر توليفات أكثر ويتسلق التسريع نحو خطه التقاربي ، النسبة العتادية الحقيقية. تقع نقطة المنتصف عند : "نقطة حافة" (ridge point) في فضاء الدفعات تخبرك بمدى الاتساع الذي يجب أن يبلغه مسحك قبل أن تصل وحدة معالجة الرسوميات ولو إلى نصف ما يمكنها أن تكونه. مسح من بضع عشرات التوليفات يجلس بعيداً على يسار تلك الحافة. ومسح من الآلاف يجلس على الجزء المسطح حيث تكسب وحدة معالجة الرسوميات سقفها أخيراً.
لذا فالسؤال الصحيح ليس أبداً "هل وحدة معالجة الرسوميات أسرع". بل "هل مسحي على يمين الحافة، وهل عملي لكل توليفة مُقيَّد بالحساب بما يكفي ليبلغ السقف المسطح عندما يصل إلى هناك". يجب أن يتحقق الشرطان معاً. بقية هذا المقال تقيس أين تقع تلك العتبات فعلياً.
حكم الإطار الزمني الواحد: وحدة معالجة الرسوميات تفوز بالكاد

ابدأ بحمل العمل الذي استخدمه سلم السرعة: مسح HMA/HMA3 على إطار زمني واحد، 80 توليفة على 150,000 شمعة. أضفنا درجة سادسة إلى ذلك السلم — M5، المؤشرات على وحدة معالجة رسوميات Apple عبر MLX، والصفقات لا تزال تُستخرج على المعالج المركزي. بعد الإحماء، أفضل من ثلاثة قياسات، وبوابة التكافؤ خضراء:
| الطريقة | الوقت الفعلي | مقابل pandas | توليفة/ثانية |
|---|---|---|---|
| M0 pandas + حلقة | 287.08 ث | 1.0x | 0.3 |
| M2 numba (نواة واحدة) | 2.02 ث | 142x | 39.7 |
| M4 mp + numba (12 نواة) | 0.33 ث | 883x | 245.9 |
| M5 MLX GPU (fp32) | 0.10 ث | 2796x | 779.2 |
مقابل خط الأساس التسلسلي الساذج تبدو وحدة معالجة الرسوميات بطولية — 2,796x. لكن هذه مقارنة لا ينبغي لأي شخص صادق أن يجريها: إنها تضع تطبيقاً جيداً لوحدة معالجة الرسوميات في مواجهة أسوأ تطبيق للمعالج المركزي. ضع وحدة معالجة الرسوميات في مواجهة المعالج المركزي الذي ستنشره فعلاً — نفس النواة على النوى الاثنتي عشرة كلها، M4 — وينهار الفوز إلى 3.2x رصينة (779 مقابل 246 توليفة في الثانية). بطاقة رسوميات كاملة، تُشغّل المسح بأكمله، تتفوق على مجمع معالج مركزي باثنتي عشرة نواة بمعامل ثلاثة.
ثلاثة فاصلة اثنان ليست لا شيء. لكنها أيضاً ليست السبب الذي يدفع أحداً لشراء وحدة معالجة رسوميات. وهي بالضبط ما يتنبأ به نموذج roofline لمسح بهذا الضيق: 80 توليفة هي يسار الحافة. نفقات الإطلاق والنقل الثابتة لا تزال شريحة معتبرة من مهمة تستغرق 0.10 ثانية، لذا لا نصل أبداً إلى الخط التقاربي . والأسوأ أن جزءاً من التكلفة لكل توليفة هو تمريرة استخراج الصفقات بتكلفة O(n)، التي تركناها عمداً على المعالج المركزي — حد لا تستطيع وحدة معالجة الرسوميات تسريعه إطلاقاً (المزيد عن السبب في القسم التالي). لحلقة بحث بإطار زمني واحد بهذا الحجم، يظل حكم سلم السرعة الأصلي قائماً: وحدة معالجة الرسوميات ليست الدرجة المفقودة. numba المتوازية وضعتك بالفعل عند 0.23–0.33 ثانية، وقصّ ذلك إلى 0.10 ليس ما يزيل العائق أمام الباحث. التنسيق المحيط بالمسح هو ما يفعل.
الكلمة المثيرة للاهتمام في ذلك الحكم هي بهذا الحجم. تحرك يميناً على محور الدفعات وتتغير القصة.
أين تعيش التكلفة فعلياً
قبل أن نُكبّر الدفعة، انظر إلى ما ندفع ثمنه فعلياً، لأن نموذج roofline لا يكافئك إلا إذا كان الجزء المكلف مُقيَّداً بالحساب. حلّل المسح وستجد أن كله تقريباً شيء واحد: عمليات الالتفاف (convolutions) للمتوسط المتحرك المُرجّح. الـHMA هو ثلاث WMAs؛ والـHMA3 أربع؛ وكل توليفة تُعيد تشغيلها على السلسلة كاملة. استخراج الصفقات — المرور على مصفوفتي المؤشرين، إيجاد انقلابات إشارة hma - hma3، تسجيل التنفيذات — تمريرة واحدة رخيصة بتكلفة O(n). المسح حمل عمل التفافي يرتدي زي استراتيجية تداول.
هذا التقسيم هو بالضبط نظاما roofline:
- عمليات الالتفاف مُقيَّدة بالحساب. كل سعر يُقرأ في العديد من مجاميع النوافذ المتداخلة، لذا فالكثافة الحسابية — عمليات لكل بايت منقول — عالية. هذا العمل يمد يده نحو السقف الحسابي المسطح، وسقف وحدة معالجة الرسوميات المسطح هو الشامخ. والأفضل من ذلك أن النوافذ تتداخل عبر التوليفات: WMA بطول 40 مفيدة لعشرات التوليفات، لذا فالحساب المسبق على دفعات يتقاسمها مرة واحدة بدلاً من إعادة حسابها لكل توليفة. تجميع الدفعات لا يستهلك نفقات الإطلاق فحسب؛ بل يرفع الكثافة الحسابية بإعادة استخدام التحميلات. هذا هو الجزء الذي ينتمي إلى وحدة معالجة الرسوميات.
- استخراج الصفقات محدود بعرض النطاق الترددي ومليء بالتفرعات. تمريرة تسلسلية واحدة، تفرعات معتمدة على البيانات عند كل تقاطع، وبلا إعادة استخدام تقريباً. كثافته الحسابية قرب الأرضية، وتدفق التحكم فيه عدائي تجاه جهاز SIMD. دفعه إلى وحدة معالجة الرسوميات سيشتري القليل ويكلف الكثير؛ فيبقى على المعالج المركزي. ما يعني أنه الذيل التسلسلي في تقسيم بحسب قانون Amdahl — أرضية ثابتة لا يستطيع تسريع وحدة معالجة الرسوميات اختراقها أبداً، وجزء من سبب تشبع رقم الإطار الزمني الواحد عند 3.2x.
هناك درس ثانٍ أكثر حدة يختبئ في النسخة متعددة الأطر الزمنية من هذه النواة، وهو مصدر الـ27x التي ما زلنا نعد بشرحها. محرك الأطر المتعددة يُحاذي HMA من إطار زمني أعلى على فهرس الدقيقة الواحدة الأساسي بدون نظر مستقبلي. مكتوبةً بالطريقة البديهية، هذه أعمال بتكلفة O(length^1.5) لكل شمعة — إعادة حساب المتوسطات المتحركة للإطار الأعلى عند كل شمعة أساسية. لكن الـHMA المُحاذاة خطية في مخزن مؤقت قصير من آخر بضع شموع مغلقة من الإطار الأعلى بالإضافة إلى الإغلاق الجاري، لذا ينهار الحساب الكامل لكل شمعة إلى متجه أوزان ثابت: conv1d واحدة على سلسلة الشموع المغلقة تليها عملية gather بتكلفة O(n). مئات الملايين من العمليات الزائدة تصبح التفافاً على سلسلة أقصر بكثير.
هذا الانهيار فوز خوارزمي، وليس عتادياً. إنه صيغة أفضل. يعمل على وحدة معالجة الرسوميات، ويعمل بنفس الجودة على المعالج المركزي — np.correlate بالإضافة إلى gather، بدقة fp64. أبقِ هذا راسخاً في ذهنك: أكبر عامل منفرد في رقم عنوان الأطر المتعددة هو إعادة كتابة متاحة لجهاز بلا وحدة معالجة رسوميات على الإطلاق. عندما نُفكك الـ167x أخيراً، هذا هو الـ27x.
التقدم ينمو مع حجم الدفعة

الآن إلى القياس الذي طلب منا نموذج roofline إجراءه. خذ المحور المكلف — الحساب المسبق لـHMA الإطار الأعلى المُحاذاة على سلسلة الدقيقة الواحدة الأساسية، أطول تدفق شموع لدينا — وأطعم وحدة معالجة الرسوميات عدداً متزايداً من توليفات الأطوال لكل استدعاء، . خط أساس المعالج المركزي هنا هو محرك الإنتاج الصادق: numba مع prange عبر النوى الاثنتي عشرة كلها. لكل دفعة نقيس الاثنين ونأخذ النسبة.
| الدفعة (توليفة/استدعاء) | تسريع وحدة معالجة الرسوميات مقابل محرك المعالج المركزي بـ12 نواة |
|---|---|
| 1 | 54.5x |
| 2 | 102.5x |
| 4 | 129.5x |
| 8 | 187.4x |
| 16 | 267.4x |
| 32 | 245.0x |
| 61 | 359.6x |
هذه هي مرسومة بقياسات حقيقية. عند وحدة معالجة الرسوميات متقدمة بالفعل بـ54.5x — لأن هذه المقارنة هي مقابل المحرك الساذج لكل شمعة، فالانهيار الخوارزمي مخبوز في الرقم حتى عند توليفة واحدة — لكنها ليست قريبة من سقفها إطلاقاً: النفقات الثابتة لا تزال تهيمن على استدعاء التوليفة الواحدة. ضاعف الدفعة ويكاد التسريع يتضاعف إلى 102.5x؛ بحلول يصبح 267.4x؛ وبحلول يصبح 359.6x ولا يزال يتسلق بشكل مرئي. التقدم ينمو مع حجم المشكلة. هذه هي الجملة الأهم على الإطلاق عن وحدات معالجة الرسوميات ومسوح المعلمات، وهي النقيض التام للطريقة التي تُقتبس بها تسريعات وحدات معالجة الرسوميات عادة — وكأنها خاصية ثابتة للشريحة.
ملاحظتا صدق، لأن هذه سلسلة اختبارات رجعية بلا أوهام وجدول رتيب نظيف يستحق الشك دائماً.
أولاً، الانخفاض: تقرأ 245.0x، أدنى من 267.4x عند . هذه ليست ضوضاء تُكنس تحت السجادة — إنها أثر لحدود الكتل. conv1d لدينا تحزم 32 طولاً في كتلة نواة واحدة، لذا تملأ كتلة واحدة بالضبط بلا فائض، بينما تفيض إلى كتلة ثانية يصادف أنها تُشبع الجهاز بشكل أفضل. بيت القصيد من roofline هو الاتجاه، والجهاز الحقيقي يحتوي على درجات تكميم (quantization) في داخله؛ نحن نُبلّغ عن التذبذب بدلاً من الانتقاء الملائم حوله.
ثانياً، والأهم: 54.5x و359.6x كلتاهما مقابل محرك المعالج المركزي الساذج، ولا واحدة منهما هي الفوز العتادي. كلا الرقمين لا يزال يحتوي على الانهيار الخوارزمي البالغ 27x. لو استبدلت بخط أساس المعالج المركزي الخوارزمية المنهارة وهي تعمل على المعالج المركزي — نفس الصيغة، بدقة fp64، والجانبان محسّنان — لتقلص كل صف بذلك المعامل تقريباً. وهذا بالضبط هو التفكيك الذي يجعله القسم التالي دقيقاً.
التفكيك الصادق: 27x خوارزمية × 6.2x عتاد

لفصل الخوارزمية عن السيليكون عليك قياس ثلاثة مسارات على نفس شبكة الأطر الزمنية المتعددة، لا اثنين. لذا يُشغّل مقياس الأداء:
- cpu-engine — محرك numba الإنتاجي، HMA مُحاذاة لكل شمعة عبر كل النوى. خط الأساس الساذج-لكن-المتوازي.
- cpu-collapsed — متجهات الأوزان المنهارة،
np.correlateبالإضافة إلى gather، بدقة fp64، على المعالج المركزي. نفس العتاد كما في (1)، وخوارزمية أفضل. - gpu-mlx — الأوزان المنهارة كـ
conv1dعلى دفعات على وحدة معالجة رسوميات Metal، بدقة fp32. نفس الخوارزمية كما في (2)، وعتاد مختلف.
اصطفّها معاً ويتحلل رقم عنوان الأطر الزمنية المتعددة الكامل بنظافة:
العامل الأيسر، 27x، هو الخوارزمية — انهيار من-لكل-شمعة-إلى-التفاف من القسم السابق. لا علاقة له بوحدة معالجة الرسوميات. طبّقه بـnumpy ويصبح المعالج المركزي لحاسوبك المحمول أسرع بـ27x على حمل العمل هذا مقابل ثمن إعادة هيكلة للكود. العامل الأيمن، 6.2x، هو العتاد — الفوز الصادق، بالمثل مقابل المثل، لوحدة معالجة رسوميات Metal على نفس الخوارزمية المحسّنة على اثنتي عشرة نواة معالج مركزي. تلك الـ6.2x هي الجزء الوحيد الذي احتجت فعلاً إلى وحدة معالجة رسوميات للحصول عليه.
هذه هي عبرة المقال بأكملها مصوغة كعملية حسابية. عندما يعرض عليك مقياس أداء من مورّد، أو ملف README لمكتبة، أو زميل متحمس "167x على وحدة معالجة الرسوميات"، ينبغي أن يكون رد الفعل التلقائي سؤالاً واحداً: ما هو خط أساس المعالج المركزي؟ إذا كان خط الأساس هو التطبيق الساذج — وهو كذلك في الغالبية الساحقة من الحالات، لأن خط أساس بطيء يصنع شريحة عرض أفضل — فمعظم رقم العنوان فوز خوارزمي كان المعالج المركزي يستحقه أيضاً، والمتبقي وحده هو العتاد. هنا المتبقي هو 6.2x. اقتباس 167x يُضخّم مساهمة العتاد بحوالي 27 ضعفاً.
ولاحظ كيف تحرك عامل العتاد نفسه مع حجم المشكلة. على مسح الإطار الزمني الواحد الصغير كان الفوز الحقيقي لوحدة معالجة الرسوميات على أفضل معالج مركزي 3.2x. وعلى الحساب المسبق متعدد الأطر الزمنية الأكبر كان 6.2x — نفس الشريحتين، وميزة عتادية تكاد تتضاعف، فقط لأن حمل العمل الأكبر يدفع أعلى في roofline نحو السقف الحسابي المسطح لوحدة معالجة الرسوميات قبل أن يستطيع المعالج المركزي مجاراته. التقدم العتادي ليس ثابتاً هو الآخر. إنه نقطة على نفس المنحنى الصاعد، والطريقة التي تتحرك بها يميناً على ذلك المنحنى هي أن تجعل الدفعة أكبر والعمل لكل توليفة أغنى.
دليل قرار: ما مدى الاتساع الذي يجب أن يبلغه المسح؟

اطوِ نموذج roofline من جديد إلى قرار يمكنك اتخاذه قبل إنفاق المال. تؤتي وحدة معالجة الرسوميات ثمارها عندما يتحقق شرطا roofline معاً: مسحك على يمين حافة الدفعات (، بحيث تُستهلك نفقات الإطلاق والنقل الثابتة)، وعملك لكل توليفة مُقيَّد بالحساب (كثافة حسابية غنية بما يكفي لبلوغ السقف المسطح، لا تمريرة رقيقة بتكلفة O(n)). بشكل ملموس، مما قسناه:
- بضع عشرات التوليفات لاستراتيجية بإطار زمني واحد: تجاوز وحدة معالجة الرسوميات. أنت على يسار الحافة؛ الفوز الصادق على numba المتوازية هو ~3.2x على مهمة تستغرق أصلاً عُشر ثانية. الاختناق ليس النواة، بل كل ما حولها.
- آلاف التوليفات، أو حساب مسبق متعدد الأطر الزمنية / متعدد المؤشرات حقاً: وحدة معالجة الرسوميات تكسب مكانها. النفقات العامة تُستهلك، وعمليات الالتفاف المشتركة ترفع الكثافة الحسابية، والفوز العتادي يتسلق إلى 6.2x ويواصل الارتفاع مع الدفعة. هذا هو النظام الذي تُحوّل فيه وحدة معالجة الرسوميات مسحاً يمتد طوال الليل إلى استراحة قهوة.
- اصعد سلم المعالج المركزي أولاً — إنه أرخص ويأتي أولاً. الـ298x على المعالج المركزي والانهيار الخوارزمي البالغ 27x مجانيان أو يكادان، وهما شرطان مسبقان لا بديلان: الـ6.2x لوحدة معالجة الرسوميات هي فوق الخوارزمية المنهارة التي كان عليك كتابتها على أي حال. وحدة معالجة رسوميات مُثبَّتة على خط أنابيب ساذج تقيس في الغالب السذاجة.
هناك أيضاً ضريبة على فرع وحدة معالجة الرسوميات لا علاقة لها بالسرعة، وعليك تسعيرها: وحدة معالجة رسوميات Metal من Apple لا تملك fp64 على الإطلاق. كل شيء يعمل بـfp32، بدقة نسبية ~1.2e-7. هذا يقتل حيلة الكتب الدراسية للمتوسطات المتحركة السريعة — WMA بالمجموع التراكمي (prefix-sum) بتكلفة O(n) — لأنه عند مقياس سعر قرب 30,000 على 150k شمعة تبلغ المجاميع الجارية ~1e14، أي سبع مراتب من الحجم بعد نطاق الأعداد الصحيحة الآمن لـfp32؛ قسنا أخطاء نسبية تصل إلى ~2e2 (معامل مئتين، وليس اثنين بالمئة). الصياغة العاملة هي الالتفاف المباشر بالنوافذ، حيث كل مجموع نافذة هو عدد محدود من حدود متقاربة الحجم وتبقى fp32 دقيقة حتى ~8e-7. وحتى حينها، استراتيجية تُقرر بناءً على إشارة hma - hma3 ستقلب تقاطعاً بين الحين والآخر على شمعة حدّية يكاد المنحنيان يتلامسان عندها، لأن تقريب fp32 يُرجّح كفة تعادل شبه تام. لهذا يُشحن مسار وحدة معالجة الرسوميات مع بوابة تكافؤ تقيس مقدار تباعد الصفقات — فرق PnL بنقاط الأساس، والإزاحة النسبية في عدد الصفقات — بدلاً من التأكيد على مخرجات متطابقة بتاً ببت لا يمكنها تسليمها أبداً. في تشغيلنا كان ذلك التباعد 90 تنفيذاً مُزاحاً من أصل 479,016 (0.019%)، داخل حدود التسامح بوضوح، لكن العبء حقيقي: الذهاب إلى وحدة معالجة الرسوميات يعني امتلاك قصة تطابق عددي، وليس مجرد ساعة أسرع. هذه التكلفة الهندسية جزء من نقطة التعادل أيضاً.
الأرقام على شكل Apple؛ المنحنى ليس كذلك
كل رقم أعلاه هو Apple M2 Max: جهاز بذاكرة موحدة تتقاسم فيه وحدة معالجة الرسوميات والمعالج المركزي مخزناً واحداً، ووحدة معالجة رسوميات تعمل بـfp32 فقط بلا دقة مزدوجة. بطاقة منفصلة من NVIDIA أو AMD تُغيّر الثوابت، ويستحق الأمر أن نكون صريحين حول الاتجاه الذي يتحرك فيه كل ثابت، لأن شكل الحجة ينجو حتى عندما لا تنجو الأرقام.
- نفقات النقل تصبح أسوأ، لا أفضل. البطاقة المنفصلة تجلس خلف PCIe، فتقوم المُدخلات والنتائج بنسخة حقيقية عبر الناقل تتجنبها الذاكرة الموحدة. هذا يدفع حافة الدفعات نحو اليمين — تحتاج إلى مسح أوسع حتى من ذي قبل لكي تستهلك وحدة معالجة رسوميات منفصلة تكلفة إطلاقها. الحرف الأيسر من roofline أشد انحداراً على جهاز PCIe، لا ألطف.
- السقف المسطح يصبح أعلى. وحدة معالجة رسوميات لمراكز البيانات تملك FLOP/s وعرض نطاق ترددي أكثر بكثير من واحدة مدمجة، لذا فالفوز العتادي التقاربي على مسح مُشبِع أكبر من 6.2x لدينا. مكافأة الوصول إلى الجانب الأيمن من المنحنى تنمو؛ ورسم البقاء على الجانب الأيسر ينمو أيضاً.
- fp64 تعود، ومعها حيلة المجموع التراكمي. على بطاقة بدقة مزدوجة حقيقية تصبح WMA بالمجموع التراكمي بتكلفة O(n) قابلة للحياة من جديد ويمكن تشديد بوابة التطابق نحو الدقة البتية التامة. ضريبة fp32 المحددة التي دفعناها — الالتفاف المباشر بدلاً من المجاميع التراكمية، وبوابة تقيس التباعد بدلاً من assert — تفصيلة خاصة بـApple Silicon، وليست قانوناً.
لا شيء من هذا يُغيّر الأطروحة. على أي جهاز، : نفقات ثابتة عليك استهلاكها، وخط تقاربي لا تقترب منه إلا من اليمين. الثوابت عتاد؛ والمنحنى حساب. قِس و و الخاصة بك بمسح دفعات من خمسة أسطر قبل أن تثق برقم عنوان أي أحد — بما في ذلك رقمنا.
أين يتصل هذا
هذا هو القياس الرابع في سلسلة فرعية صغيرة عن المصدر الفعلي لسرعة الاختبار الرجعي، والقطع تتراكب معاً كحجة واحدة عن ما الذي يجب تحسينه قبل أن تنفق:
- سلم السرعة تسلق من pandas إلى numba المتوازية محققاً 298x على المعالج المركزي وحده، وترك وحدة معالجة الرسوميات سؤالاً مفتوحاً. هذا المقال يجيب عنه: وحدة معالجة الرسوميات درجة خامسة حقيقية لكنها مشروطة، تساوي 3.2x–6.2x فوق أعلى درجات المعالج المركزي، وفقط متى صار المسح واسعاً بما يكفي لتسلق roofline.
- ضريبة IPC قامت بنفس الحركة في الاتجاه الآخر — قياس تكلفة مغادرة العملية — ووصلت إلى استنتاج من نفس الشكل: الحد الفاصل (مقبس، أو إطلاق وحدة معالجة رسوميات) رخيص؛ الضريبة في عدد مرات عبوره ومدى ثرثرته. اجمع استدعاءات وحدة معالجة الرسوميات في دفعات لنفس السبب الذي تجمع به IPC في دفعات: لاستهلاك تكلفة ثابتة لكل عبور.
- مخبأ parquet المُجمَّع هو نسخة جانب المعالج المركزي مما يفعله الحساب المسبق على وحدة معالجة الرسوميات — احسب المؤشرات المشتركة مرة واحدة، وأعد استخدامها عبر كل توليفة. وحدة معالجة الرسوميات تأخذ فقط مبدأ إعادة-الاستخدام-والدفعات ذاك إلى السيليكون.
- وبوابة تطابق fp32 هي مشكلة تطابق الاختبار الرجعي والتداول الحي مُصغَّرة: في اللحظة التي يحسب فيها مسارك السريع شيئاً مختلفاً قليلاً عن مرجعك، تصبح مديناً بحساب كمي للتباعد، لا بتلويحة يد.
الانضباط الجامع هو نفسه الذي تدفع به هذه السلسلة كلها: قِس الشيء الذي يُباع لك فعلاً. التسريع نسبة، وللنسبة بسط ومقام. معظم خيبات الأمل مع وحدات معالجة الرسوميات تأتي من مقام — خط أساس المعالج المركزي — اختير للمجاملة، ومعظم هدر وحدات معالجة الرسوميات يأتي من تشغيل مسح أصغر من أن يغادر الحرف الأيسر من roofline.
الخلاصات
- تسريع وحدة معالجة الرسوميات منحنى، وليس رقماً. على حسابنا المسبق متعدد الأطر الزمنية امتد التقدم على المعالج المركزي من 54.5x عند توليفة واحدة لكل استدعاء إلى 359.6x عند إحدى وستين — نفس الشريحة، نفس البيانات. أي رقم منفرد هو نقطة على ذلك المنحنى؛ اسأل عند أي حجم دفعة قيس.
- استجوب خط أساس المعالج المركزي دائماً. رقم عنوان الأطر الزمنية المتعددة البالغ 167x يتحلل بنظافة إلى 27x من الخوارزمية (انهيار من-لكل-شمعة-إلى-التفاف يُسرّع المعالج المركزي بنفس القدر) مضروبة في 6.2x من العتاد الفعلي. الفوز العادل لوحدة معالجة الرسوميات على أفضل معالج مركزي هنا هو 3.2x على إطار زمني واحد و6.2x على أطر متعددة — وليس 167x.
- التقدم ينمو مع حجم المشكلة، وكذلك عامل العتاد. دفعة أكبر وعمل أغنى لكل توليفة يدفعانك أعلى في roofline: الفوز العتادي الصادق نفسه ارتفع من 3.2x إلى 6.2x فقط بجعل حمل العمل أكبر. المسوح الصغيرة تجلس يسار الحافة وبالكاد تستفيد.
- أصلح الخوارزمية واصعد سلم المعالج المركزي أولاً — فوز وحدة معالجة الرسوميات يجلس فوقهما، لا بديلاً عنهما. الـ6.2x مقيسة مقابل الخوارزمية المنهارة التي كان عليك كتابتها على أي حال. ثبّت وحدة معالجة رسوميات على خط أنابيب ساذج ومعظم ما تقيسه هو السذاجة، وليس السيليكون.
- الذهاب إلى وحدة معالجة الرسوميات يعني امتلاك قصة تطابق عددي. لا fp64 على Metal، وحيلة WMA بالمجموع التراكمي تموت عند مقياس الأسعار (خطأ نسبي ~2e2)، واستراتيجيات إشارة-التقاطع تنقلب على الشموع الحدّية. اشحن بوابة تكافؤ تُكمّم التباعد بنقاط الأساس؛ واحسب تلك التكلفة الهندسية في نقطة تعادلك.
عندما يخبرك أحدهم أن وحدة معالجة الرسوميات جعلت اختباره الرجعي أسرع مئة مرة، فهو لم يخبرك بشيء تقريباً. اسأله عن حجم الدفعة وخط أساس المعالج المركزي، وستنحل المئة عادة إلى فوز عتادي أحادي الخانة ملفوف حول فوز خوارزمي كان بإمكانه الحصول عليه مجاناً — يستحق الاقتناء، على مسح كبير بما يكفي، للأسباب التي يقولها نموذج roofline بالضبط ولا سبب واحد زيادة.
Authors
Trading-systems engineer
Trading-systems engineer building bots since 2017: cross-exchange arbitrage (connected up to 30 venues), cointegration-based pairs arbitrage across spot and futures, scalping, news and sentiment-driven strategies, trend algorithms, and portfolio management and balancing algorithms. Also builds sub-millisecond order execution, big-data warehouses, backtesting engines, AI agents, and trading interfaces (incl. open-source profitmaker.cc). Stack: JS/TS, Python, Rust/Zig/Go, DevOps, backend, frontend, architecture.