سؤال

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

أدرك أنه من المرجح أن تأتي عبر برمز Spinlock في التعليمات البرمجية "المنخفضة المستوى"، لكنني مهتم بمعرفة ما إذا كنت تجد أنه مفيد حتى نوعا أكثر راقية من البرمجة؟

هل كانت مفيدة؟

المحلول

ذلك يعتمد على ما تفعله. في رمز التطبيق عام، ستحتاج إلى تجنب SpinLocks.

في الأشياء المنخفضة المستوى حيث ستحمل فقط القفل لبضعة التعليمات، والكمون مهم، يكون حصيرة Spinlock حلا أفضل من القفل. لكن هذه الحالات نادرة، خاصة في نوع التطبيقات التي يستخدم فيها C # عادة.

نصائح أخرى

في C #، كانت "أقفال الدوران"، في تجربتي، أسوأ دائما تقريبا من أخذ قفل - إنه حدوث نادر حيث ستتفوق أقفال الدوران قفلا.

ومع ذلك، هذا ليس هو الحال دائما. .NET 4 يضيف system.threading.spinlock. هيكل. يوفر هذا فوائد في المواقف التي يحتفظ فيها القفل لفترة قصيرة للغاية، والاستيلاء عليها مرارا وتكرارا. من مستندات MSDN هياكل البيانات للبرمجة الموازية:

في السيناريوهات حيث من المتوقع أن تكون الانتظار للقفل قصيرة، تقدم SpinLock أداء أفضل من الأشكال الأخرى للقفل.

يمكن أن تتفوق أقفال الدوران على آليات قفل أخرى في الحالات التي تقوم فيها بأي شيء يشبه قفل شجرة - إذا كنت تقطع فقط على كل عقدة لفترة زمنية قصيرة للغاية، فيمكنها أن تؤدي إلى قفل تقليدي. ركضت في ذلك في محرك تقديمي مع تحديث مشهد متعدد مؤشرات الترابط، في إحدى النقاط - أقفال الدوران لم يخرج إلى التوفيق في قفل المراقب.

لعملي في الوقت الحقيقي، لا سيما مع برامج تشغيل الأجهزة، لقد استخدمتها قليلا. اتضح أن (عندما أخيرا توقيت هذا) في انتظار كائن مزامنة مثل إشارة مرتبطة بمقاطعة الأجهزة يمضغ ما لا يقل عن 20 micseconds، بغض النظر عن المدة التي تستغرقها في الواقع للحقور. فحص واحد من تسجيل الأجهزة المعين بالذاكرة، متبوعا بتحقق من RDTSC (للسماح للمهلة حتى لا تقوم بإغلاق الجهاز) في نطاق Nannosecond العالي (في الأساس أسفل الضوضاء). بالنسبة للمصافش على مستوى الأجهزة الذي لا ينبغي أن يستغرق الكثير من الوقت على الإطلاق، فمن الصعب حقا للفوز على Spinlock.

بلدي 2C: إذا كانت التحديثات الخاصة بك ترضي بعض معايير الوصول، فهي مرشحي Spinlock جيدة:

  • بسرعة, ، أي سيكون لديك وقت لاكتساب SpinLock، وأداء التحديثات وإصدار SpinLock في مؤشر ترابط واحد Quanta حتى لا يتم استباقه أثناء الضغط على Spinlock
  • موضعية جميع البيانات التي يمكنك تحديثها هي في صفحة من الواحدة التي تم تحميلها بالفعل، أنت لا تريد ملكة جمال TLB أثناء حمل SpinLock، وأنت بالتأكيد لا تريد مبادلة خطأ صفحة!
  • الذري لا تحتاج إلى أي قفل آخر لأداء العملية، أي. لا تنتظر أبدا الأقفال تحت Spinlock.

بالنسبة إلى أي شيء يحتوي على أي إمكانات للعائد، يجب عليك استخدام هيكل قفل مخطط (الأحداث، Mutex، Semaphores، إلخ).

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

