سؤال

لدي جهاز رباعي النواة وأرغب في كتابة بعض التعليمات البرمجية لتحليل ملف نصي يستفيد من جميع النوى الأربعة.يحتوي الملف النصي بشكل أساسي على سجل واحد لكل سطر.

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

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

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

أعلم أنه من المحتمل أن يكون هناك حل آخر أبسط من كلا الحلين ولكن في الوقت الحالي لا أرى ذلك.

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

المحلول

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

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

نصائح أخرى

إجابة مارك هي الحل الأبسط والأكثر أناقة.لماذا نبني برنامجًا معقدًا به اتصال بين الخيوط إذا لم يكن ذلك ضروريًا؟تفرخ 4 المواضيع.يحسب كل مؤشر ترابط حجم الملف/4 لتحديد نقطة البداية (ونقطة التوقف).يمكن لكل خيط بعد ذلك أن يعمل بشكل مستقل تمامًا.

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

سيؤدي هذا إلى القضاء على الاختناقات الناتجة عن وجود خيط واحد يقوم بالقراءة:

open file
for each thread n=0,1,2,3:
    seek to file offset 1/n*filesize
    scan to next complete line
    process all lines in your part of the file

تجربتي مع Java، وليس C#، لذا أعتذر إذا لم تنطبق هذه الحلول.

الحل الفوري الذي يمكنني التفكير فيه من أعلى رأسي هو أن يكون لدي منفذ يقوم بتشغيل 3 خيوط (باستخدام Executors.newFixedThreadPool, ، يقول).لكل سطر/سجل يتم قراءته من ملف الإدخال، قم بإطلاق مهمة على المنفذ (باستخدام ExecutorService.submit).سيقوم المنفذ بوضع الطلبات في قائمة الانتظار نيابةً عنك، وسيقوم بالتخصيص بين المواضيع الثلاثة.

ربما توجد حلول أفضل، ولكن نأمل أن تؤدي هذه المهمة.:-)

الوقت المتوقع للوصول:يبدو كثيرًا مثل الحل الثاني لـ Wolfbyte.:-)

إي تي إيه 2: System.Threading.ThreadPool تبدو فكرة مشابهة جدًا في .NET.لم أستخدمها أبدًا، ولكن قد يكون الأمر يستحق وقتك!

نظرًا لأن عنق الزجاجة سيكون عمومًا في المعالجة وليس في القراءة عند التعامل مع الملفات، فإنني سأختار المنتج والمستهلك نمط.لتجنب القفل سألقي نظرة على قوائم القفل المجانية.نظرًا لأنك تستخدم C#، يمكنك إلقاء نظرة على Julian Bucknall قائمة خالية من القفل شفرة.

@lomaxx

@ ديريك ومارك:أتمنى أن تكون هناك طريقة لقبول إجابتين.سأضطر في النهاية إلى استخدام حل Wolfbyte لأنه إذا قمت بتقسيم الملف إلى أقسام n، فمن المحتمل أن يأتي الخيط عبر مجموعة من المعاملات "البطيئة"، ولكن إذا كنت أقوم بمعالجة ملف حيث تكون كل عملية كان مضمونًا أنه يتطلب قدرًا متساويًا من المعالجة، فأنا حقًا أحب الحل الذي قدمته وهو تقسيم الملف إلى أجزاء وتعيين كل قطعة لسلسلة رسائل والانتهاء منها.

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

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

يمكن بعد ذلك تمرير مجموعات البيانات التي تم تحليلها مسبقًا (حيث قمت بالفعل بإجراء جميع مقارنات السلسلة و"تحويلها إلى رمز مميز") إلى جزء من التعليمات البرمجية الذي سينظر فعليًا إلى دلالات البيانات المرمزة وترتيبها.

لقد ذكرت أيضًا أنك قلق بشأن حجم ملفك الذي يشغل مساحة كبيرة من الذاكرة.هناك بعض الأشياء التي يمكنك القيام بها لتقليص ميزانية الذاكرة لديك.

قم بتقسيم الملف إلى أجزاء وتحليله.اقرأ فقط عدد القطع التي تعمل عليها في المرة الواحدة بالإضافة إلى عدد قليل من الأجزاء من أجل "القراءة للأمام" حتى لا تتوقف على القرص عند الانتهاء من معالجة قطعة قبل الانتقال إلى القطعة التالية.

وبدلاً من ذلك، يمكن تعيين الذاكرة للملفات الكبيرة وتحميلها "حسب الطلب".إذا كان لديك سلاسل رسائل تعمل على معالجة الملف أكثر من وحدات المعالجة المركزية (عادةً ما تكون سلاسل العمليات = 1.5-2X وحدة المعالجة المركزية رقمًا جيدًا لتطبيقات الترحيل عند الطلب)، فإن سلاسل الرسائل التي تتعطل عند الإدخال / الإخراج للملف المعين للذاكرة ستتوقف تلقائيًا من نظام التشغيل حتى يتم الذاكرة جاهزة وستستمر المواضيع الأخرى في المعالجة.

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