문제

약간의 병렬 처리가 도움이되는 응용 프로그램이 있습니다. 토론의 목적으로 10 개의 텍스트 파일이있는 디렉토리가 있고 프로그램을 시작하고 싶다고 가정 해 봅시다. 프로그램을 시작하고 싶습니다. 각각 10 개의 프로세스를 포크하고 각각 파일 중 하나를 취하고 파일의 내용을 어퍼 케이싱합니다. 나는 부모 프로그램이 아이들이 기다리다 함수 또는 사용 고르다 기능.

내가하고 싶은 것은 부모 프로세스가 각 포크 프로세스의 진행 상황을 모니터링하고 프로세스가 실행될 때 진행률 표시 줄과 같은 것을 표시하는 것입니다.

내 질문.

포크 프로세스 가이 정보를 부모에게 다시 전달하기위한 합리적인 대안은 무엇입니까? 어떤 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;
}

명확성을 위해 오류 처리 등.

몇 가지 옵션 (어떤 경우, 어떤 것이라도 당신에게 적합 할 것인지는 알지 못합니다. 많은 것은 당신이 실제로하고있는 일에 의존합니다.

  • 신호
  • FIFOS / 명명 된 파이프
  • 어린이 또는 기타 통과 된 핸들의 성병
  • 메시지 대기열 (적절한 경우)

당신이 원하는 모든 것이 진행 상황 업데이트 만 있으면, 가장 쉬운 방법은 아마도 익명 파이프를 사용하는 것입니다. 파이프 (2) 호출은 파이프의 각 끝마다 하나의 파일 설명자를 제공합니다. 포크 직전에 전화를 걸어 부모가 첫 번째 FD를 듣고 아이가 두 번째로 글을 쓰게하십시오. (파일 디스크립터와 이들이 포함 된 2 요소 배열이 모두 공유 메모리 자체가 아닌 프로세스간에 공유되기 때문에 작동하지만 복사 된 쓰기이므로 값을 덮어 쓰지 않으면 값을 공유하기 때문에 작동합니다.)

오늘 일찍 누군가 누군가가 항상 파이프를 사용한다고 말했습니다.이를 통해 아이들은 모든 것이 잘 진행되고 있다는 부모 과정에 알림을 보낼 수 있습니다. 이것은 괜찮은 해결책으로 보이며 오류를 인쇄하려는 장소에서 특히 유용하지만 더 이상 stdout/stderr 등에 액세스 할 수 없습니다.

boost.mpi 이 시나리오에서 유용해야합니다. 과잉을 고려할 수도 있지만 확실히 조사 할 가치가 있습니다.
www.boost.org/doc/html/mpi.html

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top