بالنسبة لحالة الاستخدام العملي، غالبا ما يكون لدي صفائف من الآلاف من العناصر، حيث يمكن أن تحدث تحديثات عن عناصر مختلفة من الصفيف بأمان بالتوازي. احتمالات مؤلمين يحاولون تحديث العنصر نفسه في نفس الوقت صغير جدا (خلاف منخفض) لكنني بحاجة إلى قفل واحد لكل عنصر (سأكون لدي الكثير منهم). في هذه الحالات، عادة ما أخصيص مجموعة من الأوعية من نفس الحجم مثل الصفيف الذي أقوم بتحديثه بالتوازي وتنفيذ SpinLocks مضمنة كما (في لغة البرمجة D):

while(!atomicCasUbyte(spinLocks[i], 0, 1)) {}
    myArray[i] = newVal;
atomicSetUbyte(spinLocks[i], 0);

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

إذا كان لديك رمز أمر مهم و لقد قررت أنه يجب أن يكون أسرع مما هو حاليا و لقد قررت أن العامل الحاسم هو سرعة القفل، ثم سيكون من الجيد تجربة Spinlock. في حالات أخرى، لماذا تهتم؟ الأقفال العادية أسهل في استخدامها بشكل صحيح.

يرجى ملاحظة النقاط التالية:

  1. تدور معظم تطبيقات Mutexe لفترة قصيرة قبل أن تكون الخيط غير مجدولة بالفعل. بسبب هذا، من الصعب مقارنة أطروحات mutexes مع Spinlocks نقية.

  2. العديد من المواضيع الصاربا "بأسرع وقت ممكن" على نفس spinlock ستجري جميع النطاق الترددي ويقلل بكفاءة البرنامج بشكل كبير. تحتاج إلى إضافة وقت "النوم" الصغير عن طريق إضافة NOOP في حلقة البعد الخاصة بك.

بالكاد تحتاج إلى استخدام SpinLocks في رمز التطبيق، إذا كان يجب تجنب أي شيء.

لا أستطيع أن أستخدم أي سبب لاستخدام SpinLock في رمز C # قيد التشغيل على نظام التشغيل العادي. الأقفال المزدحمة هي في الغالب نفايات على مستوى التطبيق - يمكن أن يتسببك الغزل في استخدام وحدة المعالجة المركزية بأكملها، وسيؤدي مقابل القفل على الفور إلى تبديل سياق إذا لزم الأمر.

قد يستفيد رمز الأداء العالي حيث يكون لديك NR من المواضيع = NR من المعالجات / النوى قد يستفيد في بعض الحالات، ولكن إذا كنت بحاجة إلى تحسين الأداء في هذا المستوى الخاص بك على الأرجح لعبة 3D المقبل 3D، تعمل على نظام تشغيل مضمن بدودية مزامنة سيئة، وخلق نظام التشغيل / سائق أو في أي حال لا يستخدم C #.

استخدمت أقفال الدوران لمرحلة التوقف في العالم من جامع القمامة في بلدي hlvm المشروع لأنهم سهلون وهذا هو لعبة VM. ومع ذلك، يمكن أن تكون أقفال الدوران عكسية في هذا السياق:

واحدة من البق Perf في جامع القمامة Glasgow Haskell Compiler مزعج للغاية لدرجة أنه يحتوي على اسم "التباطؤ الأساسي الأخير.

التأثير واضح في الرسم البياني الثاني هنا ويمكن رؤيتها تؤثر على أكثر من مجرد جوهر آخر هنا, ، حيث يرى برنامج Haskell تدهور الأداء يتجاوز 5 نوى فقط.

دائما الحفاظ على هذه النقاط في عقلك أثناء استخدام Spinlocks.:

  • تنفيذ وضع المستخدم السريع.
  • مزامنة الخيوط داخل عملية واحدة، أو عمليات متعددة إذا في الذاكرة المشتركة.
  • لا يعود حتى يتم امتياز الكائن.
  • لا يدعم العودية.
  • يستهلك 100٪ من وحدة المعالجة المركزية أثناء "الانتظار".

لقد رأيت شخصيا الكثير من الجمود فقط لأن شخصا ما يعتقد أنه سيكون من الجيد استخدام SpinLock.

كن حذرا جدا أثناء استخدام Spinlocks

(لا أستطيع التأكيد على هذا بما فيه الكفاية).

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top