وقت النوم الأمثل في نموذج متعدد المنتجين / مستهلك واحد

StackOverflow https://stackoverflow.com/questions/1400605

  •  05-07-2019
  •  | 
  •  

سؤال

أنا أكتب تطبيقًا يحتوي على منتج متعدد ونموذج مستهلك واحد (ترسل سلاسل رسائل متعددة رسائل إلى سلسلة كاتب ملف واحد).

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

في حلقة ترابط المستهلك، فإنه ينام لفترة محددة من الوقت بعد معالجة كافة سلاسل العمليات المنتجة.أحد الأشياء التي لاحظتها على الفور هو أن متوسط ​​الوقت الذي يستغرقه المنتج لكتابة شيء ما في قائمة الانتظار والعودة إليه قد زاد بشكل كبير (بمقدار 5x) عندما انتقلت من موضوع منتج واحد إلى موضوعين.ومع إضافة المزيد من المواضيع، يقل متوسط ​​الوقت حتى يصل إلى القاع - لا يوجد فرق كبير بين الوقت المستغرق مع 10 منتجين مقابل 15 منتجًا.من المفترض أن يرجع ذلك إلى أنه مع وجود عدد أكبر من المنتجين الذين تتم معالجتهم، يكون هناك تنافس أقل على كائن المزامنة (mutex) الخاص بمؤشر ترابط المنتج.

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

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

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

المحلول

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

وفي كلتا الحالتين أنت تتجاهل قضية أكثر جوهرية.من السهل إجراء عملية النوم والاقتراع بشكل صحيح، وفي بعض الأحيان يكون هذا هو النهج الوحيد المتاح، ولكن له العديد من العيوب وليس الطريقة "الصحيحة".

يمكنك التوجه في الاتجاه الصحيح عن طريق إضافة إشارة تتزايد عندما يضيف المنتج عنصرًا إلى قائمة الانتظار ويتناقص عندما يقوم المستهلك بمعالجة عنصر في قائمة الانتظار.لن يستيقظ المستهلك إلا عندما تكون هناك عناصر يجب معالجتها وسيقوم بذلك على الفور.

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

نصائح أخرى

بدلاً من النوم، أوصي بأن يحظر المستهلك الخاص بك بشرط يشير إليه المنتجون.في نظام متوافق مع posix، يمكنك جعله يعمل مع pthread_cond.إنشاء مجموعة من pthread_cond_t, ، واحدة لكل منتج، ثم قم بإنشاء واحدة إضافية مشتركة بينهما.يشير المنتجون أولاً إلى متغير الحالة الفردي الخاص بهم، ثم المتغير المشترك.ينتظر المستهلك الشرط المشترك ثم يكرره على عناصر المصفوفة، وينفذ pthread_cond_timed_wait() على كل عنصر من عناصر المصفوفة (use pthread_get_expiration_np() للحصول على الوقت المطلق لـ "الآن").إذا أعاد الانتظار 0، فهذا يعني أن المنتج قد كتب البيانات.يجب على المستهلك إعادة تهيئة متغيرات الحالة قبل الانتظار مرة أخرى.

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

حاول العثور على تطبيق لقائمة انتظار الحظر باللغة التي تستخدمها للبرمجة.لن يكون هناك أكثر من قائمة انتظار واحدة كافية لأي عدد من المنتجين ومستهلك واحد.

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

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

هل يمكنك إظهار بعض التعليمات البرمجية؟

يحرر:ربما تقوم بأخذ قفلك وتبديل قوائم الانتظار حتى في حالة عدم وجود عمل للقيام به؟

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