سؤال

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

بعض الأسئلة:

هل هذا في الواقع يشتريني أي شيء على أجهزة الكمبيوتر المكتبية متعددة النواة القياسية - أي ، هل ستعمل المواضيع فعليًا على النوى المنفصلة إذا كان لدي JVM حاليًا ، أو هل يجب علي فعل شيء آخر؟

لدي القليل من الكائنات التي تتم قراءتها (على الرغم من عدم كتابتها أبدًا) من قبل جميع المواضيع. مشاكل محتملة مع ذلك؟ حلول لتلك المشاكل؟

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

المكافأة: يتكون معظم التقييم من مقارنات محددة (على سبيل المثال ، الاتحاد ، التقاطع ، مع) مع بعض الخرائط من مفاتيح للحصول على مجموعات ذات صلة. لديّ بعض الخبرة المحدودة مع فورتران و C و C ++ (فصل دراسي من الحوسبة العلمية للفصول الأولى ، و HS AP منذ 10 سنوات للآخران) - ما هو نوع السرعة/سهولة مكاسب التوازي التي قد أجدها إذا قمت بربط بلدي Java في الواجهة الأمامية لخوارزمية خلفية في إحدى هذه اللغات ، وما نوع الصداع الذي قد يجد مستوى خبرتي في تنفيذ تلك العمليات في تلك اللغات؟

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

المحلول

  • نعم ، سيستخدم استخدام مؤشرات الترابط المستقلة نوى متعددة في JVM العادي ، دون الحاجة إلى القيام بأي عمل.

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

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

نصائح أخرى

استخدام متعدد النواة

تقوم Java Runtimes بجدولة المواضيع التقليدية لتشغيلها بشكل متزامن على جميع المعالجات والرسم المتاحة. أعتقد أنه من الممكن تقييد هذا ، لكن الأمر سيستغرق عملًا إضافيًا ؛ بشكل افتراضي ، لا يوجد تقييد.

الأشياء غير القابلة للتغيير

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

يجب الإعلان عن أي حقول قابلة للتغيير يتم الوصول إليها بواسطة مؤشرات ترابط متعددة volatile, ، تكون محمية عن طريق التزامن ، أو استخدم بعض آلية التزامن الأخرى لضمان أن التغييرات متسقة ومرئية بين الخيوط.

الحوسبة الموزعة

يسمى الإطار الأكثر استخدامًا للمعالجة الموزعة من هذا النوع في Java هادوب. يستخدم نموذجا يسمى حديد الخريطة.

تكامل الكود الأصلي

من غير المرجح أن يكون الاندماج مع اللغات الأخرى جديرة بالاهتمام. نظرًا لمجمول المترجمة التكيفية من رمز Bytecode إلى أصلي ، فإن Java سريع جدًا بالفعل على مجموعة واسعة من مهام الحوسبة. سيكون من الخطأ افتراض أن لغة أخرى أسرع بدون اختبار فعلي. أيضًا ، فإن الاندماج مع الكود "الأصلي" باستخدام JNI مملة للغاية ، معرضة للخطأ ، ومعقدة ؛ يعد استخدام واجهات أبسط مثل JNA بطيئة جدًا وسيحو بسرعة أي مكاسب في الأداء.

كما قال بعض الناس ، الإجابات هي:

  1. المواضيع على النوى - نعم. حصلت Java على دعم للخيوط الأصلية لفترة طويلة. قدمت معظم OPS مواضيع kernel التي يتم جدولة تلقائيًا إلى أي وحدة المعالجة المركزية لديك (قد يختلف أداء التنفيذ حسب نظام التشغيل).

  2. الإجابة البسيطة هي أنها ستكون آمنة بشكل عام. الإجابة الأكثر تعقيدًا هي أنه يتعين عليك التأكد من إنشاء كائنك وتهيئته بالفعل قبل أن تتمكن أي مؤشرات ترابط. تم حل هذا واحدة من طريقتين:

    • اسمح لوكيل الفصل بحل المشكلة بالنسبة لك باستخدام Singleton (وتحميل فئة كسول):

      public class MyImmutableObject
      {
          private static class MyImmutableObjectInstance {
              private static final MyImmutableObject instance = new MyImmutableObject();
          }
          public MyImmutableObject getInstance() {
              return MyImmutableObjectInstance.instance;
          }
      }
      
    • باستخدام دلالات الحصول على/إطلاقها بشكل صريح لضمان نموذج ذاكرة ثابت:

      MyImmutableObject foo = null;
      volatile bool objectReady = false;
      
      // initializer thread:
      ....
      /// create & initialize object for use by multiple threads
      foo = new MyImmutableObject();
      foo.initialize();
      
      // release barrier
      objectReady = true;
      
      // start worker threads
      public void run() {
         // acquire barrier
         if (!objectReady)
             throw new IllegalStateException("Memory model violation");
      
         // start using immutable object foo
      }
      

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

  3. كما ذكرنا ، هناك كل أنواع آليات RPC. هناك أيضًا RMI وهو نهج أصلي لتشغيل التعليمات البرمجية على الأهداف البعيدة. هناك أيضًا أطر عمل مثل Hadoop التي توفر حلًا أكثر اكتمالًا قد يكون أكثر ملاءمة.

  4. لاتصال الكود الأصلي ، إنه قبيح إلى حد ما - حيث لا تشجع Sun حقًا الاستخدام عن طريق جعل JNI فوضى معقدة قبيحة ، لكنها ممكنة. أعلم أنه كان هناك إطار عمل تجاري واحد على الأقل لتحميل وتنفيذ المكتبات الديناميكية الأصلية دون الحاجة إلى القلق بشأن JNI (لست متأكدًا مما إذا كانت هناك أي مشاريع مجانية أو OSS).

حظا طيبا وفقك الله.

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