سؤال

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

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

سؤالي.

ماذا سيكون بدائل معقولة هل يجب على متشعب عمليات التواصل هذه المعلومات مرة أخرى إلى الوالدين ؟ ما IPC التقنيات ستكون معقولة للاستخدام ؟

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

المحلول

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

نصائح أخرى

إذا كان التقدم الوحيد الذي تحتاجه هو "كيف العديد من الوظائف لديها الانتهاء؟", ثم بسيط

while (jobs_running) {
    pid = wait(&status);
    for (i = 0; i < num_jobs; i++)
        if (pid == jobs[i]) {
            jobs_running--;
            break;
        }
    printf("%i/%i\n", num_jobs - jobs_running, num_jobs);
}

وسوف نفعل.للإبلاغ عن التقدم المحرز في حين في التقدم ، وهنا البكم تطبيقات بعض الاقتراحات الأخرى.

الأنابيب:

#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>

int child(int fd) {
    int i;
    struct timespec ts;
    for (i = 0; i < 100; i++) {
        write(fd, &i, sizeof(i));
        ts.tv_sec = 0;
        ts.tv_nsec = rand() % 512 * 1000000;
        nanosleep(&ts, NULL);
    }
    write(fd, &i, sizeof(i));
    exit(0);
}

int main() {
    int fds[10][2];
    int i, j, total, status[10] = {0};
    for (i = 0; i < 10; i++) {
        pipe(fds[i]);
        if (!fork())
            child(fds[i][1]);
    }
    for (total = 0; total < 1000; sleep(1)) {
        for (i = 0; i < 10; i++) {
            struct pollfd pfds = {fds[i][0], POLLIN};
            for (poll(&pfds, 1, 0); pfds.revents & POLLIN; poll(&pfds, 1, 0)) {
                read(fds[i][0], &status[i], sizeof(status[i]));
                for (total = j = 0; j < 10; j++)
                    total += status[j];
            }
        }
        printf("%i/1000\n", total);
    }
    return 0;
}

الذاكرة المشتركة:

#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <time.h>
#include <unistd.h>

int child(int *o, sem_t *sem) {
    int i;
    struct timespec ts;
    for (i = 0; i < 100; i++) {
        sem_wait(sem);
        *o = i;
        sem_post(sem);
        ts.tv_sec = 0;
        ts.tv_nsec = rand() % 512 * 1000000;
        nanosleep(&ts, NULL);
    }
    sem_wait(sem);
    *o = i;
    sem_post(sem);
    exit(0);
}

int main() {
    int i, j, size, total;
    void *page;
    int *status;
    sem_t *sems;
    size = sysconf(_SC_PAGESIZE);
    size = (10 * sizeof(*status) + 10 * sizeof(*sems) + size - 1) & size;
    page = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
    status = page;
    sems = (void *)&status[10];
    for (i = 0; i < 10; i++) {
        status[i] = 0;
        sem_init(&sems[i], 1, 1);
        if (!fork())
            child(&status[i], &sems[i]);
    }
    for (total = 0; total < 1000; sleep(1)) {
        for (total = i = 0; i < 10; i++) {
            sem_wait(&sems[i]);
            total += status[i];
            sem_post(&sems[i]);
        }
        printf("%i/1000\n", total);
    }
    return 0;
}

معالجة الخطأ.... الخحذفه من أجل الوضوح.

عدد قليل من الخيارات (أي الفكرة التي تناسبك--الكثير يعتمد على ما تقومون به فعلا ، opped إلى "uppercasing الملفات" القياس):

  • إشارات
  • fifos / أنابيب الاتصال المسماة
  • من STDOUT الأطفال أو غيرها مرت مقابض
  • رسالة طوابير (إذا كان ذلك مناسبا)

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

فقط في وقت سابق من اليوم قال لي أحدهم أنهم دائما استخدام الأنابيب التي يمكن للأطفال إرسال الإخطار إلى عملية الأصل أن كل شيء يسير على ما يرام.هذا يبدو الكريم الحل هو مفيدة بشكل خاص في الأماكن التي قد ترغب في طباعة خطأ ، ولكن لم يعد لدينا إمكانية الوصول إلى المعياري/stderr, الخ.

دفعة.MPI ينبغي أن تكون مفيدة في هذا السيناريو.قد تفكر في الأمر مبالغة لكنه بالتأكيد يستحق التحقيق:
www.boost.org/doc/html/mpi.html

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