Frage

Ich habe eine Anwendung, bei der ein Bit der parallelen Verarbeitung von Nutzen sein würde. Für die Zwecke der Diskussion, sagen wir mal gibt es ein Verzeichnis mit 10 Textdateien in es, und ich möchte ein Programm starten, das abzweigt 10 Prozesse, die jeweils eine der Dateien nehmen und großgeschrieben, den Inhalt der Datei. Ich nehme zur Kenntnis, dass das übergeordnete Programm für die Kinder warten kann, um mit einem der zu vervollständigen warten Funktionen oder mit der wählen Funktion.

Was würde Ich mag es zu tun hat, den übergeordneten Prozess den Fortschritt jeden gegabelten Prozess überwachen und so etwas wie ein Fortschrittsbalken angezeigt, wie die Prozesse ausgeführt werden.

Meine Frage.

Was wäre eine vernünftige Alternativen habe ich für die gegabelten verarbeitet diese Information zurück an die Eltern zu kommunizieren? Welche IPC-Techniken wäre sinnvoll sein, zu benutzen?

War es hilfreich?

Lösung

In einer solchen Situation, wo man nur den Fortschritt überwachen möchten, ist die einfachste Alternative Shared Memory zu verwenden. Jeder Prozess aktualisiert er Wert läuft (z eine ganze Zahl) auf einem gemeinsamen Speicherblock, und der Master-Prozess liest den Block regelmäßig. Grundsätzlich Sie brauchen keine Verriegelung in diesem Schema. Außerdem ist es eine „Polling“ -Stil Anwendung, da der Master die Informationen lesen kann, wann immer er will, so dass Sie brauchen keine Ereignisverarbeitung für die Fortschrittsdatenverarbeitung.

Andere Tipps

Wenn der einzige Fortschritt, den Sie benötigen, ist „wie viele Arbeitsplätze abgeschlossen haben?“, Dann eine einfache

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);
}

tun. Für die Berichterstattung Fortschritte während, na ja, im Gange, hier ist dumm Implementierungen einige der anderen Vorschläge.

Pipes:

#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;
}

Shared Memory:

#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;
}

Fehlerbehandlung usw. elided für Klarheit.

Einige Optionen (keine Ahnung, was, wenn überhaupt, zu Ihnen passen - viel hängt davon ab, was Sie tatsächlich tun, als Channel-Operator auf die „großgeschrieben Dateien“ Analogie):

  • Signale
  • fifos / Named Pipes
  • die STDOUT der Kinder oder andere übergeben Griffe
  • Nachrichtenwarteschlangen (falls zutreffend)

Wenn alles, was Sie wollen ein Fortschritt Update ist bei weitem der einfachste Weg ist wahrscheinlich ein anonymes Rohr zu verwenden. Das Rohr (2) Aufruf gibt Ihnen zwei Dateideskriptoren, einen für jedes Ende des Rohres. Nennen Sie es, bevor Sie gerade Gabel, und haben die Eltern auf die erste fd hören und das Kind Schreiben in den zweiten. (Dies funktioniert, weil sowohl die Datei-Deskriptoren und das Array mit zwei Elementen die sie enthalten, sind zwischen den Prozessen geteilt -. Nicht gemeinsam genutzten Speicher per se, aber es ist copy-on-write, damit sie die Werte teilen, wenn Sie sie überschreiben)

Gerade heute früher jemand sagte mir, dass sie immer ein Rohr verwenden, mit denen die Kinder Mitteilung an den Elternprozess senden können, dass alles gut geht. Dies scheint eine anständige Lösung, und ist besonders nützlich in Orte, wo man einen Fehler drucken möchte, aber keinen Zugriff mehr auf stdout / stderr haben, etc.

Boost.MPI sollte in diesem Szenario nützlich sein. Sie können es übertrieben betrachten, aber es ist auf jeden Fall eine Untersuchung wert:
www.boost.org/doc/html/mpi.html

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top